hprof.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 565 行 · 第 1/2 页

C
565
字号
/* * @(#)hprof.c	1.57 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/clib.h"#include "hprof.h"static void hprof_notify_event(JVMPI_Event *event);static void hprof_dump_data(void);JavaVM *jvm;int hprof_is_on;            /* whether hprof is enabled */int hprof_fd = -1;	    /* Non-zero file or socket descriptor. */FILE *hprof_fp = NULL;            /* FILE handle. */int hprof_socket_p = FALSE; /* True if hprof_fd is a socket. */#define HPROF_DEFAULT_TRACE_DEPTH 4int max_trace_depth = HPROF_DEFAULT_TRACE_DEPTH;int prof_trace_depth = HPROF_DEFAULT_TRACE_DEPTH;int thread_in_traces = FALSE;int lineno_in_traces = TRUE;char output_format = 'a';              /* 'b' for binary */float hprof_cutoff_point = (float)0.0001;int dump_on_exit = TRUE;#ifdef HASH_STATSint print_global_hash_stats_on_exit = FALSE;int print_thread_hash_stats_on_exit = FALSE;int print_verbose_hash_stats        = FALSE;#endif /* HASH_STATS */#ifdef WATCH_ALLOCSunsigned int jmethodID_array_peak;unsigned int jmethodID_array_reallocs;unsigned int jmethodID_array_threads;unsigned int jmethodID_array_total;unsigned int method_time_stack_peak;unsigned int method_time_stack_reallocs;unsigned int method_time_stack_threads;int          print_alloc_track_on_exit = FALSE;#endif /* WATCH_ALLOCS */int cpu_sampling = FALSE;int monitor_tracing = FALSE;int heap_dump = FALSE;int alloc_sites = FALSE;/* cpu timing output formats */int cpu_timing = FALSE;int timing_format = NEW_PROF_OUTPUT_FORMAT;jlong total_alloced_bytes;jlong total_alloced_instances;long total_live_bytes = 0;long total_live_instances = 0;/* * PRESERVE THIS LOCK ORDER TO AVOID DEADLOCKS!!! * * hprof_dump_lock => DisableGC/EnableGC => data_access_lock * *//* Data access Lock */JVMPI_RawMonitor data_access_lock;/* Dump lock */JVMPI_RawMonitor hprof_dump_lock;/* profiler interface */JVMPI_Interface *hprof_jvm_interface;unsigned int micro_sec_ticks;/** * Memory allocation and deallocation. */#ifdef WATCH_ALLOCS/* allocation type tracking */static struct {    unsigned int obj_count;	/* #-objects of this allocation type */    unsigned int byte_count;	/* #-bytes used by this allocation type */} alloc_peak[ALLOC_TYPE_MAX], alloc_track[ALLOC_TYPE_MAX];static int n_allocs;		/* #-calls to allocator */static int n_frees;		/* #-calls to free */static void *_hprof_calloc(unsigned int size);void *hprof_calloc(unsigned int size){    return hprof_calloc_tag(ALLOC_TYPE_OTHER, size);}void *hprof_calloc_tag(unsigned int tag, unsigned int size){    unsigned int *buf;    if (tag >= ALLOC_TYPE_MAX) {        fprintf(stderr,	    "HPROF ERROR: %u: invalid tag value on alloc, exiting.\n", tag);	CALL(ProfilerExit)((jint)2);    }					/* get extra space for tag and size */    buf = _hprof_calloc(size + 2 * sizeof(unsigned int));    /* no return check because _hprof_calloc() exits on out of memory */    buf[0] = tag;			/* save the extra info */    buf[1] = size;    alloc_track[tag].obj_count++;    if (alloc_track[tag].obj_count > alloc_peak[tag].obj_count) {	alloc_peak[tag].obj_count = alloc_track[tag].obj_count;    }    alloc_track[tag].byte_count += size;    if (alloc_track[tag].byte_count > alloc_peak[tag].byte_count) {	alloc_peak[tag].byte_count = alloc_track[tag].byte_count;    }    n_allocs++;    return &buf[2];			/* give the caller their memory */}static void hprof_free_hash_tables(void) {    hprof_free_class_table();    if (monitor_tracing) hprof_free_contended_monitor_table();    hprof_free_frame_table();    hprof_free_method_table();    hprof_free_objmap_table();    if (monitor_tracing) hprof_free_raw_monitor_table();    hprof_free_site_table();    hprof_free_thread_table();    hprof_free_trace_table();    /*     * Free name table after thread table since thread table hash     * stats are printed when thread table entries are finished     * and the thread name is used to identify the table.     */    hprof_free_name_table();}static char *alloc_type_name(unsigned int tag) {    switch (tag) {					        /*          1111111111222222 */				                /* 1234567890123456789012345 */    case ALLOC_TYPE_ARRAY:                 return "array";    case ALLOC_TYPE_BUCKET:                return "bucket_t";    case ALLOC_TYPE_CALLFRAME:             return "JVMPI_CallFrame";    case ALLOC_TYPE_CALLTRACE:             return "JVMPI_CallTrace";    case ALLOC_TYPE_CLASS:                 return "class_t";    case ALLOC_TYPE_CONTENDED_MONITOR:     return "contended_monitor_t";    case ALLOC_TYPE_FIELD:                 return "field_t";    case ALLOC_TYPE_FRAME:                 return "frame_t";    case ALLOC_TYPE_FRAMES_COST:           return "frames_cost_t";    case ALLOC_TYPE_GLOBALREF:             return "globalref_t";    case ALLOC_TYPE_JMETHODID:             return "jmethodID";    case ALLOC_TYPE_LIVE_THREAD:           return "live_thread_t";    case ALLOC_TYPE_METHOD:                return "method_t";    case ALLOC_TYPE_METHOD_TIME:           return "method_time_t";    case ALLOC_TYPE_NAME:                  return "name_t";    case ALLOC_TYPE_OBJMAP:                return "objmap_t";    case ALLOC_TYPE_OTHER:                 return "other";    case ALLOC_TYPE_RAW_MONITOR:           return "raw_monitor_t";    case ALLOC_TYPE_SITE:                  return "site_t";    case ALLOC_TYPE_THREAD:                return "thread_t";    case ALLOC_TYPE_THREAD_LOCAL:          return "thread_local_t";    case ALLOC_TYPE_TRACE:                 return "trace-pointers";    default:	switch (tag - ALLOC_TYPE_HASH_TABLES) {        case ALLOC_HASH_CLASS:             return "class_tbl";        case ALLOC_HASH_CONTENDED_MONITOR: return "contended_monitor_tbl";        case ALLOC_HASH_FRAME:             return "frame_tbl";        case ALLOC_HASH_FRAMES_COST:       return "frames_cost_tbl";        case ALLOC_HASH_METHOD:            return "method_tbl";        case ALLOC_HASH_NAME:              return "name_tbl";        case ALLOC_HASH_OBJMAP:            return "objmap_tbl";        case ALLOC_HASH_RAW_MONITOR:       return "raw_monitor_tbl";        case ALLOC_HASH_SITE:              return "site_tbl";        case ALLOC_HASH_THREAD:            return "thread_tbl";        case ALLOC_HASH_TRACE:             return "trace_tbl";	default:                           return "<UNKNOWN>";	}    }}void hprof_print_alloc_track(FILE *fp) {    unsigned int i;			/* scratch index */    unsigned int current_bytes = 0;	/* current total # of bytes */    unsigned int current_objects = 0;	/* current total # of objects */    unsigned int peak_bytes = 0;	/* peak total # of bytes */    unsigned int peak_objects = 0;	/* peak total # of objects */    fprintf(fp, "Allocation Tracking Information\n\n");    fprintf(fp, "#-alloc-calls=%u  #-free-calls=%u\n\n", n_allocs, n_frees);    fprintf(fp, "                       current  current    peak     peak\n");    fprintf(fp, "alloc-type             #-objs   #-bytes   #-objs   #-bytes\n");    fprintf(fp, "=====================  =======  ========  =======  ========\n");    for (i = 0; i < ALLOC_TYPE_MAX; i++) {        if (alloc_peak[i].obj_count == 0 && alloc_peak[i].byte_count == 0) {	    continue;	/* skip entries with no data */	}	fprintf(fp, "%-21s  %7u  %8u  %7u  %8u\n", alloc_type_name(i),	    alloc_track[i].obj_count, alloc_track[i].byte_count,	    alloc_peak[i].obj_count, alloc_peak[i].byte_count);	current_objects += alloc_track[i].obj_count;	current_bytes   += alloc_track[i].byte_count;	peak_objects    += alloc_peak[i].obj_count;	peak_bytes      += alloc_peak[i].byte_count;    }    fprintf(fp, "=====================  =======  ========  =======  ========\n");    fprintf(fp, "%-21s  %7u  %8u  %7u  %8u\n\n", "Totals",	current_objects, current_bytes, peak_objects, peak_bytes);    if (jmethodID_array_peak + method_time_stack_peak > 0) {        fprintf(fp, "Growable Array/Stack Details\n\n");        fprintf(fp, "                   #-reallocs\n");        fprintf(fp, "                   /#-threads  peak-elems  total-elems\n");        fprintf(fp, "=================  ==========  ==========  ===========\n");    }    if (jmethodID_array_peak > 0) {	fprintf(fp, "jmethodID array    %5u/%-4u  %10u  %11u\n",	    jmethodID_array_reallocs, jmethodID_array_threads,	    jmethodID_array_peak, jmethodID_array_total);    }    if (method_time_stack_peak > 0) {	fprintf(fp, "method_time stack  %5u/%-4u  %10u\n",	    method_time_stack_reallocs, method_time_stack_threads,	    method_time_stack_peak);    }}static void *_hprof_calloc(unsigned int size)#else /* !WATCH_ALLOCS */void *hprof_calloc(unsigned int size)#endif /* WATCH_ALLOCS */{    void *p = malloc(size);    if (p == NULL) {        fprintf(stderr, "HPROF ERROR: ***Out of Memory***, exiting.\n");#ifdef WATCH_ALLOCS        hprof_print_alloc_track(stderr);#endif /* WATCH_ALLOCS */	CALL(ProfilerExit)((jint)1);    }    memset(p, 0, size);    return p;}#ifdef WATCH_ALLOCSvoid hprof_free(void *ptr){    if (ptr == NULL) {        fprintf(stderr,	    "HPROF ERROR: NULL pointer passed to hprof_free(), exiting.\n");	CALL(ProfilerExit)((jint)3);    } else {						/* back up to extra info */	unsigned int *buf = (unsigned int *)ptr - 2;	unsigned int tag = buf[0];		/* short hand for tag value */	unsigned int size = buf[1];		/* short hand for size */	if (tag >= ALLOC_TYPE_MAX) {	    fprintf(stderr,		"HPROF ERROR: %u: invalid tag value on free, exiting.\n", tag);	    CALL(ProfilerExit)((jint)4);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?