1 #!/usr/sbin/dtrace -Zs
2 
3 /*
4  * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *   - Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  *
13  *   - Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  *
17  *   - Neither the name of Oracle nor the names of its
18  *     contributors may be used to endorse or promote products derived
19  *     from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35 */
36 
37 /*
38  * Usage:
39  *    1. object_allocation_stat.d -c "java ..." TOP_RESULTS_COUNT INTERVAL_SECS
40  *    2. object_allocation_stat.d -p JAVA_PID TOP_RESULTS_COUNT INTERVAL_SECS
41  *
42  * This script collects statistics about TOP_RESULTS_COUNT (default is 25)
43  * object allocations every INTERVAL_SECS (default is 60) seconds.
44  *
45  * The results are displayed in ascending order which means that the highest
46  * allocated type is listed last. The script can be improved to sort the
47  * results in reverse order when DTrace supports it.
48  *
49  * Notes:
50  *  - The object-alloc probe is disabled by default since it incurs
51  *    performance overhead to the application. To trace object-alloc probe,
52  *    you need to turn on the ExtendedDTraceProbes VM option.
53  *    You can either start the application with -XX:+ExtendedDTraceProbes
54  *    option or use the jinfo command to enable it at runtime as follows:
55  *
56  *       jinfo -flag +ExtendedDTraceProbes <java_pid>
57  *
58  */
59 
60 #pragma D option quiet
61 #pragma D option destructive
62 #pragma D option defaultargs
63 #pragma D option bufsize=16m
64 #pragma D option aggrate=100ms
65 
66 
67 self char *str_ptr;
68 self string class_name;
69 
70 long long ALLOCATED_OBJECTS_CNT;
71 
72 int INTERVAL_SECS;
73 
74 :::BEGIN
75 {
76     SAMPLE_NAME = "hotspot object allocation tracing";
77 
78     TOP_RESULTS_COUNT = $1 ? $1 : 25;
79     INTERVAL_SECS = $2 ? $2 : 60;
80 
81     ALLOCATED_OBJECTS_CNT = 0;
82 
83     SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
84 
85     LINE_SEP =
86     "------------------------------------------------------------------------";
87 
88     printf("BEGIN %s\n\n", SAMPLE_NAME);
89 }
90 
91 /*
92  * hotspot:::object-alloc probe arguments:
93  *  arg0: uintptr_t,    Java thread id
94  *  arg1: char*,        a pointer to mUTF-8 string containing the name of
95  *                          the class of the object being allocated
96  *  arg2: uintptr_t,    the length of the class name (in bytes)
97  *  arg3: uintptr_t,    the size of the object being allocated
98  */
99 hotspot$target:::object-alloc
100 {
101     ALLOCATED_OBJECTS_CNT ++;
102 
103     self->str_ptr = (char*) copyin(arg1, arg2+1);
104     self->str_ptr[arg2] = '\0';
105     self->class_name = (string) self->str_ptr;
106 
107 
108     @allocs_count[self->class_name] = count();
109     @allocs_size[self->class_name] = sum(arg3);
110 }
111 
112 tick-1sec
113 /timestamp > SAMPLING_TIME/
114 {
115     printf("\n");
116     printf("%s\n", LINE_SEP);
117     printf("%Y\n", walltimestamp);
118     printf("%s\n", LINE_SEP);
119 
120     printf("\n");
121     printf("Top %d allocations by size:\n", TOP_RESULTS_COUNT);
122     trunc(@allocs_size, TOP_RESULTS_COUNT);
123     printa("%10@d %s\n", @allocs_size);
124 
125     printf("\n");
126     printf("Top %d allocations by count:\n", TOP_RESULTS_COUNT);
127     trunc(@allocs_count, TOP_RESULTS_COUNT);
128     printa("%10@d %s\n", @allocs_count);
129 
130     printf("\nTotal number of allocated objects: %d\n", ALLOCATED_OBJECTS_CNT);
131 
132     SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
133 }
134 
135 :::END
136 {
137     printf("\n");
138     printf("%s\n", LINE_SEP);
139     printf("%Y\n", walltimestamp);
140     printf("%s\n", LINE_SEP);
141 
142     printf("\n");
143     printf("Top %d allocations by size:\n", TOP_RESULTS_COUNT);
144     trunc(@allocs_size, TOP_RESULTS_COUNT);
145     printa("%10@d %s\n", @allocs_size);
146 
147     printf("\n");
148     printf("Top %d allocations by count:\n", TOP_RESULTS_COUNT);
149     trunc(@allocs_count, TOP_RESULTS_COUNT);
150     printa("%10@d %s\n", @allocs_count);
151 
152     printf("\nTotal number of allocated objects: %d\n", ALLOCATED_OBJECTS_CNT);
153 
154     printf("\nEND of %s\n", SAMPLE_NAME);
155 }
156 
157 syscall::rexit:entry,
158 syscall::exit:entry
159 /pid == $target/
160 {
161    exit(0);
162 }
163