0N/A#!/usr/sbin/dtrace -Zs
0N/A/*
2362N/A * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
0N/A *
0N/A * Redistribution and use in source and binary forms, with or without
0N/A * modification, are permitted provided that the following conditions
0N/A * are met:
0N/A *
0N/A * - Redistributions of source code must retain the above copyright
0N/A * notice, this list of conditions and the following disclaimer.
0N/A *
0N/A * - Redistributions in binary form must reproduce the above copyright
0N/A * notice, this list of conditions and the following disclaimer in the
0N/A * documentation and/or other materials provided with the distribution.
0N/A *
2362N/A * - Neither the name of Oracle nor the names of its
0N/A * contributors may be used to endorse or promote products derived
0N/A * from this software without specific prior written permission.
0N/A *
0N/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
0N/A * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
0N/A * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
0N/A * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
0N/A * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0N/A * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
0N/A * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
0N/A * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0N/A * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0N/A * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0N/A * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0N/A */
0N/A
0N/A/*
0N/A*/
0N/A
0N/A/*
0N/A * Usage:
0N/A * 1. gc_time_stat.d -c "java ..." INTERVAL_SECS
0N/A * 2. gc_time_stat.d -p JAVA_PID INTERVAL_SECS
0N/A *
0N/A * This script measures the duration of a time spent in GC. The duration is
0N/A * measured for every memory pool every INTERVAL_SECS seconds. If
0N/A * INTERVAL_SECS is not set then 10 seconds interval is used.
0N/A *
0N/A */
0N/A
0N/A#pragma D option quiet
0N/A#pragma D option destructive
0N/A#pragma D option defaultargs
0N/A#pragma D option aggrate=100ms
0N/A
0N/A
0N/Astring TEST_NAME;
0N/Aself char *str_ptr;
0N/Aself string mgr_name;
0N/Aself string pool_name;
0N/A
0N/Aint INTERVAL_SECS;
0N/A
0N/A:::BEGIN
0N/A{
0N/A SAMPLE_NAME = "hotspot GC tracing";
0N/A
0N/A START_TIME = timestamp;
0N/A gc_total_time = 0;
0N/A gc_total_count = 0;
0N/A
0N/A INTERVAL_SECS = $1 ? $1 : 10;
0N/A SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
0N/A
0N/A LINE_SEP = "--------------------------------------------------------";
0N/A
0N/A printf("BEGIN %s\n\n", SAMPLE_NAME);
0N/A}
0N/A
0N/A
0N/A/*
0N/A * hotspot:::gc-begin
0N/A * arg0: uintptr_t, boolean value which indicates
0N/A * if this is to be a full GC or not
0N/A */
0N/Ahotspot$target:::gc-begin
0N/A{
0N/A self->gc_ts = timestamp;
0N/A printf("\nGC started: %Y\n", walltimestamp);
0N/A printf("%20s | %-20s | %10s\n", "manager", "pool", "time (ms)");
0N/A printf(" %s\n", LINE_SEP);
0N/A}
0N/A
0N/Ahotspot$target:::gc-end
0N/A/self->gc_ts/
0N/A{
0N/A self->time = (timestamp - self->gc_ts) / 1000;
0N/A
0N/A printf(" %s\n", LINE_SEP);
0N/A printf(" %40s | %10d\n", "GC total", self->time);
0N/A
0N/A gc_total_time += self->time;
0N/A gc_total_count ++;
0N/A self->gc_ts = 0;
0N/A}
0N/A
0N/A/*
0N/A * hotspot:::mem-pool-gc-begin, hotspot:::mem-pool-gc-end
0N/A * arg0: char*, a pointer to mUTF-8 string data which contains the name
0N/A * of the manager which manages this memory pool
0N/A * arg1: uintptr_t, the length of the manager name (in bytes
0N/A * arg2: char*, a pointer to mUTF-8 string data which contains the name
0N/A * of the memory pool
0N/A * arg3: uintptr_t, the length of the memory pool name (in bytes)
0N/A * arg4: uintptr_t, the initial size of the memory pool (in bytes)
0N/A * arg5: uintptr_t, the amount of memory in use in the memory pool
0N/A * (in bytes)
0N/A * arg6: uintptr_t, the the number of committed pages in the memory pool
0N/A * arg7: uintptr_t, the the maximum size of the memory pool
0N/A */
0N/Ahotspot$target:::mem-pool-gc-begin
0N/A{
0N/A self->str_ptr = (char*) copyin(arg0, arg1+1);
0N/A self->str_ptr[arg1] = '\0';
0N/A self->mgr_name = (string) self->str_ptr;
0N/A
0N/A self->str_ptr = (char*) copyin(arg2, arg3+1);
0N/A self->str_ptr[arg3] = '\0';
0N/A self->pool_name = (string) self->str_ptr;
0N/A
0N/A self->mem_pool_ts[self->mgr_name, self->pool_name] = timestamp;
0N/A}
0N/A
0N/Ahotspot$target:::mem-pool-gc-end
0N/A{
0N/A self->str_ptr = (char*) copyin(arg0, arg1+1);
0N/A self->str_ptr[arg1] = '\0';
0N/A self->mgr_name = (string) self->str_ptr;
0N/A
0N/A self->str_ptr = (char*) copyin(arg2, arg3+1);
0N/A self->str_ptr[arg3] = '\0';
0N/A self->pool_name = (string) self->str_ptr;
0N/A
0N/A self->time =
0N/A (timestamp - self->mem_pool_ts[self->mgr_name, self->pool_name]) / 1000;
0N/A
0N/A printf(
0N/A "%20s | %-20s | %10d\n", self->mgr_name, self->pool_name, self->time);
0N/A
0N/A @mem_pool_total_time[self->mgr_name, self->pool_name] = sum(self->time);
0N/A self->mem_pool_ts[self->mgr_name, self->pool_name] = 0;
0N/A
0N/A @mem_pool_count[self->mgr_name, self->pool_name] = count();
0N/A}
0N/A
0N/Atick-1sec
0N/A/timestamp > SAMPLING_TIME/
0N/A{
0N/A trace_time = (timestamp - START_TIME) / 1000;
0N/A
0N/A printf(" %s\n", LINE_SEP);
0N/A printf("\nGC statistics, time: %Y\n\n", walltimestamp);
0N/A printf("%20s | %-20s | %10s\n", "manager", "pool", "total time");
0N/A printf(" %s\n", LINE_SEP);
0N/A printa("%20s | %-20s | %10@d\n", @mem_pool_total_time);
0N/A printf(" %s\n", LINE_SEP);
0N/A printf(" %40s | %10d\n", "total", gc_total_time);
0N/A
0N/A printf("\n");
0N/A printf("%20s | %-20s | %10s\n", "manager", "pool", "# of calls");
0N/A printf(" %s\n", LINE_SEP);
0N/A printa("%20s | %-20s | %10@d\n", @mem_pool_count);
0N/A printf(" %s\n", LINE_SEP);
0N/A printf(" %40s | %10d\n", "total", gc_total_count);
0N/A
0N/A SAMPLING_TIME = timestamp + INTERVAL_SECS * 1000000000ull;
0N/A}
0N/A
0N/A:::END
0N/A{
0N/A trace_time = (timestamp - START_TIME) / 1000;
0N/A
0N/A printf(" %s\n", LINE_SEP);
0N/A printf("\nGC statistics, time: %Y\n\n", walltimestamp);
0N/A printf("%20s | %-20s | %10s\n", "manager", "pool", "total time");
0N/A printf(" %s\n", LINE_SEP);
0N/A printa("%20s | %-20s | %10@d\n", @mem_pool_total_time);
0N/A printf(" %s\n", LINE_SEP);
0N/A printf(" %40s | %10d\n", "total", gc_total_time);
0N/A
0N/A printf("\n");
0N/A printf("%20s | %-20s | %10s\n", "manager", "pool", "# of calls");
0N/A printf(" %s\n", LINE_SEP);
0N/A printa("%20s | %-20s | %10@d\n", @mem_pool_count);
0N/A printf(" %s\n", LINE_SEP);
0N/A printf(" %40s | %10d\n", "total", gc_total_count);
0N/A
0N/A
0N/A printf("\nEND of %s\n", SAMPLE_NAME);
0N/A}
0N/A
0N/Asyscall::rexit:entry,
0N/Asyscall::exit:entry
0N/A/pid == $target/
0N/A{
0N/A exit(0);
0N/A}