1 #!/usr/sbin/dtrace -Zs
2 /*
3  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  *   - Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *
12  *   - Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  *
16  *   - Neither the name of Oracle nor the names of its
17  *     contributors may be used to endorse or promote products derived
18  *     from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34 */
35 
36 /*
37  * Usage:
38  *   1. method_compile_stat.d -c "java ..." TOP_RESULTS_COUNT INTERVAL_SECS
39  *   2. method_compile_stat.d -p JAVA_PID TOP_RESULTS_COUNT INTERVAL_SECS
40  *
41  * This script prints statistics about TOP_RESULTS_COUNT (default is 25)
42  * methods with largest/smallest compilation time every INTERVAL_SECS
43  * (default is 60) seconds.
44  *
45  */
46 
47 #pragma D option quiet
48 #pragma D option destructive
49 #pragma D option defaultargs
50 #pragma D option aggrate=100ms
51 
52 
53 self char *str_ptr;
54 self string class_name;
55 self string method_name;
56 self string signature;
57 
58 int INTERVAL_SECS;
59 
60 :::BEGIN
61 {
62     SAMPLE_NAME = "hotspot methods compilation tracing";
63 
64     TOP_RESULTS_COUNT = $1 ? $1 : 25;
65     INTERVAL_SECS = $2 ? $2 : 60;
66 
67     COMPILED_METHODS_COUNT = 0;
68     LOADED_METHODS_CNT = 0;
69     UNLOADED_METHODS_CNT = 0;
70 
71     SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
72 
73     LINE_SEP =
74     "------------------------------------------------------------------------";
75 
76     printf("BEGIN %s\n\n", SAMPLE_NAME);
77 }
78 
79 /*
80  * hotspot:::method-compile-begin
81  *  arg0: char*,        a pointer to mUTF-8 string containing the name of
82  *                          the compiler
83  *  arg1: uintptr_t,    the length of the compiler name (in bytes)
84  *  arg2: char*,        a pointer to mUTF-8 string containing the class name of
85  *                          the method being compiled
86  *  arg3: uintptr_t,    the length of the class name (in bytes)
87  *  arg4: char*,        a pointer to mUTF-8 string containing the method name of
88  *                          the method being compiled
89  *  arg5: uintptr_t,    the length of the method name (in bytes)
90  *  arg6: char*,        a pointer to mUTF-8 string containing the signature of
91  *                          the method being compiled
92  *  arg7: uintptr_t,    the length of the signature(in bytes)
93  */
94 hotspot$target:::method-compile-begin
95 {
96     /*compiler_name, len, class_name, len, method_name, len, signature, len*/
97 
98     self->str_ptr = (char*) copyin(arg0, arg1+1);
99     self->str_ptr[arg1] = '\0';
100     compiler_name = (string) self->str_ptr;
101 
102     self->str_ptr = (char*) copyin(arg2, arg3+1);
103     self->str_ptr[arg3] = '\0';
104     self->class_name = (string) self->str_ptr;
105 
106     self->str_ptr = (char*) copyin(arg4, arg5+1);
107     self->str_ptr[arg5] = '\0';
108     self->method_name = (string) self->str_ptr;
109 
110     self->str_ptr = (char*) copyin(arg6, arg7+1);
111     self->str_ptr[arg7] = '\0';
112     self->signature = (string) self->str_ptr;
113 
114     self->ts[self->class_name, self->method_name, self->signature] = timestamp;
115 }
116 
117 /*
118  * hotspot:::method-compile-end
119  *  arg0: char*,        a pointer to mUTF-8 string containing the name of
120  *                          the compiler
121  *  arg1: uintptr_t,    the length of the compiler name (in bytes)
122  *  arg2: char*,        a pointer to mUTF-8 string containing the class name of
123  *                          the method being compiled
124  *  arg3: uintptr_t,    the length of the class name (in bytes)
125  *  arg4: char*,        a pointer to mUTF-8 string containing the method name of
126  *                          the method being compiled
127  *  arg5: uintptr_t,    the length of the method name (in bytes)
128  *  arg6: char*,        a pointer to mUTF-8 string containing the signature of
129  *                          the method being compiled
130  *  arg7: uintptr_t,    the length of the signature(in bytes)
131  *  arg8: uintptr_t,    boolean value which indicates if method
132  *                          has been compiled successfuly
133  */
134 hotspot$target:::method-compile-end
135 {
136     /* compiler_name, len, class_name, len, method_name, len,
137        signature, len, isSuccess */
138 
139     self->str_ptr = (char*) copyin(arg0, arg1+1);
140     self->str_ptr[arg1] = '\0';
141     compiler_name = (string) self->str_ptr;
142 
143     self->str_ptr = (char*) copyin(arg2, arg3+1);
144     self->str_ptr[arg3] = '\0';
145     self->class_name = (string) self->str_ptr;
146 
147     self->str_ptr = (char*) copyin(arg4, arg5+1);
148     self->str_ptr[arg5] = '\0';
149     self->method_name = (string) self->str_ptr;
150 
151     self->str_ptr = (char*) copyin(arg6, arg7+1);
152     self->str_ptr[arg7] = '\0';
153     self->signature = (string) self->str_ptr;
154 }
155 
156 /*
157  * Method was successfuly compiled
158  */
159 hotspot$target:::method-compile-end
160 /arg8 && self->ts[self->class_name, self->method_name, self->signature]/
161 {
162     /* compiler_name, len, class_name, len, method_name, len,
163        signature, len, isSuccess */
164 
165     COMPILED_METHODS_COUNT++;
166 
167     @compile_time_top[self->class_name, self->method_name, self->signature] =
168      avg((timestamp -
169       self->ts[self->class_name, self->method_name, self->signature]) / 1000);
170 
171     @compile_time_last[self->class_name, self->method_name, self->signature] =
172      avg((timestamp -
173       self->ts[self->class_name, self->method_name, self->signature]) / 1000);
174 
175     self->ts[self->class_name, self->method_name, self->signature] = 0;
176 }
177 
178 /*
179  * Method compilation was failed
180  */
181 hotspot$target:::method-compile-end
182 /arg8 != 1 && self->ts[self->class_name, self->method_name, self->signature]/
183 {
184     /* compiler_name, len, class_name, len, method_name, len,
185        signature, len, isSuccess */
186 
187     @fail_compile_count[self->class_name,
188                         self->method_name, self->signature] = count();
189 }
190 
191 hotspot$target:::compiled-method-load
192 {
193     /* class_name, len, method_name, len, signature, len, code_address, size */
194 
195     LOADED_METHODS_CNT ++;
196 }
197 
198 hotspot$target:::compiled-method-unload
199 {
200     /* class_name, len, method_name, len, signature, len, code_address, size */
201 
202     UNLOADED_METHODS_CNT ++;
203 }
204 
205 
206 tick-1sec
207 /timestamp > SAMPLING_TIME/
208 {
209     trunc(@compile_time_top, TOP_RESULTS_COUNT);
210     trunc(@compile_time_last, -TOP_RESULTS_COUNT);
211 
212     printf("\n");
213     printf("%s\n", LINE_SEP);
214     printf("%Y\n", walltimestamp);
215     printf("%s\n", LINE_SEP);
216 
217     printf(
218         "\nTop %d methods with largest compilation time (in milleseconds):\n",
219         TOP_RESULTS_COUNT);
220     printa("%10@d %s::%s%s\n", @compile_time_top);
221 
222     printf(
223         "\nTop %d methods with smallest compilation time (in milleseconds):\n",
224         TOP_RESULTS_COUNT);
225     printa("%10@d %s::%s%s\n", @compile_time_last);
226 
227     printf("\n");
228     printf("Compiled methods:         %10d\n", COMPILED_METHODS_COUNT);
229     printf("Loaded compiled methods:  %10d\n", LOADED_METHODS_CNT);
230     printf("Unoaded compiled methods: %10d\n", UNLOADED_METHODS_CNT);
231 
232     printf("\nFailed compilation:\n");
233     printa("%10@d %s::%s%s\n", @fail_compile_count);
234 
235     SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
236 }
237 
238 :::END
239 {
240     trunc(@compile_time_top, TOP_RESULTS_COUNT);
241     trunc(@compile_time_last, -TOP_RESULTS_COUNT);
242 
243     printf("\n");
244     printf("%s\n", LINE_SEP);
245     printf("%Y\n", walltimestamp);
246     printf("%s\n", LINE_SEP);
247 
248     printf(
249         "\nTop %d methods with largest compilation time (in milleseconds):\n",
250         TOP_RESULTS_COUNT);
251     printa("%10@d %s::%s%s\n", @compile_time_top);
252 
253     printf(
254         "\nTop %d methods with smallest compilation time (in milleseconds):\n",
255         TOP_RESULTS_COUNT);
256     printa("%10@d %s::%s%s\n", @compile_time_last);
257 
258     printf("\n");
259     printf("Compiled methods:         %10d\n", COMPILED_METHODS_COUNT);
260     printf("Loaded compiled methods:  %10d\n", LOADED_METHODS_CNT);
261     printf("Unoaded compiled methods: %10d\n", UNLOADED_METHODS_CNT);
262 
263     printf("\nFailed compilations:\n");
264     printa("%10@d %s::%s%s\n", @fail_compile_count);
265 
266     printf("\nEND of %s\n", SAMPLE_NAME);
267 }
268 
269 syscall::rexit:entry,
270 syscall::exit:entry
271 /pid == $target/
272 {
273    exit(0);
274 }
275