static void malloc_trace_start() { static int inserted = 0; if (!inserted) inserted = 1; else return; if (!malloc_usable_size) { malloc_usable_size = bin_find_symbol("MallocExtension_GetAllocatedSize", NULL, 1); if (!malloc_usable_size) { dbg_printf("tcmalloc was not found...\n"); malloc_usable_size = bin_find_symbol("malloc_usable_size", NULL, 1); } if (!malloc_usable_size) { dbg_printf("malloc_usable_size was not found...\n"); malloc_usable_size = bin_find_symbol("malloc_size", NULL, 1); } assert(malloc_usable_size != NULL); dbg_printf("malloc_usable_size: %p\n", malloc_usable_size); } insert_tramp("malloc", malloc_tramp); insert_tramp("realloc", realloc_tramp); insert_tramp("calloc", calloc_tramp); insert_tramp("free", free_tramp); }
static void mysql_trace_start() { static int inserted = 0; if (!inserted) inserted = 1; else return; orig_real_query = bin_find_symbol("mysql_real_query", NULL, 1); if (orig_real_query) insert_tramp("mysql_real_query", real_query_tramp); orig_send_query = bin_find_symbol("mysql_send_query", NULL, 1); if (orig_send_query) insert_tramp("mysql_send_query", send_query_tramp); }
static void init_cpyprof(void) { if (!Original_PyEval_EvalFrameEx) { Original_PyEval_EvalFrameEx = PyEval_EvalFrameEx; // monkey-patch PyEval_EvalFrameEx init_memprof_config_base(); bin_init(); create_tramp_table(); size_t tramp_size; tramp_start = insert_tramp("PyEval_EvalFrameEx", &cpyprof_PyEval_EvalFrameEx, &tramp_size); tramp_end = tramp_start + tramp_size; } if (!Original_code_dealloc) { Original_code_dealloc = PyCode_Type.tp_dealloc; PyCode_Type.tp_dealloc = &cpyprof_code_dealloc; } }
static VALUE memprof_dump(int argc, VALUE *argv, VALUE self) { VALUE str; FILE *out = NULL; if (!track_objs) rb_raise(rb_eRuntimeError, "object tracking disabled, call Memprof.start first"); rb_scan_args(argc, argv, "01", &str); if (RTEST(str)) { out = fopen(StringValueCStr(str), "w"); if (!out) rb_raise(rb_eArgError, "unable to open output file"); } yajl_gen_config conf = { .beautify = 1, .indentString = " " }; yajl_gen gen = yajl_gen_alloc2((yajl_print_t)&json_print, &conf, NULL, (void*)out); track_objs = 0; yajl_gen_array_open(gen); st_foreach(objs, objs_each_dump, (st_data_t)gen); yajl_gen_array_close(gen); yajl_gen_free(gen); if (out) fclose(out); track_objs = 1; return Qnil; } static VALUE memprof_dump_all(int argc, VALUE *argv, VALUE self) { char *heaps = *(char**)bin_find_symbol("heaps",0); int heaps_used = *(int*)bin_find_symbol("heaps_used",0); #ifndef sizeof__RVALUE size_t sizeof__RVALUE = bin_type_size("RVALUE"); #endif #ifndef sizeof__heaps_slot size_t sizeof__heaps_slot = bin_type_size("heaps_slot"); #endif #ifndef offset__heaps_slot__limit int offset__heaps_slot__limit = bin_type_member_offset("heaps_slot", "limit"); #endif #ifndef offset__heaps_slot__slot int offset__heaps_slot__slot = bin_type_member_offset("heaps_slot", "slot"); #endif char *p, *pend; int i, limit; if (sizeof__RVALUE == 0 || sizeof__heaps_slot == 0) rb_raise(eUnsupported, "could not find internal heap"); VALUE str; FILE *out = NULL; rb_scan_args(argc, argv, "01", &str); if (RTEST(str)) { out = fopen(StringValueCStr(str), "w"); if (!out) rb_raise(rb_eArgError, "unable to open output file"); } yajl_gen_config conf = { .beautify = 0, .indentString = " " }; yajl_gen gen = yajl_gen_alloc2((yajl_print_t)&json_print, &conf, NULL, (void*)out); track_objs = 0; //yajl_gen_array_open(gen); for (i=0; i < heaps_used; i++) { p = *(char**)(heaps + (i * sizeof__heaps_slot) + offset__heaps_slot__slot); limit = *(int*)(heaps + (i * sizeof__heaps_slot) + offset__heaps_slot__limit); pend = p + (sizeof__RVALUE * limit); while (p < pend) { if (RBASIC(p)->flags) { obj_dump((VALUE)p, gen); // XXX ugh yajl_gen_clear(gen); yajl_gen_free(gen); gen = yajl_gen_alloc2((yajl_print_t)&json_print, &conf, NULL, (void*)out); while(fputc('\n', out ? out : stdout) == EOF); } p += sizeof__RVALUE; } } //yajl_gen_array_close(gen); yajl_gen_clear(gen); yajl_gen_free(gen); if (out) fclose(out); track_objs = 1; return Qnil; } void Init_memprof() { VALUE memprof = rb_define_module("Memprof"); eUnsupported = rb_define_class_under(memprof, "Unsupported", rb_eStandardError); rb_define_singleton_method(memprof, "start", memprof_start, 0); rb_define_singleton_method(memprof, "stop", memprof_stop, 0); rb_define_singleton_method(memprof, "stats", memprof_stats, -1); rb_define_singleton_method(memprof, "stats!", memprof_stats_bang, -1); rb_define_singleton_method(memprof, "track", memprof_track, -1); rb_define_singleton_method(memprof, "dump", memprof_dump, -1); rb_define_singleton_method(memprof, "dump_all", memprof_dump_all, -1); pagesize = getpagesize(); objs = st_init_numtable(); bin_init(); create_tramp_table(); gc_hook = Data_Wrap_Struct(rb_cObject, sourcefile_marker, NULL, NULL); rb_global_variable(&gc_hook); ptr_to_rb_mark_table_add_filename = bin_find_symbol("rb_mark_table_add_filename", NULL); rb_classname = bin_find_symbol("classname", 0); rb_add_freelist = bin_find_symbol("add_freelist", 0); insert_tramp("rb_newobj", newobj_tramp); insert_tramp("add_freelist", freelist_tramp); if (getenv("MEMPROF")) track_objs = 1; return; }