hprof_trace.c
来自「一个小公司要求给写的很简单的任务管理系统。」· C语言 代码 · 共 867 行 · 第 1/2 页
C
867 行
/* * @(#)hprof_trace.c 1.40 05/11/17 * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution 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 Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. *//* 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 TraceIndexfind_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 voidlist_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 voidclear_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 voidget_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 voidcollect_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. */voidtrace_init(void){ gdata->trace_table = table_initialize("Trace", 256, 256, 511, (int)sizeof(TraceInfo));}voidtrace_list(void){ debug_message( "--------------------- Trace Table ------------------------\n"); table_walk_items(gdata->trace_table, &list_item, NULL); debug_message( "----------------------------------------------------------\n");}voidtrace_cleanup(void){ table_cleanup(gdata->trace_table, NULL, NULL); gdata->trace_table = NULL;}SerialNumbertrace_get_serial_number(TraceIndex index){ TraceInfo *info; if ( index == 0 ) { return 0; } info = get_info(index); return info->serial_num;}voidtrace_increment_cost(TraceIndex index, jint num_hits, jlong self_cost, jlong total_cost)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?