hprof_trace.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 494 行
C
494 行
/* * @(#)hprof_trace.c 1.18 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/porting/ansi/string.h"#include "hprof.h"static unsigned int trace_serial_number = 1;static hprof_hash_t hprof_trace_table;static unsigned int hash_trace(void * _trace){ hprof_trace_t *trace = _trace; unsigned int hash = trace->thread_serial_num + 37 * trace->n_frames; int i; for (i = 0; i < trace->n_frames; i++) { hash = hash * 37 + ((unsigned int)trace->frames[i] >> HASH_OBJ_SHIFT); } return hash % hprof_trace_table.size;}static unsigned int size_trace(void * _trace){ hprof_trace_t *trace = _trace; return ((char *)&(trace->frames) - (char *)trace) + trace->n_frames * sizeof(hprof_frame_t *);}static int compare_trace(void *_trace1, void *_trace2){ hprof_trace_t *trace1 = _trace1; hprof_trace_t *trace2 = _trace2; int result = trace1->thread_serial_num - trace2->thread_serial_num; int i; if (result) { return result; } result = trace1->n_frames - trace2->n_frames; if (result) { return result; } for (i = 0; i < trace1->n_frames; i++) { result = trace1->frames[i] - trace2->frames[i]; if (result) { return result; } } return 0;}void hprof_trace_table_init(void){ hprof_hash_init(ALLOC_HASH_TRACE, &hprof_trace_table, 256, hash_trace, size_trace, compare_trace);}static hprof_hash_t hprof_frame_table;static unsigned int hash_frame(void *_frame){ hprof_frame_t *frame = _frame; return (((unsigned int)frame->method >> HASH_OBJ_SHIFT) + 31 * (unsigned int)frame->lineno) % hprof_frame_table.size;}static unsigned int size_frame(void *_frame){ return sizeof(hprof_frame_t);}static int compare_frame(void *_frame1, void *_frame2){ hprof_frame_t *frame1 = _frame1; hprof_frame_t *frame2 = _frame2; int result = frame1->lineno - frame2->lineno; if (result) { return result; } return frame1->method - frame2->method;}void hprof_frame_table_init(void){ hprof_hash_init(ALLOC_HASH_FRAME, &hprof_frame_table, 256, hash_frame, size_frame, compare_frame);}hprof_frame_t *hprof_intern_jvmpi_frame(jmethodID method_id, int lineno){ hprof_frame_t frame_tmp; frame_tmp.marked = 0; if (lineno_in_traces) { frame_tmp.lineno = lineno; } else { frame_tmp.lineno = -1; } frame_tmp.method = hprof_lookup_method(method_id); if (frame_tmp.method == NULL) { fprintf(stderr, "HPROF ERROR: unable to resolve a method id\n"); return NULL; } return hprof_hash_intern(&hprof_frame_table, &frame_tmp);}hprof_trace_t *hprof_alloc_tmp_trace(int n_frames, JNIEnv *env_id){ hprof_trace_t *trace_tmp = 0; int thread_serial_num = 0; trace_tmp = HPROF_CALLOC(ALLOC_TYPE_ARRAY, n_frames * sizeof(hprof_frame_t *) + ((char *)&(trace_tmp->frames) - (char *)trace_tmp)); trace_tmp->n_frames = n_frames; trace_tmp->serial_num = 0; trace_tmp->marked = 0; trace_tmp->num_hits = 0; trace_tmp->cost = jlong_zero; /* include thread info only if thread_in_traces is true and env_id is not * NULL. even if thread_in_traces is true, other hprof functions may want to * intern traces without the thread info, e.g. hprof_bill_frames_cost for * the old prof output format. */ if ((!thread_in_traces) || (env_id == NULL)) { thread_serial_num = 0; } else { hprof_thread_t *thread = hprof_intern_thread(env_id); thread_serial_num = thread->serial_num; } trace_tmp->thread_serial_num = thread_serial_num; return trace_tmp;}hprof_trace_t *hprof_intern_tmp_trace(hprof_trace_t *trace_tmp){ hprof_trace_t *result = hprof_hash_lookup(&hprof_trace_table, trace_tmp); if (result == NULL) { trace_tmp->serial_num = trace_serial_number++; result = hprof_hash_put(&hprof_trace_table, trace_tmp); } hprof_free(trace_tmp); return result;} hprof_trace_t *hprof_intern_jvmpi_trace(JVMPI_CallFrame *frames, int n_frames, JNIEnv *env_id){ int i; hprof_trace_t *trace_tmp = hprof_alloc_tmp_trace(n_frames, env_id); /* intern all the frames in the trace */ for (i = 0; i < n_frames; i++) { hprof_frame_t *frame = hprof_intern_jvmpi_frame(frames[i].method_id , frames[i].lineno); if (frame == NULL) { hprof_free(trace_tmp); return NULL; } trace_tmp->frames[i] = frame; } return hprof_intern_tmp_trace(trace_tmp);}hprof_trace_t *hprof_get_trace(JNIEnv *env_id, int depth){ hprof_trace_t *htrace; JVMPI_CallTrace jtrace; /* allocate space for the trace */ jtrace.frames = HPROF_CALLOC(ALLOC_TYPE_CALLFRAME, depth*sizeof(JVMPI_CallFrame)); /* Get the trace from the JVM */ jtrace.env_id = env_id; CALL(GetCallTrace)(&jtrace, depth); /* intern the trace */ htrace = hprof_intern_jvmpi_trace(jtrace.frames, jtrace.num_frames, jtrace.env_id); /* Free up the space */ hprof_free(jtrace.frames); return htrace;} /* Write out a stack trace. * Works differently depending on the output_format */static void hprof_output_trace(hprof_trace_t *trace){ int i; if (trace->marked) { return; } trace->marked = 1; if (output_format == 'b') { for (i = 0; i < trace->n_frames; i++) { if (trace->frames[i]->marked == 0) { hprof_frame_t *frame = trace->frames[i]; hprof_method_t *method = frame->method; hprof_name_t *method_name = method->method_name; hprof_name_t *method_signature = method->method_signature; hprof_class_t *class = method->class; hprof_name_t *src_name = class->src_name; frame->marked = 1; hprof_write_header(HPROF_FRAME, sizeof(void *) * 4 + 8); hprof_write_id(frame); hprof_write_id(method_name); hprof_write_id(method_signature); hprof_write_id(src_name); hprof_write_u4(class->serial_num); hprof_write_u4(frame->lineno); } } hprof_write_header(HPROF_TRACE, sizeof(void *) * trace->n_frames + 12); hprof_write_u4(trace->serial_num); hprof_write_u4(trace->thread_serial_num); hprof_write_u4(trace->n_frames); for (i = 0; i < trace->n_frames; i++) { hprof_write_id(trace->frames[i]); } } else { hprof_printf("TRACE %u:", trace->serial_num); if (trace->thread_serial_num) { hprof_printf(" (thread=%d)", trace->thread_serial_num); } hprof_printf("\n"); if (trace->n_frames == 0) { hprof_printf("\t<empty>\n"); } for (i = 0; i < trace->n_frames; i++) { hprof_frame_t *frame = trace->frames[i]; hprof_method_t *method = frame->method; hprof_class_t *class = method->class; const char *srcname = class->src_name->name; const char *classname = class->name->name; const char *methodname = method->method_name->name; char lineno_buf[256]; int lineno = frame->lineno; if (lineno == -2) { strcpy(lineno_buf, "Compiled method"); } else if (lineno == -3) { strcpy(lineno_buf, "Native method"); } else if (lineno == -1) { strcpy(lineno_buf, "Unknown line"); } else { sprintf(lineno_buf, "%d", lineno); } hprof_printf("\t%s.%s(%s:%s)\n", classname, methodname, srcname, lineno_buf); } }}static void *hprof_output_unmarked_trace(void *_trace, void *arg){ hprof_trace_t *trace = _trace; hprof_output_trace(trace); return arg;}void hprof_output_unmarked_traces(void){ hprof_hash_iterate(&hprof_trace_table, hprof_output_unmarked_trace, 0);}static void * hprof_trace_collect(void *_trace, void *_arg){ hprof_trace_iterate_t *arg = _arg; hprof_trace_t *trace = _trace; arg->traces[arg->index++] = trace; arg->total_count += jlong_to_jint(trace->cost); return _arg;}static int hprof_trace_compare_cost(const void *p_trace1, const void *p_trace2){ hprof_trace_t *trace1 = *(hprof_trace_t **)p_trace1; hprof_trace_t *trace2 = *(hprof_trace_t **)p_trace2; return jlong_to_jint(jlong_sub(trace2->cost, trace1->cost));}static int hprof_trace_compare_num_hits(const void *p_trace1, const void *p_trace2){ hprof_trace_t *trace1 = *(hprof_trace_t **)p_trace1; hprof_trace_t *trace2 = *(hprof_trace_t **)p_trace2; return trace2->num_hits - trace1->num_hits;}/* output info on the cost associated with traces */voidhprof_output_trace_cost(float cutoff, char *record_name){ hprof_trace_iterate_t iterate; int i, trace_table_size, n_items; float accum, percent; CALL(RawMonitorEnter)(data_access_lock); /* First write all trace we might refer to. */ hprof_output_unmarked_traces(); iterate.traces = HPROF_CALLOC(ALLOC_TYPE_ARRAY, hprof_trace_table.n_entries * sizeof(void *)); iterate.total_count = iterate.index = 0; hprof_hash_iterate(&hprof_trace_table, hprof_trace_collect, &iterate); trace_table_size = iterate.index; /* sort all the traces according to the cost */ qsort(iterate.traces, trace_table_size, sizeof(void *), hprof_trace_compare_cost); n_items = 0; for (i = 0; i < trace_table_size; i++) { hprof_trace_t *trace = iterate.traces[i]; percent = CVMlong2Float(trace->cost) / (float)iterate.total_count; if (percent < cutoff) { break; } n_items++; } /* output the info */ if (output_format == 'a') { time_t t = time(0); hprof_printf("%s BEGIN (total = %u) %s", record_name, iterate.total_count, ctime(&t)); hprof_printf("rank self accum count trace method\n"); accum = 0; for (i = 0; i < n_items; i++) { hprof_trace_t *trace = iterate.traces[i]; percent = CVMlong2Float(trace->cost) / (float)iterate.total_count * 100.0; accum += percent; hprof_printf("%4u %5.2f%% %5.2f%% %7u %5u", i + 1, percent, accum, trace->num_hits, trace->serial_num); if (trace->n_frames > 0) { hprof_frame_t *frame = trace->frames[0]; hprof_method_t *method = frame->method; hprof_printf(" %s.%s\n", method->class->name->name, method->method_name->name); } else { hprof_printf(" <empty trace>\n"); } } hprof_printf("%s END\n", record_name); } else { hprof_write_header(HPROF_CPU_SAMPLES, n_items * 8 + 4 + 4); hprof_write_u4(iterate.total_count); hprof_write_u4(n_items); for (i = 0; i < n_items; i++) { hprof_trace_t *trace = iterate.traces[i]; hprof_write_u4(jlong_to_jint(trace->cost)); hprof_write_u4(trace->serial_num); } } hprof_free(iterate.traces); CALL(RawMonitorExit)(data_access_lock);}/* output the trace cost in old prof format */void hprof_output_trace_cost_in_prof_format(void) { hprof_trace_iterate_t iterate; int i, trace_table_size; CALL(RawMonitorEnter)(data_access_lock); iterate.traces = HPROF_CALLOC(ALLOC_TYPE_ARRAY, hprof_trace_table.n_entries * sizeof(void *)); iterate.index = 0; hprof_hash_iterate(&hprof_trace_table, hprof_trace_collect, &iterate); trace_table_size = iterate.index; /* sort all the traces according to the number of hits */ qsort(iterate.traces, trace_table_size, sizeof(void *), hprof_trace_compare_num_hits); hprof_printf("count callee caller time\n"); for (i = 0; i < trace_table_size; i++) { hprof_trace_t *trace = iterate.traces[i]; int num_frames = trace->n_frames; int num_hits = trace->num_hits; if (num_hits == 0) { goto done; } hprof_printf("%d ", trace->num_hits); if (num_frames >= 1) { hprof_method_t *callee = trace->frames[0]->method; hprof_printf("%s.%s%s ", callee->class->name->name, callee->method_name->name, callee->method_signature->name); } else { hprof_printf("%s ", "<unknown callee>"); } if (num_frames > 1) { hprof_method_t *caller = trace->frames[1]->method; hprof_printf("%s.%s%s ", caller->class->name->name, caller->method_name->name, caller->method_signature->name); } else { hprof_printf("%s ", "<unknown caller>"); } hprof_printf("%d\n", jlong_to_jint(trace->cost)); } done: CALL(RawMonitorExit)(data_access_lock);} static void * hprof_clear_trace_cost_helper(void *_trace, void *_arg){ hprof_trace_t *trace = _trace; trace->cost = jlong_zero; return _arg;}void hprof_clear_trace_cost(void){ hprof_hash_iterate(&hprof_trace_table, hprof_clear_trace_cost_helper, NULL);}#ifdef HASH_STATSvoid hprof_print_frame_hash_stats(FILE *fp) { hprof_print_tbl_hash_stats(fp, &hprof_frame_table);}void hprof_print_trace_hash_stats(FILE *fp) { hprof_print_tbl_hash_stats(fp, &hprof_trace_table);}#endif /* HASH_STATS */#ifdef WATCH_ALLOCSvoid hprof_free_frame_table(void){ hprof_hash_removeall(&hprof_frame_table); hprof_hash_free(&hprof_frame_table);}void hprof_free_trace_table(void){ hprof_hash_removeall(&hprof_trace_table); hprof_hash_free(&hprof_trace_table);}#endif /* WATCH_ALLOCS */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?