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_invocation_stat.d -c "java ..." 39 * 2. method_invocation_stat.d -p JAVA_PID 40 * 41 * This script collects statistics about Java method invocations. 42 * 43 * Notes: 44 * - These probes are disabled by default since it incurs performance 45 * overhead to the application. To trace the method-entry and 46 * method-exit probes, you need to turn on the ExtendedDTraceProbes VM 47 * option. 48 * You can either start the application with -XX:+ExtendedDTraceProbes 49 * option or use the jinfo command to enable it at runtime as follows: 50 * 51 * jinfo -flag +ExtendedDTraceProbes <java_pid> 52 * 53 */ 54 55 #pragma D option quiet 56 #pragma D option destructive 57 #pragma D option defaultargs 58 #pragma D option bufsize=16m 59 #pragma D option aggrate=100ms 60 61 62 self char *str_ptr; 63 self string class_name; 64 self string method_name; 65 self string signature; 66 self string package_name; 67 self string last_class_name; 68 69 long long JAVA_CALLS; 70 long long JNI_CALLS; 71 long long SYS_CALLS; 72 73 int SYS_DEEP; 74 long long LAST_SYS_TS; 75 76 long long START_TIME; 77 long long JAVA_TIME; 78 long long RUN_TIME; 79 long long SYS_TIME; 80 81 BEGIN 82 { 83 SAMPLE_NAME = "hotspot method invocation tracing"; 84 85 START_TIME = timestamp; 86 SYS_TIME = 0; 87 88 printf("BEGIN %s\n\n", SAMPLE_NAME); 89 } 90 91 /* 92 * hotspot:::method-entry, hotspot:::method-return 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 method being entered 96 * arg2: uintptr_t, the length of the class name (in bytes) 97 * arg3: char*, a pointer to mUTF-8 string data which contains the 98 * name of the method being entered 99 * arg4: uintptr_t, the length of the method name (in bytes) 100 * arg5: char*, a pointer to mUTF-8 string data which contains the 101 * signature of the method being entered 102 * arg6: uintptr_t, the length of the signature(in bytes) 103 */ 104 hotspot$target:::method-entry 105 { 106 self->str_ptr = (char*) copyin(arg1, arg2+1); 107 self->str_ptr[arg2] = '\0'; 108 self->class_name = (string) self->str_ptr; 109 110 self->str_ptr = (char*) copyin(arg3, arg4+1); 111 self->str_ptr[arg4] = '\0'; 112 self->method_name = (string) self->str_ptr; 113 114 self->str_ptr = (char*) copyin(arg5, arg6+1); 115 self->str_ptr[arg6] = '\0'; 116 self->signature = (string) self->str_ptr; 117 118 119 self->package_name = dirname(self->class_name); 120 121 JAVA_CALLS ++; 122 @method_calls[self->class_name, 123 self->method_name, self->signature] = count(); 124 @class_calls[self->class_name] = count(); 125 @package_calls[self->package_name] = count(); 126 } 127 128 129 hotspot_jni$target:::*-entry 130 { 131 JNI_CALLS ++; 132 133 @jni_calls[probename] = count(); 134 } 135 136 syscall:::entry 137 /pid == $target && SYS_DEEP == 0/ 138 { 139 LAST_SYS_TS = timestamp; 140 } 141 142 syscall:::entry 143 /pid == $target/ 144 { 145 SYS_DEEP ++; 146 @sys_calls[probefunc] = count(); 147 SYS_CALLS ++; 148 } 149 150 syscall:::return 151 /pid == $target/ 152 { 153 SYS_DEEP --; 154 } 155 156 syscall:::return 157 /pid == $target && SYS_DEEP == 0/ 158 { 159 SYS_TIME += (timestamp - LAST_SYS_TS); 160 } 161 162 163 :::END 164 { 165 RUN_TIME = (timestamp - START_TIME); 166 JAVA_TIME = (RUN_TIME - SYS_TIME); 167 168 printf("System calls:\n"); 169 printa("%10@d %s\n", @sys_calls); 170 printf("\n"); 171 172 printf("JNI calls:\n"); 173 printa("%10@d %s\n", @jni_calls); 174 printf("\n"); 175 176 printf("Top packages calls:\n"); 177 printa("%10@d %s\n", @package_calls); 178 printf("\n"); 179 180 printf("Top class calls:\n"); 181 printa("%10@d %s\n", @class_calls); 182 printf("\n"); 183 184 printf("Top method calls:\n"); 185 printa("%10@d %s:%s:%s\n", @method_calls); 186 printf("\n"); 187 188 printf("=======================================\n"); 189 printf("JAVA_CALLS: %10d\n", JAVA_CALLS); 190 printf(" JNI_CALLS: %10d\n", JNI_CALLS); 191 printf(" SYS_CALLS: %10d\n", SYS_CALLS); 192 printf("\n"); 193 194 printf("Run time: %15d\n", RUN_TIME); 195 printf("Syscall time: %15d\n", SYS_TIME); 196 printf("Java+JNI time: %15d\n", JAVA_TIME); 197 printf("\n"); 198 } 199 200 :::END 201 { 202 printf("\nEND %s\n", SAMPLE_NAME); 203 } 204 205 syscall::rexit:entry, 206 syscall::exit:entry 207 /pid == $target/ 208 { 209 exit(0); 210 } 211