ruby-changes:31919
From: ko1 <ko1@a...>
Date: Thu, 5 Dec 2013 13:54:26 +0900 (JST)
Subject: [ruby-changes:31919] ko1:r43998 (trunk): * gc.c (vm_malloc_size): added.
ko1 2013-12-05 13:54:20 +0900 (Thu, 05 Dec 2013) New Revision: 43998 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43998 Log: * gc.c (vm_malloc_size): added. return malloc_usable_size() if possible. * gc.c (MALLOC_ALLOCATED_SIZE): add new setting macro to enable GC.allocated_size. If platform supports `malloc_usable_size()' (or similar one), GC.allocated_size can be implemented with this function. Default is 0. * gc.c (vm_xmalloc, vm_xrealloc, vm_xfree): use vm_malloc_size() to detect collect allocated size. * gc.c (vm_malloc_increase): refactoring. Modified files: trunk/ChangeLog trunk/gc.c Index: ChangeLog =================================================================== --- ChangeLog (revision 43997) +++ ChangeLog (revision 43998) @@ -1,3 +1,19 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Dec 5 13:47:15 2013 Koichi Sasada <ko1@a...> + + * gc.c (vm_malloc_size): added. + return malloc_usable_size() if possible. + + * gc.c (MALLOC_ALLOCATED_SIZE): add new setting macro to enable + GC.allocated_size. + If platform supports `malloc_usable_size()' (or similar one), + GC.allocated_size can be implemented with this function. + Default is 0. + + * gc.c (vm_xmalloc, vm_xrealloc, vm_xfree): use vm_malloc_size() + to detect collect allocated size. + + * gc.c (vm_malloc_increase): refactoring. + Thu Dec 5 13:19:03 2013 Aman Gupta <ruby@t...> * include/ruby/ruby.h: remove INTERNAL_EVENT_GC_END and replace with Index: gc.c =================================================================== --- gc.c (revision 43997) +++ gc.c (revision 43998) @@ -240,8 +240,15 @@ static ruby_gc_params_t gc_params = { https://github.com/ruby/ruby/blob/trunk/gc.c#L240 #ifndef CALC_EXACT_MALLOC_SIZE #define CALC_EXACT_MALLOC_SIZE 0 #endif -#ifndef CALC_EXACT_MALLOC_SIZE_CHECK_OLD_SIZE -#define CALC_EXACT_MALLOC_SIZE_CHECK_OLD_SIZE 0 +#if defined(HAVE_MALLOC_USABLE_SIZE) || CALC_EXACT_MALLOC_SIZE > 0 +#ifndef MALLOC_ALLOCATED_SIZE +#define MALLOC_ALLOCATED_SIZE 0 +#endif +#else +#define MALLOC_ALLOCATED_SIZE 0 +#endif +#ifndef MALLOC_ALLOCATED_SIZE_CHECK +#define MALLOC_ALLOCATED_SIZE_CHECK 0 #endif typedef enum { @@ -299,7 +306,7 @@ typedef struct gc_profile_record { https://github.com/ruby/ruby/blob/trunk/gc.c#L306 long majflt; #endif #endif -#if CALC_EXACT_MALLOC_SIZE +#if MALLOC_ALLOCATED_SIZE size_t allocated_size; #endif @@ -405,7 +412,7 @@ typedef struct rb_objspace { https://github.com/ruby/ruby/blob/trunk/gc.c#L412 struct { size_t limit; size_t increase; -#if CALC_EXACT_MALLOC_SIZE +#if MALLOC_ALLOCATED_SIZE size_t allocated_size; size_t allocations; #endif @@ -5595,8 +5602,24 @@ aligned_free(void *ptr) https://github.com/ruby/ruby/blob/trunk/gc.c#L5602 #endif } +static inline size_t +vm_malloc_size(rb_objspace_t *objspace, void *ptr, size_t hint) +{ +#ifdef HAVE_MALLOC_USABLE_SIZE + return malloc_usable_size(ptr); +#else + return hint; +#endif +} + +enum memop_type { + MEMOP_TYPE_MALLOC = 1, + MEMOP_TYPE_FREE = 2, + MEMOP_TYPE_REALLOC = 3 +}; + static void -vm_malloc_increase(rb_objspace_t *objspace, size_t new_size, size_t old_size, int do_gc) +vm_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, size_t old_size, enum memop_type type) { if (new_size > old_size) { ATOMIC_SIZE_ADD(malloc_increase, new_size - old_size); @@ -5613,7 +5636,7 @@ vm_malloc_increase(rb_objspace_t *objspa https://github.com/ruby/ruby/blob/trunk/gc.c#L5636 } } - if (do_gc) { + if (type == MEMOP_TYPE_MALLOC) { if (ruby_gc_stress && !ruby_disable_gc_stress) { garbage_collect_with_gvl(objspace, FALSE, TRUE, GPR_FLAG_MALLOC); } @@ -5628,6 +5651,58 @@ vm_malloc_increase(rb_objspace_t *objspa https://github.com/ruby/ruby/blob/trunk/gc.c#L5651 } } } + +#if MALLOC_ALLOCATED_SIZE + if (new_size >= old_size) { + ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, new_size - old_size); + } + else { + size_t dec_size = old_size - new_size; + while (1) { + size_t allocated_size = objspace->malloc_params.allocated_size; + size_t next_allocated_size; + + if (allocated_size > dec_size) { + next_allocated_size = allocated_size - dec_size; + } + else { +#if MALLOC_ALLOCATED_SIZE_CHECK + rb_bug("vm_malloc_increase: underflow malloc_params.allocated_size."); +#endif + next_allocated_size = 0; + } + if (ATOMIC_SIZE_CAS(objspace->malloc_params.allocated_size, allocated_size, next_allocated_size) == allocated_size) break; + } + } + + if (0) fprintf(stderr, "incraese - ptr: %p, type: %s, new_size: %d, old_size: %d\n", + mem, + type == MEMOP_TYPE_MALLOC ? "malloc" : + type == MEMOP_TYPE_FREE ? "free " : + type == MEMOP_TYPE_REALLOC ? "realloc": "error", + (int)new_size, (int)old_size); + + switch (type) { + case MEMOP_TYPE_MALLOC: + ATOMIC_SIZE_INC(objspace->malloc_params.allocations); + break; + case MEMOP_TYPE_FREE: + while (1) { + size_t allocations = objspace->malloc_params.allocations; + if (allocations > 0) { + if (ATOMIC_SIZE_CAS(objspace->malloc_params.allocations, allocations, allocations - 1) == allocations) break; + } + else { +#if MALLOC_ALLOCATED_SIZE_CHECK + assert(objspace->malloc_params.allocations > 0); +#endif + break; + } + } + break; + case MEMOP_TYPE_REALLOC: /* ignore */ break; + } +#endif } static inline size_t @@ -5642,8 +5717,6 @@ vm_malloc_prepare(rb_objspace_t *objspac https://github.com/ruby/ruby/blob/trunk/gc.c#L5717 size += sizeof(size_t); #endif - vm_malloc_increase(objspace, size, 0, TRUE); - return size; } @@ -5651,8 +5724,6 @@ static inline void * https://github.com/ruby/ruby/blob/trunk/gc.c#L5724 vm_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size) { #if CALC_EXACT_MALLOC_SIZE - ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, size); - ATOMIC_SIZE_INC(objspace->malloc_params.allocations); ((size_t *)mem)[0] = size; mem = (size_t *)mem + 1; #endif @@ -5675,6 +5746,8 @@ vm_xmalloc(rb_objspace_t *objspace, size https://github.com/ruby/ruby/blob/trunk/gc.c#L5746 size = vm_malloc_prepare(objspace, size); TRY_WITH_GC(mem = malloc(size)); + size = vm_malloc_size(objspace, mem, size); + vm_malloc_increase(objspace, mem, size, 0, MEMOP_TYPE_MALLOC); return vm_malloc_fixup(objspace, mem, size); } @@ -5682,9 +5755,6 @@ static void * https://github.com/ruby/ruby/blob/trunk/gc.c#L5755 vm_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t old_size) { void *mem; -#if CALC_EXACT_MALLOC_SIZE - size_t cem_oldsize; -#endif if ((ssize_t)new_size < 0) { negative_size_allocation_error("negative re-allocation size"); @@ -5702,30 +5772,23 @@ vm_xrealloc(rb_objspace_t *objspace, voi https://github.com/ruby/ruby/blob/trunk/gc.c#L5772 return 0; } -#ifdef HAVE_MALLOC_USABLE_SIZE - old_size = malloc_usable_size(ptr); -#endif - - vm_malloc_increase(objspace, new_size, old_size, FALSE); - #if CALC_EXACT_MALLOC_SIZE new_size += sizeof(size_t); ptr = (size_t *)ptr - 1; - cem_oldsize = ((size_t *)ptr)[0]; - - if (CALC_EXACT_MALLOC_SIZE_CHECK_OLD_SIZE && old_size > 0 && cem_oldsize - sizeof(size_t) != old_size) { - fprintf(stderr, "vm_xrealloc: old_size mismatch: expected %d, but %d\n", (int)(cem_oldsize-sizeof(size_t)), (int)old_size); - } + oldsize = ((size_t *)ptr)[0]; #endif + old_size = vm_malloc_size(objspace, ptr, old_size); TRY_WITH_GC(mem = realloc(ptr, new_size)); + new_size = vm_malloc_size(objspace, mem, new_size); #if CALC_EXACT_MALLOC_SIZE - ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, new_size - cem_oldsize); ((size_t *)mem)[0] = new_size; mem = (size_t *)mem + 1; #endif + vm_malloc_increase(objspace, mem, new_size, old_size, MEMOP_TYPE_REALLOC); + return mem; } @@ -5733,27 +5796,14 @@ static void https://github.com/ruby/ruby/blob/trunk/gc.c#L5796 vm_xfree(rb_objspace_t *objspace, void *ptr, size_t old_size) { #if CALC_EXACT_MALLOC_SIZE - size_t cem_oldsize; ptr = ((size_t *)ptr) - 1; - cem_oldsize = ((size_t*)ptr)[0]; - if (cem_oldsize) { - ATOMIC_SIZE_SUB(objspace->malloc_params.allocated_size, cem_oldsize); - ATOMIC_SIZE_DEC(objspace->malloc_params.allocations); - } -#endif - -#ifdef HAVE_MALLOC_USABLE_SIZE - old_size = malloc_usable_size(ptr); -#endif - -#if CALC_EXACT_MALLOC_SIZE - if (CALC_EXACT_MALLOC_SIZE_CHECK_OLD_SIZE && old_size > 0 && cem_oldsize - sizeof(size_t) != old_size) { - fprintf(stderr, "vm_xfree: old_size mismatch: expected %d, but %d\n", (int)(cem_oldsize-sizeof(size_t)), (int)old_size); - } + oldsize = ((size_t*)ptr)[0]; #endif - vm_malloc_increase(objspace, 0, old_size, FALSE); + old_size = vm_malloc_size(objspace, ptr, old_size); free(ptr); + + vm_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE); } void * @@ -5868,7 +5918,7 @@ ruby_mimfree(void *ptr) https://github.com/ruby/ruby/blob/trunk/gc.c#L5918 free(mem); } -#if CALC_EXACT_MALLOC_SIZE +#if MALLOC_ALLOCATED_SIZE /* * call-seq: * GC.malloc_allocated_size -> Integer @@ -6323,7 +6373,7 @@ gc_prof_setup_new_record(rb_objspace_t * https://github.com/ruby/ruby/blob/trunk/gc.c#L6373 /* setup before-GC parameter */ record->flags = reason | ((ruby_gc_stress && !ruby_disable_gc_stress) ? GPR_FLAG_STRESS : 0); -#if CALC_EXACT_MALLOC_SIZE +#if MALLOC_ALLOCATED_SIZE record->allocated_size = malloc_allocated_size; #endif #if GC_PROFILE_DETAIL_MEMORY @@ -7133,7 +7183,7 @@ Init_GC(void) https://github.com/ruby/ruby/blob/trunk/gc.c#L7183 rb_include_module(rb_cWeakMap, rb_mEnumerable); } -#if CALC_EXACT_MALLOC_SIZE +#if MALLOC_ALLOCATED_SIZE rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0); rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0); #endif @@ -7153,7 +7203,8 @@ Init_GC(void) https://github.com/ruby/ruby/blob/trunk/gc.c#L7203 OPT(GC_PROFILE_MORE_DETAIL); OPT(GC_ENABLE_LAZY_SWEEP); OPT(CALC_EXACT_MALLOC_SIZE); - OPT(CALC_EXACT_MALLOC_SIZE_CHECK_OLD_SIZE); + OPT(MALLOC_ALLOCATED_SIZE); + OPT(MALLOC_ALLOCATED_SIZE_CHECK); OPT(GC_PROFILE_DETAIL_MEMORY); #undef OPT } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/