alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (hprof_trace.c)

This example Java source code file (hprof_trace.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

classindex, frameindex, framenames, hprof_assert, hprof_free, hprof_malloc, iterateinfo, jni_false, null, serialnumber, traceindex, traceinfo, tracekey, tracekey\*

The hprof_trace.c Java example source code

/*
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Oracle nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * This source code is provided to illustrate the usage of a given feature
 * or technique and has been deliberately simplified. Additional steps
 * required for a production-quality application, such as security checks,
 * input validation and proper error handling, might not be present in
 * this sample code.
 */


/* Trace table. */

/*
 * A trace is an optional thread serial number plus N frames.
 *
 * The thread serial number is added to the key only if the user asks for
 *    threads in traces, which will cause many more traces to be created.
 *    Without it all threads share the traces.
 *
 * This is a variable length Key, depending on the number of frames.
 *   The frames are FrameIndex values into the frame table.
 *
 * It is important that the thread serial number is used and not the
 *    TlsIndex, threads come and go, and TlsIndex values are re-used
 *    but the thread serial number is unique per thread.
 *
 * The cpu=times and cpu=samples dumps rely heavily on traces, the trace
 *   dump preceeds the cpu information and uses the trace information.
 *   Depending on the cpu= request, different sorts are applied to the
 *   traces that are dumped.
 *
 */

#include "hprof.h"

typedef struct TraceKey {
    SerialNumber thread_serial_num; /* Thread serial number */
    short        n_frames;          /* Number of frames that follow. */
    jvmtiPhase   phase : 8;         /* Makes some traces unique */
    FrameIndex   frames[1];         /* Variable length */
} TraceKey;

typedef struct TraceInfo {
    SerialNumber serial_num;        /* Trace serial number */
    jint         num_hits;          /* Number of hits this trace has */
    jlong        total_cost;        /* Total cost associated with trace */
    jlong        self_cost;         /* Total cost without children cost */
    jint         status;            /* Status of dump of trace */
} TraceInfo;

typedef struct IterateInfo {
    TraceIndex* traces;
    int         count;
    jlong       grand_total_cost;
} IterateInfo;

/* Private internal functions. */

static TraceKey*
get_pkey(TraceIndex index)
{
    void *      pkey;
    int         key_len;

    table_get_key(gdata->trace_table, index, &pkey, &key_len);
    HPROF_ASSERT(pkey!=NULL);
    HPROF_ASSERT(key_len>=(int)sizeof(TraceKey));
    HPROF_ASSERT(((TraceKey*)pkey)->n_frames<=1?key_len==(int)sizeof(TraceKey) :
             key_len==(int)sizeof(TraceKey)+
                      (int)sizeof(FrameIndex)*(((TraceKey*)pkey)->n_frames-1));
    return (TraceKey*)pkey;
}

static TraceInfo *
get_info(TraceIndex index)
{
    TraceInfo *         info;

    info        = (TraceInfo*)table_get_info(gdata->trace_table, index);
    return info;
}

static TraceIndex
find_or_create(SerialNumber thread_serial_num, jint n_frames,
            FrameIndex *frames, jvmtiPhase phase, TraceKey *trace_key_buffer)
{
    TraceInfo * info;
    TraceKey *  pkey;
    int         key_len;
    TraceIndex  index;
    jboolean    new_one;
    static TraceKey empty_key;

    HPROF_ASSERT(frames!=NULL);
    HPROF_ASSERT(trace_key_buffer!=NULL);
    key_len = (int)sizeof(TraceKey);
    if ( n_frames > 1 ) {
        key_len += (int)((n_frames-1)*(int)sizeof(FrameIndex));
    }
    pkey = trace_key_buffer;
    *pkey = empty_key;
    pkey->thread_serial_num = (gdata->thread_in_traces ? thread_serial_num : 0);
    pkey->n_frames = (short)n_frames;
    pkey->phase = phase;
    if ( n_frames > 0 ) {
        (void)memcpy(pkey->frames, frames, (n_frames*(int)sizeof(FrameIndex)));
    }

    new_one = JNI_FALSE;
    index = table_find_or_create_entry(gdata->trace_table,
                                pkey, key_len, &new_one, NULL);
    if ( new_one ) {
        info = get_info(index);
        info->serial_num = gdata->trace_serial_number_counter++;
    }
    return index;
}

static void
list_item(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
{
    TraceInfo *info;
    TraceKey         *key;
    int               i;

    HPROF_ASSERT(key_ptr!=NULL);
    HPROF_ASSERT(key_len>0);
    HPROF_ASSERT(info_ptr!=NULL);
    key = (TraceKey*)key_ptr;
    info = (TraceInfo *)info_ptr;

    debug_message( "Trace 0x%08x: SN=%u, threadSN=%u, n_frames=%d, frames=(",
             index,
             info->serial_num,
             key->thread_serial_num,
             key->n_frames);
    for ( i = 0 ; i < key->n_frames ; i++ ) {
        debug_message( "0x%08x, ", key->frames[i]);
    }
    debug_message( "), traceSN=%u, num_hits=%d, self_cost=(%d,%d), "
                        "total_cost=(%d,%d), status=0x%08x\n",
                        info->serial_num,
                        info->num_hits,
                        jlong_high(info->self_cost),
                        jlong_low(info->self_cost),
                        jlong_high(info->total_cost),
                        jlong_low(info->total_cost),
                        info->status);
}

static void
clear_cost(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg)
{
    TraceInfo *info;

    HPROF_ASSERT(key_ptr!=NULL);
    HPROF_ASSERT(key_len>0);
    HPROF_ASSERT(info_ptr!=NULL);
    info = (TraceInfo *)info_ptr;
    info->num_hits = 0;
    info->total_cost = 0;
    info->self_cost = 0;
}

/* Get the names for a frame in order to dump it. */
static void
get_frame_details(JNIEnv *env, FrameIndex frame_index,
                SerialNumber *frame_serial_num, char **pcsig, ClassIndex *pcnum,
                char **pmname, char **pmsig, char **psname, jint *plineno)
{
    jmethodID method;
    jlocation location;
    jint      lineno;

    HPROF_ASSERT(frame_index!=0);
    *pmname = NULL;
    *pmsig = NULL;
    *pcsig = NULL;
    if ( psname != NULL ) {
        *psname = NULL;
    }
    if ( plineno != NULL ) {
        *plineno = -1;
    }
    if ( pcnum != NULL ) {
        *pcnum = 0;
    }
    frame_get_location(frame_index, frame_serial_num, &method, &location, &lineno);
    if ( plineno != NULL ) {
        *plineno = lineno;
    }
    WITH_LOCAL_REFS(env, 1) {
        jclass klass;

        getMethodClass(method, &klass);
        getClassSignature(klass, pcsig, NULL);
        if ( pcnum != NULL ) {
            LoaderIndex loader_index;
            jobject     loader;

            loader = getClassLoader(klass);
            loader_index = loader_find_or_create(env, loader);
            *pcnum = class_find_or_create(*pcsig, loader_index);
             (void)class_new_classref(env, *pcnum, klass);
        }
        if ( psname != NULL ) {
            getSourceFileName(klass, psname);
        }
    } END_WITH_LOCAL_REFS;
    getMethodName(method, pmname, pmsig);
}

/* Write out a stack trace.  */
static void
output_trace(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
{
    TraceKey *key;
    TraceInfo *info;
    SerialNumber serial_num;
    SerialNumber thread_serial_num;
    jint n_frames;
    JNIEnv *env;
    int i;
    char *phase_str;
    struct FrameNames {
        SerialNumber serial_num;
        char * sname;
        char * csig;
        char * mname;
        int    lineno;
    } *finfo;

    info = (TraceInfo*)info_ptr;
    if ( info->status != 0 ) {
        return;
    }

    env = (JNIEnv*)arg;

    key = (TraceKey*)key_ptr;
    thread_serial_num = key->thread_serial_num;
    serial_num = info->serial_num;
    info->status = 1;
    finfo = NULL;

    n_frames = (jint)key->n_frames;
    if ( n_frames > 0 ) {
        finfo = (struct FrameNames *)HPROF_MALLOC(n_frames*(int)sizeof(struct FrameNames));

        /* Write frames, but save information for trace later */
        for (i = 0; i < n_frames; i++) {
            FrameIndex frame_index;
            char *msig;
            ClassIndex cnum;

            frame_index = key->frames[i];
            get_frame_details(env, frame_index, &finfo[i].serial_num,
                        &finfo[i].csig, &cnum,
                        &finfo[i].mname, &msig, &finfo[i].sname, &finfo[i].lineno);

            if (frame_get_status(frame_index) == 0) {
                io_write_frame(frame_index, finfo[i].serial_num,
                               finfo[i].mname, msig,
                               finfo[i].sname, class_get_serial_number(cnum),
                               finfo[i].lineno);
                frame_set_status(frame_index, 1);
            }
            jvmtiDeallocate(msig);
        }
    }

    /* Find phase string */
    if ( key->phase == JVMTI_PHASE_LIVE ) {
        phase_str = NULL; /* Normal trace, no phase annotation */
    } else {
        phase_str =  phaseString(key->phase);
    }

    io_write_trace_header(serial_num, thread_serial_num, n_frames, phase_str);

    for (i = 0; i < n_frames; i++) {
        io_write_trace_elem(serial_num, key->frames[i], finfo[i].serial_num,
                            finfo[i].csig,
                            finfo[i].mname, finfo[i].sname, finfo[i].lineno);
        jvmtiDeallocate(finfo[i].csig);
        jvmtiDeallocate(finfo[i].mname);
        jvmtiDeallocate(finfo[i].sname);
    }

    io_write_trace_footer(serial_num, thread_serial_num, n_frames);

    if ( finfo != NULL ) {
        HPROF_FREE(finfo);
    }
}

/* Output a specific list of traces. */
static void
output_list(JNIEnv *env, TraceIndex *list, jint count)
{
    rawMonitorEnter(gdata->data_access_lock); {
        int i;

        for ( i = 0; i < count ; i++ ) {
            TraceIndex index;
            TraceInfo  *info;
            void *      pkey;
            int         key_len;

            index = list[i];
            table_get_key(gdata->trace_table, index, &pkey, &key_len);
            info = get_info(index);
            output_trace(index, pkey, key_len, info, (void*)env);
        }
    } rawMonitorExit(gdata->data_access_lock);
}

static void
collect_iterator(TableIndex index, void *key_ptr, int key_len, void *info_ptr, void *arg)
{
    TraceInfo *info;
    IterateInfo      *iterate;

    HPROF_ASSERT(key_ptr!=NULL);
    HPROF_ASSERT(key_len>0);
    HPROF_ASSERT(arg!=NULL);
    HPROF_ASSERT(info_ptr!=NULL);
    iterate = (IterateInfo *)arg;
    info = (TraceInfo *)info_ptr;
    iterate->traces[iterate->count++] = index;
    iterate->grand_total_cost += info->self_cost;
}

static int
qsort_compare_cost(const void *p_trace1, const void *p_trace2)
{
    TraceIndex          trace1;
    TraceIndex          trace2;
    TraceInfo * info1;
    TraceInfo * info2;

    HPROF_ASSERT(p_trace1!=NULL);
    HPROF_ASSERT(p_trace2!=NULL);
    trace1 = *(TraceIndex *)p_trace1;
    trace2 = *(TraceIndex *)p_trace2;
    info1 = get_info(trace1);
    info2 = get_info(trace2);
    /*LINTED*/
    return (int)(info2->self_cost - info1->self_cost);
}

static int
qsort_compare_num_hits(const void *p_trace1, const void *p_trace2)
{
    TraceIndex          trace1;
    TraceIndex          trace2;
    TraceInfo * info1;
    TraceInfo * info2;

    HPROF_ASSERT(p_trace1!=NULL);
    HPROF_ASSERT(p_trace2!=NULL);
    trace1 = *(TraceIndex *)p_trace1;
    trace2 = *(TraceIndex *)p_trace2;
    info1 = get_info(trace1);
    info2 = get_info(trace2);
    return info2->num_hits - info1->num_hits;
}

/* External interfaces. */

void
trace_init(void)
{
    gdata->trace_table = table_initialize("Trace",
                            256, 256, 511, (int)sizeof(TraceInfo));
}

void
trace_list(void)
{
    debug_message(
        "--------------------- Trace Table ------------------------\n");
    table_walk_items(gdata->trace_table, &list_item, NULL);
    debug_message(
        "----------------------------------------------------------\n");
}

void
trace_cleanup(void)
{
    table_cleanup(gdata->trace_table, NULL, NULL);
    gdata->trace_table = NULL;
}

SerialNumber
trace_get_serial_number(TraceIndex index)
{
    TraceInfo *info;

    if ( index == 0 ) {
        return 0;
    }
    info = get_info(index);
    return info->serial_num;
}

void
trace_increment_cost(TraceIndex index, jint num_hits, jlong self_cost, jlong total_cost)
{
    TraceInfo *info;

    table_lock_enter(gdata->trace_table); {
        info              = get_info(index);
        info->num_hits   += num_hits;
        info->self_cost  += self_cost;
        info->total_cost += total_cost;
    } table_lock_exit(gdata->trace_table);
}

TraceIndex
trace_find_or_create(SerialNumber thread_serial_num, jint n_frames, FrameIndex *frames, jvmtiFrameInfo *jframes_buffer)
{
    return find_or_create(thread_serial_num, n_frames, frames, getPhase(),
                                (TraceKey*)jframes_buffer);
}

/* We may need to ask for more frames than the user asked for */
static int
get_real_depth(int depth, jboolean skip_init)
{
    int extra_frames;

    extra_frames = 0;
    /* This is only needed if we are doing BCI */
    if ( gdata->bci && depth > 0 ) {
        /* Account for Java and native Tracker methods */
        extra_frames = 2;
        if ( skip_init ) {
            /* Also allow for ignoring the java.lang.Object.<init> method */
            extra_frames += 1;
        }
    }
    return depth + extra_frames;
}

/* Fill in FrameIndex array from jvmtiFrameInfo array, return n_frames */
static int
fill_frame_buffer(int depth, int real_depth,
                 int frame_count, jboolean skip_init,
                 jvmtiFrameInfo *jframes_buffer, FrameIndex *frames_buffer)
{
    int  n_frames;
    jint topframe;

    /* If real_depth is 0, just return 0 */
    if ( real_depth == 0 ) {
        return 0;
    }

    /* Assume top frame index is 0 for now */
    topframe = 0;

    /* Possible top frames belong to the hprof Tracker class, remove them */
    if ( gdata->bci ) {
        while ( ( ( frame_count - topframe ) > 0 ) &&
                ( topframe < (real_depth-depth) ) &&
                ( tracker_method(jframes_buffer[topframe].method) ||
                  ( skip_init
                    && jframes_buffer[topframe].method==gdata->object_init_method ) )
             ) {
            topframe++;
        }
    }

    /* Adjust count to match depth request */
    if ( ( frame_count - topframe ) > depth ) {
        frame_count =  depth + topframe;
    }

    /* The actual frame count we will process */
    n_frames = frame_count - topframe;
    if ( n_frames > 0 ) {
        int i;

        for (i = 0; i < n_frames; i++) {
            jmethodID method;
            jlocation location;

            method = jframes_buffer[i+topframe].method;
            location = jframes_buffer[i+topframe].location;
            frames_buffer[i] = frame_find_or_create(method, location);
        }
    }
    return n_frames;
}

/* Get the trace for the supplied thread */
TraceIndex
trace_get_current(jthread thread, SerialNumber thread_serial_num,
                        int depth, jboolean skip_init,
                        FrameIndex *frames_buffer,
                        jvmtiFrameInfo *jframes_buffer)
{
    TraceIndex index;
    jint       frame_count;
    int        real_depth;
    int        n_frames;

    HPROF_ASSERT(thread!=NULL);
    HPROF_ASSERT(frames_buffer!=NULL);
    HPROF_ASSERT(jframes_buffer!=NULL);

    /* We may need to ask for more frames than the user asked for */
    real_depth = get_real_depth(depth, skip_init);

    /* Get the stack trace for this one thread */
    frame_count = 0;
    if ( real_depth > 0 ) {
        getStackTrace(thread, jframes_buffer, real_depth, &frame_count);
    }

    /* Create FrameIndex's */
    n_frames = fill_frame_buffer(depth, real_depth, frame_count, skip_init,
                                 jframes_buffer, frames_buffer);

    /* Lookup or create new TraceIndex */
    index = find_or_create(thread_serial_num, n_frames, frames_buffer,
                getPhase(), (TraceKey*)jframes_buffer);
    return index;
}

/* Get traces for all threads in list (traces[i]==0 if thread not running) */
void
trace_get_all_current(jint thread_count, jthread *threads,
                      SerialNumber *thread_serial_nums,
                      int depth, jboolean skip_init,
                      TraceIndex *traces, jboolean always_care)
{
    jvmtiStackInfo *stack_info;
    int             nbytes;
    int             real_depth;
    int             i;
    FrameIndex     *frames_buffer;
    TraceKey       *trace_key_buffer;
    jvmtiPhase      phase;

    HPROF_ASSERT(threads!=NULL);
    HPROF_ASSERT(thread_serial_nums!=NULL);
    HPROF_ASSERT(traces!=NULL);
    HPROF_ASSERT(thread_count > 0);

    /* Find out what the phase is for all these traces */
    phase = getPhase();

    /* We may need to ask for more frames than the user asked for */
    real_depth = get_real_depth(depth, skip_init);

    /* Get the stack traces for all the threads */
    getThreadListStackTraces(thread_count, threads, real_depth, &stack_info);

    /* Allocate a frames_buffer and trace key buffer */
    nbytes = (int)sizeof(FrameIndex)*real_depth;
    frames_buffer = (FrameIndex*)HPROF_MALLOC(nbytes);
    nbytes += (int)sizeof(TraceKey);
    trace_key_buffer = (TraceKey*)HPROF_MALLOC(nbytes);

    /* Loop over the stack traces we have for these 'thread_count' threads */
    for ( i = 0 ; i < thread_count ; i++ ) {
        int n_frames;

        /* Assume 0 at first (no trace) */
        traces[i] = 0;

        /* If thread has frames, is runnable, and isn't suspended, we care */
        if ( always_care ||
             ( stack_info[i].frame_count > 0
               && (stack_info[i].state & JVMTI_THREAD_STATE_RUNNABLE)!=0
               && (stack_info[i].state & JVMTI_THREAD_STATE_SUSPENDED)==0
               && (stack_info[i].state & JVMTI_THREAD_STATE_INTERRUPTED)==0 )
            ) {

            /* Create FrameIndex's */
            n_frames = fill_frame_buffer(depth, real_depth,
                                         stack_info[i].frame_count,
                                         skip_init,
                                         stack_info[i].frame_buffer,
                                         frames_buffer);

            /* Lookup or create new TraceIndex */
            traces[i] = find_or_create(thread_serial_nums[i],
                           n_frames, frames_buffer, phase, trace_key_buffer);
        }
    }

    /* Make sure we free the space */
    HPROF_FREE(frames_buffer);
    HPROF_FREE(trace_key_buffer);
    jvmtiDeallocate(stack_info);
}

/* Increment the trace costs for all the threads (for cpu=samples) */
void
trace_increment_all_sample_costs(jint thread_count, jthread *threads,
                      SerialNumber *thread_serial_nums,
                      int depth, jboolean skip_init)
{
    TraceIndex *traces;
    int         nbytes;

    HPROF_ASSERT(threads!=NULL);
    HPROF_ASSERT(thread_serial_nums!=NULL);
    HPROF_ASSERT(thread_count > 0);
    HPROF_ASSERT(depth >= 0);

    if ( depth == 0 ) {
        return;
    }

    /* Allocate a traces array */
    nbytes = (int)sizeof(TraceIndex)*thread_count;
    traces = (TraceIndex*)HPROF_MALLOC(nbytes);

    /* Get all the current traces for these threads */
    trace_get_all_current(thread_count, threads, thread_serial_nums,
                      depth, skip_init, traces, JNI_FALSE);

    /* Increment the cpu=samples cost on these traces */
    table_lock_enter(gdata->trace_table); {
        int i;

        for ( i = 0 ; i < thread_count ; i++ ) {
            /* Each trace gets a hit and an increment of it's total cost */
            if ( traces[i] != 0 ) {
                TraceInfo *info;

                info              = get_info(traces[i]);
                info->num_hits   += 1;
                info->self_cost  += (jlong)1;
                info->total_cost += (jlong)1;
            }
        }
    } table_lock_exit(gdata->trace_table);

    /* Free up the memory allocated */
    HPROF_FREE(traces);
}

void
trace_output_unmarked(JNIEnv *env)
{
    rawMonitorEnter(gdata->data_access_lock); {
        table_walk_items(gdata->trace_table, &output_trace, (void*)env);
    } rawMonitorExit(gdata->data_access_lock);
}

/* output info on the cost associated with traces  */
void
trace_output_cost(JNIEnv *env, double cutoff)
{
    IterateInfo iterate;
    int i, trace_table_size, n_items;
    double accum;
    int n_entries;

    rawMonitorEnter(gdata->data_access_lock); {

        n_entries = table_element_count(gdata->trace_table);
        iterate.traces = HPROF_MALLOC(n_entries*(int)sizeof(TraceIndex)+1);
        iterate.count = 0;
        iterate.grand_total_cost = 0;
        table_walk_items(gdata->trace_table, &collect_iterator, &iterate);

        trace_table_size = iterate.count;

        /* sort all the traces according to the cost */
        qsort(iterate.traces, trace_table_size, sizeof(TraceIndex),
                    &qsort_compare_cost);

        n_items = 0;
        for (i = 0; i < trace_table_size; i++) {
            TraceInfo *info;
            TraceIndex trace_index;
            double percent;

            trace_index = iterate.traces[i];
            info = get_info(trace_index);
            /* As soon as a trace with zero hits is seen, we need no others */
            if (info->num_hits == 0 ) {
                break;
            }
            percent = (double)info->self_cost / (double)iterate.grand_total_cost;
            if (percent < cutoff) {
                break;
            }
            n_items++;
        }

        /* Now write all trace we might refer to. */
        output_list(env, iterate.traces, n_items);

        io_write_cpu_samples_header(iterate.grand_total_cost, n_items);

        accum = 0;

        for (i = 0; i < n_items; i++) {
            SerialNumber frame_serial_num;
            TraceInfo *info;
            TraceKey *key;
            TraceIndex trace_index;
            double percent;
            char *csig;
            char *mname;
            char *msig;

            trace_index = iterate.traces[i];
            info = get_info(trace_index);
            key = get_pkey(trace_index);
            percent = ((double)info->self_cost / (double)iterate.grand_total_cost) * 100.0;
            accum += percent;

            csig = NULL;
            mname = NULL;
            msig  = NULL;

            if (key->n_frames > 0) {
                get_frame_details(env, key->frames[0], &frame_serial_num,
                        &csig, NULL, &mname, &msig, NULL, NULL);
            }

            io_write_cpu_samples_elem(i+1, percent, accum, info->num_hits,
                        (jint)info->self_cost, info->serial_num,
                        key->n_frames, csig, mname);

            jvmtiDeallocate(csig);
            jvmtiDeallocate(mname);
            jvmtiDeallocate(msig);
        }

        io_write_cpu_samples_footer();

        HPROF_FREE(iterate.traces);

    } rawMonitorExit(gdata->data_access_lock);

}

/* output the trace cost in old prof format */
void
trace_output_cost_in_prof_format(JNIEnv *env)
{
    IterateInfo iterate;
    int i, trace_table_size;
    int n_entries;

    rawMonitorEnter(gdata->data_access_lock); {

        n_entries = table_element_count(gdata->trace_table);
        iterate.traces = HPROF_MALLOC(n_entries*(int)sizeof(TraceIndex)+1);
        iterate.count = 0;
        iterate.grand_total_cost = 0;
        table_walk_items(gdata->trace_table, &collect_iterator, &iterate);

        trace_table_size = iterate.count;

        /* sort all the traces according to the number of hits */
        qsort(iterate.traces, trace_table_size, sizeof(TraceIndex),
                    &qsort_compare_num_hits);

        io_write_oldprof_header();

        for (i = 0; i < trace_table_size; i++) {
            SerialNumber frame_serial_num;
            TraceInfo *info;
            TraceKey *key;
            TraceIndex trace_index;
            int num_frames;
            int num_hits;
            char *csig_callee;
            char *mname_callee;
            char *msig_callee;
            char *csig_caller;
            char *mname_caller;
            char *msig_caller;

            trace_index = iterate.traces[i];
            key = get_pkey(trace_index);
            info = get_info(trace_index);
            num_hits = info->num_hits;

            if (num_hits == 0) {
                break;
            }

            csig_callee  = NULL;
            mname_callee = NULL;
            msig_callee  = NULL;
            csig_caller  = NULL;
            mname_caller = NULL;
            msig_caller  = NULL;

            num_frames = (int)key->n_frames;

            if (num_frames >= 1) {
                get_frame_details(env, key->frames[0], &frame_serial_num,
                        &csig_callee, NULL,
                        &mname_callee, &msig_callee, NULL, NULL);
            }

            if (num_frames > 1) {
                get_frame_details(env, key->frames[1], &frame_serial_num,
                        &csig_caller, NULL,
                        &mname_caller, &msig_caller, NULL, NULL);
            }

            io_write_oldprof_elem(info->num_hits, num_frames,
                                    csig_callee, mname_callee, msig_callee,
                                    csig_caller, mname_caller, msig_caller,
                                    (int)info->total_cost);

            jvmtiDeallocate(csig_callee);
            jvmtiDeallocate(mname_callee);
            jvmtiDeallocate(msig_callee);
            jvmtiDeallocate(csig_caller);
            jvmtiDeallocate(mname_caller);
            jvmtiDeallocate(msig_caller);
        }

        io_write_oldprof_footer();

        HPROF_FREE(iterate.traces);

    } rawMonitorExit(gdata->data_access_lock);
}

void
trace_clear_cost(void)
{
    table_walk_items(gdata->trace_table, &clear_cost, NULL);
}

Other Java examples (source code examples)

Here is a short list of links related to this Java hprof_trace.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.