Home | History | Annotate | Download | only in hotspot
      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