From de0c788bb4d337d3bc2bb3f6fcac4b26cdccb8b8 Mon Sep 17 00:00:00 2001 From: nari Date: Sat, 4 Aug 2012 14:12:12 +0000 Subject: * gc.c: use inline functions instead of macros, and close up related codes for the profiler. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36619 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 + gc.c | 445 +++++++++++++++++++++++++++++++++++++------------------------- 2 files changed, 274 insertions(+), 176 deletions(-) diff --git a/ChangeLog b/ChangeLog index 887fc47680..2891587285 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sat Aug 4 22:56:20 2012 Narihiro Nakamura + + * gc.c: use inline functions instead of macros, and close up + related codes for the profiler. + Sat Aug 4 20:37:56 2012 Narihiro Nakamura * gc.c (gc_mark_children): use gc_mark_ptr instead of marking diff --git a/gc.c b/gc.c index 99e0ce53ba..71d757276d 100644 --- a/gc.c +++ b/gc.c @@ -116,7 +116,6 @@ static ruby_gc_params_t initial_params = { int ruby_gc_debug_indent = 0; -/* for GC profile */ #ifndef GC_PROFILE_MORE_DETAIL #define GC_PROFILE_MORE_DETAIL 0 #endif @@ -141,143 +140,6 @@ typedef struct gc_profile_record { size_t allocate_limit; } gc_profile_record; -static double -getrusage_time(void) -{ -#ifdef RUSAGE_SELF - struct rusage usage; - struct timeval time; - getrusage(RUSAGE_SELF, &usage); - time = usage.ru_utime; - return time.tv_sec + time.tv_usec * 1e-6; -#elif defined _WIN32 - FILETIME creation_time, exit_time, kernel_time, user_time; - ULARGE_INTEGER ui; - LONG_LONG q; - double t; - - if (GetProcessTimes(GetCurrentProcess(), - &creation_time, &exit_time, &kernel_time, &user_time) == 0) - { - return 0.0; - } - memcpy(&ui, &user_time, sizeof(FILETIME)); - q = ui.QuadPart / 10L; - t = (DWORD)(q % 1000000L) * 1e-6; - q /= 1000000L; -#ifdef __GNUC__ - t += q; -#else - t += (double)(DWORD)(q >> 16) * (1 << 16); - t += (DWORD)q & ~(~0 << 16); -#endif - return t; -#else - return 0.0; -#endif -} - -#define GC_PROF_TIMER_START do {\ - if (objspace->profile.run) {\ - if (!objspace->profile.record) {\ - objspace->profile.size = 1000;\ - objspace->profile.record = malloc(sizeof(gc_profile_record) * objspace->profile.size);\ - }\ - if (count >= objspace->profile.size) {\ - objspace->profile.size += 1000;\ - objspace->profile.record = realloc(objspace->profile.record, sizeof(gc_profile_record) * objspace->profile.size);\ - }\ - if (!objspace->profile.record) {\ - rb_bug("gc_profile malloc or realloc miss");\ - }\ - MEMZERO(&objspace->profile.record[count], gc_profile_record, 1);\ - gc_time = getrusage_time();\ - objspace->profile.record[count].gc_invoke_time = gc_time - objspace->profile.invoke_time;\ - }\ - } while(0) - -#define GC_PROF_TIMER_STOP(marked) do {\ - if (objspace->profile.run) {\ - gc_time = getrusage_time() - gc_time;\ - if (gc_time < 0) gc_time = 0;\ - objspace->profile.record[count].gc_time = gc_time;\ - objspace->profile.record[count].is_marked = !!(marked);\ - GC_PROF_SET_HEAP_INFO(objspace->profile.record[count]);\ - objspace->profile.count++;\ - }\ - } while(0) - -#if GC_PROFILE_MORE_DETAIL -#define INIT_GC_PROF_PARAMS double gc_time = 0, sweep_time = 0;\ - size_t count = objspace->profile.count, total = 0, live = 0 - -#define GC_PROF_MARK_TIMER_START double mark_time = 0;\ - do {\ - if (objspace->profile.run) {\ - mark_time = getrusage_time();\ - }\ - } while(0) - -#define GC_PROF_MARK_TIMER_STOP do {\ - if (objspace->profile.run) {\ - mark_time = getrusage_time() - mark_time;\ - if (mark_time < 0) mark_time = 0;\ - objspace->profile.record[objspace->profile.count].gc_mark_time = mark_time;\ - }\ - } while(0) - -#define GC_PROF_SWEEP_TIMER_START do {\ - if (objspace->profile.run) {\ - sweep_time = getrusage_time();\ - }\ - } while(0) - -#define GC_PROF_SWEEP_TIMER_STOP do {\ - if (objspace->profile.run) {\ - sweep_time = getrusage_time() - sweep_time;\ - if (sweep_time < 0) sweep_time = 0;\ - objspace->profile.record[count].gc_sweep_time = sweep_time;\ - }\ - } while(0) -#define GC_PROF_SET_MALLOC_INFO do {\ - if (objspace->profile.run) {\ - gc_profile_record *record = &objspace->profile.record[objspace->profile.count];\ - record->allocate_increase = malloc_increase;\ - record->allocate_limit = malloc_limit; \ - }\ - } while(0) -#define GC_PROF_SET_HEAP_INFO(record) do {\ - live = objspace->heap.live_num;\ - total = heaps_used * HEAP_OBJ_LIMIT;\ - (record).heap_use_slots = heaps_used;\ - (record).heap_live_objects = live;\ - (record).heap_free_objects = total - live;\ - (record).heap_total_objects = total;\ - (record).have_finalize = deferred_final_list ? Qtrue : Qfalse;\ - (record).heap_use_size = live * sizeof(RVALUE);\ - (record).heap_total_size = total * sizeof(RVALUE);\ - } while(0) -#define GC_PROF_INC_LIVE_NUM objspace->heap.live_num++ -#define GC_PROF_DEC_LIVE_NUM objspace->heap.live_num-- -#else -#define INIT_GC_PROF_PARAMS double gc_time = 0;\ - size_t count = objspace->profile.count, total = 0, live = 0 -#define GC_PROF_MARK_TIMER_START -#define GC_PROF_MARK_TIMER_STOP -#define GC_PROF_SWEEP_TIMER_START -#define GC_PROF_SWEEP_TIMER_STOP -#define GC_PROF_SET_MALLOC_INFO -#define GC_PROF_SET_HEAP_INFO(record) do {\ - live = objspace->heap.live_num;\ - total = heaps_used * HEAP_OBJ_LIMIT;\ - (record).heap_total_objects = total;\ - (record).heap_use_size = live * sizeof(RVALUE);\ - (record).heap_total_size = total * sizeof(RVALUE);\ - } while(0) -#define GC_PROF_INC_LIVE_NUM -#define GC_PROF_DEC_LIVE_NUM -#endif - #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__) #pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */ @@ -577,6 +439,17 @@ static void run_final(rb_objspace_t *objspace, VALUE obj); static int garbage_collect(rb_objspace_t *objspace); static int gc_lazy_sweep(rb_objspace_t *objspace); +static double getrusage_time(void); +static inline void gc_prof_timer_start(rb_objspace_t *); +static inline void gc_prof_timer_stop(rb_objspace_t *, int); +static inline void gc_prof_mark_timer_start(rb_objspace_t *); +static inline void gc_prof_mark_timer_stop(rb_objspace_t *); +static inline void gc_prof_sweep_timer_start(rb_objspace_t *); +static inline void gc_prof_sweep_timer_stop(rb_objspace_t *); +static inline void gc_prof_set_malloc_info(rb_objspace_t *); +static inline void gc_prof_inc_live_num(rb_objspace_t *); +static inline void gc_prof_dec_live_num(rb_objspace_t *); + void rb_global_variable(VALUE *var) { @@ -709,23 +582,6 @@ gc_profile_disable(void) return Qnil; } -/* - * call-seq: - * GC::Profiler.clear -> nil - * - * Clears the GC profiler data. - * - */ - -static VALUE -gc_profile_clear(void) -{ - rb_objspace_t *objspace = &rb_objspace; - MEMZERO(objspace->profile.record, gc_profile_record, objspace->profile.size); - objspace->profile.count = 0; - return Qnil; -} - static void * negative_size_allocation_error_with_gvl(void *ptr) { @@ -1363,7 +1219,7 @@ rb_newobj(void) RANY(obj)->file = rb_sourcefile(); RANY(obj)->line = rb_sourceline(); #endif - GC_PROF_INC_LIVE_NUM; + gc_prof_inc_live_num(objspace); return obj; } @@ -2150,7 +2006,7 @@ finalize_list(rb_objspace_t *objspace, RVALUE *p) if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */ add_slot_local_freelist(objspace, p); if (!is_lazy_sweeping(objspace)) { - GC_PROF_DEC_LIVE_NUM; + gc_prof_dec_live_num(objspace); } } else { @@ -2330,8 +2186,8 @@ static void after_gc_sweep(rb_objspace_t *objspace) { size_t inc; - GC_PROF_SET_MALLOC_INFO; + gc_prof_set_malloc_info(objspace); if (objspace->heap.free_num < objspace->heap.free_min) { set_heaps_increment(objspace); heaps_increment(objspace); @@ -2381,7 +2237,6 @@ static int gc_lazy_sweep(rb_objspace_t *objspace) { int res; - INIT_GC_PROF_PARAMS; if (objspace->flags.dont_lazy_sweep) return garbage_collect(objspace); @@ -2390,15 +2245,15 @@ gc_lazy_sweep(rb_objspace_t *objspace) if (!ready_to_gc(objspace)) return TRUE; during_gc++; - GC_PROF_TIMER_START; - GC_PROF_SWEEP_TIMER_START; + gc_prof_timer_start(objspace); + gc_prof_sweep_timer_start(objspace); if (objspace->heap.sweep_slots) { res = lazy_sweep(objspace); if (res) { - GC_PROF_SWEEP_TIMER_STOP; - GC_PROF_SET_MALLOC_INFO; - GC_PROF_TIMER_STOP(Qfalse); + gc_prof_sweep_timer_stop(objspace); + gc_prof_set_malloc_info(objspace); + gc_prof_timer_stop(objspace, Qfalse); return res; } after_gc_sweep(objspace); @@ -2417,7 +2272,7 @@ gc_lazy_sweep(rb_objspace_t *objspace) set_heaps_increment(objspace); } - GC_PROF_SWEEP_TIMER_START; + gc_prof_sweep_timer_start(objspace); if (!(res = lazy_sweep(objspace))) { after_gc_sweep(objspace); if (has_free_object) { @@ -2425,9 +2280,9 @@ gc_lazy_sweep(rb_objspace_t *objspace) during_gc = 0; } } - GC_PROF_SWEEP_TIMER_STOP; + gc_prof_sweep_timer_stop(objspace); - GC_PROF_TIMER_STOP(Qtrue); + gc_prof_timer_stop(objspace, Qtrue); return res; } @@ -2459,7 +2314,7 @@ rb_gc_force_recycle(VALUE p) add_slot_local_freelist(objspace, (RVALUE *)p); } else { - GC_PROF_DEC_LIVE_NUM; + gc_prof_dec_live_num(objspace); slot = add_slot_local_freelist(objspace, (RVALUE *)p); if (slot->free_next == NULL) { link_free_heap_slot(objspace, slot); @@ -2664,7 +2519,7 @@ gc_marks(rb_objspace_t *objspace) { struct gc_list *list; rb_thread_t *th = GET_THREAD(); - GC_PROF_MARK_TIMER_START; + gc_prof_mark_timer_start(objspace); objspace->heap.live_num = 0; objspace->count++; @@ -2707,14 +2562,12 @@ gc_marks(rb_objspace_t *objspace) gc_mark_rest(objspace); } } - GC_PROF_MARK_TIMER_STOP; + gc_prof_mark_timer_stop(objspace); } static int garbage_collect(rb_objspace_t *objspace) { - INIT_GC_PROF_PARAMS; - if (GC_NOTIFY) printf("start garbage_collect()\n"); if (!heaps) { @@ -2724,18 +2577,18 @@ garbage_collect(rb_objspace_t *objspace) return TRUE; } - GC_PROF_TIMER_START; + gc_prof_timer_start(objspace); rest_sweep(objspace); during_gc++; gc_marks(objspace); - GC_PROF_SWEEP_TIMER_START; + gc_prof_sweep_timer_start(objspace); gc_sweep(objspace); - GC_PROF_SWEEP_TIMER_STOP; + gc_prof_sweep_timer_stop(objspace); - GC_PROF_TIMER_STOP(Qtrue); + gc_prof_timer_stop(objspace, Qtrue); if (GC_NOTIFY) printf("end garbage_collect()\n"); return TRUE; } @@ -3866,6 +3719,246 @@ gc_malloc_allocations(VALUE self) } #endif +/* + ------------------------------ GC profiler ------------------------------ +*/ + +static inline void gc_prof_set_heap_info(rb_objspace_t *, gc_profile_record *); + +static double +getrusage_time(void) +{ +#ifdef RUSAGE_SELF + struct rusage usage; + struct timeval time; + getrusage(RUSAGE_SELF, &usage); + time = usage.ru_utime; + return time.tv_sec + time.tv_usec * 1e-6; +#elif defined _WIN32 + FILETIME creation_time, exit_time, kernel_time, user_time; + ULARGE_INTEGER ui; + LONG_LONG q; + double t; + + if (GetProcessTimes(GetCurrentProcess(), + &creation_time, &exit_time, &kernel_time, &user_time) == 0) + { + return 0.0; + } + memcpy(&ui, &user_time, sizeof(FILETIME)); + q = ui.QuadPart / 10L; + t = (DWORD)(q % 1000000L) * 1e-6; + q /= 1000000L; +#ifdef __GNUC__ + t += q; +#else + t += (double)(DWORD)(q >> 16) * (1 << 16); + t += (DWORD)q & ~(~0 << 16); +#endif + return t; +#else + return 0.0; +#endif +} + +static inline void +gc_prof_timer_start(rb_objspace_t *objspace) +{ + if (objspace->profile.run) { + size_t count = objspace->profile.count; + + if (!objspace->profile.record) { + objspace->profile.size = 1000; + objspace->profile.record = malloc(sizeof(gc_profile_record) * objspace->profile.size); + } + if (count >= objspace->profile.size) { + objspace->profile.size += 1000; + objspace->profile.record = realloc(objspace->profile.record, sizeof(gc_profile_record) * objspace->profile.size); + } + if (!objspace->profile.record) { + rb_bug("gc_profile malloc or realloc miss"); + } + MEMZERO(&objspace->profile.record[count], gc_profile_record, 1); + objspace->profile.record[count].gc_time = getrusage_time(); + objspace->profile.record[objspace->profile.count].gc_invoke_time = + objspace->profile.record[count].gc_time - objspace->profile.invoke_time; + } +} + +static inline void +gc_prof_timer_stop(rb_objspace_t *objspace, int marked) +{ + if (objspace->profile.run) { + double gc_time = 0; + size_t count = objspace->profile.count; + gc_profile_record *record = &objspace->profile.record[count]; + + gc_time = getrusage_time() - record->gc_time; + if (gc_time < 0) gc_time = 0; + record->gc_time = gc_time; + record->is_marked = !!(marked); + gc_prof_set_heap_info(objspace, record); + objspace->profile.count++; + } +} + +#if !GC_PROFILE_MORE_DETAIL + +static inline void +gc_prof_mark_timer_start(rb_objspace_t *objspace) +{ +} + +static inline void +gc_prof_mark_timer_stop(rb_objspace_t *objspace) +{ +} + +static inline void +gc_prof_sweep_timer_start(rb_objspace_t *objspace) +{ +} + +static inline void +gc_prof_sweep_timer_stop(rb_objspace_t *objspace) +{ +} + +static inline void +gc_prof_set_malloc_info(rb_objspace_t *objspace) +{ +} + +static inline void +gc_prof_set_heap_info(rb_objspace_t *objspace, gc_profile_record *record) +{ + size_t live = objspace->heap.live_num; + size_t total = heaps_used * HEAP_OBJ_LIMIT; + + record->heap_total_objects = total; + record->heap_use_size = live * sizeof(RVALUE); + record->heap_total_size = total * sizeof(RVALUE); +} + +static inline void +gc_prof_inc_live_num(rb_objspace_t *objspace) +{ +} + +static inline void +gc_prof_dec_live_num(rb_objspace_t *objspace) +{ +} + +#else + +static inline void +gc_prof_mark_timer_start(rb_objspace_t *objspace) +{ + if (objspace->profile.run) { + size_t count = objspace->profile.count; + + objspace->profile.record[count].gc_mark_time = getrusage_time(); + } +} + +static inline void +gc_prof_mark_timer_stop(rb_objspace_t *objspace) +{ + if (objspace->profile.run) { + double mark_time = 0; + size_t count = count; + gc_profile_record *record = &objspace->profile.record[count]; + + mark_time = getrusage_time() - record->gc_mark_time; + if (mark_time < 0) mark_time = 0; + record->gc_mark_time = mark_time; + } +} + +static inline void +gc_prof_sweep_timer_start(rb_objspace_t *objspace) +{ + if (objspace->profile.run) { + size_t count = objspace->profile.count; + + objspace->profile.record[count].gc_sweep_time = getrusage_time(); + } +} + +static inline void +gc_prof_sweep_timer_stop(rb_objspace_t *objspace) +{ + if (objspace->profile.run) { + double sweep_time = 0; + size_t count = objspace->profile.count; + gc_profile_record *record = &objspace->profile.record[count]; + + sweep_time = getrusage_time() - record->gc_sweep_time;\ + if (sweep_time < 0) sweep_time = 0;\ + record->gc_sweep_time = sweep_time; + } +} + +static inline void +gc_prof_set_malloc_info(rb_objspace_t *objspace) +{ + if (objspace->profile.run) { + gc_profile_record *record = &objspace->profile.record[objspace->profile.count]; + if (record) { + record->allocate_increase = malloc_increase; + record->allocate_limit = malloc_limit; + } + } +} + +static inline void +gc_prof_set_heap_info(rb_objspace_t *objspace, gc_profile_record *record) +{ + size_t live = objspace->heap.live_num; + size_t total = heaps_used * HEAP_OBJ_LIMIT; + + record->heap_use_slots = heaps_used; + record->heap_live_objects = live; + record->heap_free_objects = total - live; + record->heap_total_objects = total; + record->have_finalize = deferred_final_list ? Qtrue : Qfalse; + record->heap_use_size = live * sizeof(RVALUE); + record->heap_total_size = total * sizeof(RVALUE); +} + +static inline void +gc_prof_inc_live_num(rb_objspace_t *objspace) +{ + objspace->heap.live_num++; +} + +static inline void +gc_prof_dec_live_num(rb_objspace_t *objspace) +{ + objspace->heap.live_num--; +} + +#endif /* !GC_PROFILE_MORE_DETAIL */ + + +/* + * call-seq: + * GC::Profiler.clear -> nil + * + * Clears the GC profiler data. + * + */ + +static VALUE +gc_profile_clear(void) +{ + rb_objspace_t *objspace = &rb_objspace; + MEMZERO(objspace->profile.record, gc_profile_record, objspace->profile.size); + objspace->profile.count = 0; + return Qnil; +} + /* * call-seq: * GC::Profiler.raw_data -> [Hash, ...] -- cgit v1.2.3