diff options
author | Koichi Sasada <ko1@atdot.net> | 2020-12-05 06:15:17 +0900 |
---|---|---|
committer | Koichi Sasada <ko1@atdot.net> | 2020-12-07 08:28:36 +0900 |
commit | 307732ccee7f9f28f8422bab2f839da021d8cdec (patch) | |
tree | f39ec33d41cbcbaf07bcc1a8d34dc3047357ca6e /transient_heap.c | |
parent | b67b24d0f5e78481e6a306881b6858f0dec996ba (diff) | |
download | ruby-307732ccee7f9f28f8422bab2f839da021d8cdec.tar.gz |
cancel theap on multi-ractors
accessing theap needs complicating synchronization but it reduce
performance on multi-ractor mode. So simply stop using theap
on multi-ractor mode. In future, theap should be replaced with
more cleaver memory strategy.
Diffstat (limited to 'transient_heap.c')
-rw-r--r-- | transient_heap.c | 136 |
1 files changed, 69 insertions, 67 deletions
diff --git a/transient_heap.c b/transient_heap.c index 357e4a4656..5b6fd89889 100644 --- a/transient_heap.c +++ b/transient_heap.c @@ -364,74 +364,72 @@ transient_heap_allocatable_header(struct transient_heap* theap, size_t size) void * rb_transient_heap_alloc(VALUE obj, size_t req_size) { - void *ret; + // only on single main ractor + if (ruby_single_main_ractor == NULL) return NULL; - RB_VM_LOCK_ENTER(); - { - struct transient_heap* theap = transient_heap_get(); - size_t size = ROUND_UP(req_size + sizeof(struct transient_alloc_header), TRANSIENT_HEAP_ALLOC_ALIGN); + void *ret; + struct transient_heap* theap = transient_heap_get(); + size_t size = ROUND_UP(req_size + sizeof(struct transient_alloc_header), TRANSIENT_HEAP_ALLOC_ALIGN); - TH_ASSERT(RB_TYPE_P(obj, T_ARRAY) || - RB_TYPE_P(obj, T_OBJECT) || - RB_TYPE_P(obj, T_STRUCT) || - RB_TYPE_P(obj, T_HASH)); /* supported types */ + TH_ASSERT(RB_TYPE_P(obj, T_ARRAY) || + RB_TYPE_P(obj, T_OBJECT) || + RB_TYPE_P(obj, T_STRUCT) || + RB_TYPE_P(obj, T_HASH)); /* supported types */ - if (size > TRANSIENT_HEAP_ALLOC_MAX) { - if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [too big: %ld] %s\n", (long)size, rb_obj_info(obj)); - ret = NULL; - } + if (size > TRANSIENT_HEAP_ALLOC_MAX) { + if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [too big: %ld] %s\n", (long)size, rb_obj_info(obj)); + ret = NULL; + } #if TRANSIENT_HEAP_DEBUG_DONT_PROMOTE == 0 - else if (RB_OBJ_PROMOTED_RAW(obj)) { - if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [promoted object] %s\n", rb_obj_info(obj)); - ret = NULL; - } + else if (RB_OBJ_PROMOTED_RAW(obj)) { + if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [promoted object] %s\n", rb_obj_info(obj)); + ret = NULL; + } #else - else if (RBASIC_CLASS(obj) == 0) { - if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [hidden object] %s\n", rb_obj_info(obj)); - ret = NULL; - } + else if (RBASIC_CLASS(obj) == 0) { + if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [hidden object] %s\n", rb_obj_info(obj)); + ret = NULL; + } #endif - else { - struct transient_alloc_header *header = transient_heap_allocatable_header(theap, size); - if (header) { - void *ptr; + else { + struct transient_alloc_header *header = transient_heap_allocatable_header(theap, size); + if (header) { + void *ptr; - /* header is poisoned to prevent buffer overflow, should - * unpoison first... */ - asan_unpoison_memory_region(header, sizeof *header, true); + /* header is poisoned to prevent buffer overflow, should + * unpoison first... */ + asan_unpoison_memory_region(header, sizeof *header, true); - header->size = size; - header->magic = TRANSIENT_HEAP_ALLOC_MAGIC; - header->next_marked_index = TRANSIENT_HEAP_ALLOC_MARKING_FREE; - header->obj = obj; /* TODO: can we eliminate it? */ + header->size = size; + header->magic = TRANSIENT_HEAP_ALLOC_MAGIC; + header->next_marked_index = TRANSIENT_HEAP_ALLOC_MARKING_FREE; + header->obj = obj; /* TODO: can we eliminate it? */ - /* header is fixed; shall poison again */ - asan_poison_memory_region(header, sizeof *header); - ptr = header + 1; + /* header is fixed; shall poison again */ + asan_poison_memory_region(header, sizeof *header); + ptr = header + 1; - theap->total_objects++; /* statistics */ + theap->total_objects++; /* statistics */ #if TRANSIENT_HEAP_DEBUG_DONT_PROMOTE - if (RB_OBJ_PROMOTED_RAW(obj)) { - transient_heap_promote_add(theap, obj); - } + if (RB_OBJ_PROMOTED_RAW(obj)) { + transient_heap_promote_add(theap, obj); + } #endif - if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: header:%p ptr:%p size:%d obj:%s\n", (void *)header, ptr, (int)size, rb_obj_info(obj)); + if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: header:%p ptr:%p size:%d obj:%s\n", (void *)header, ptr, (int)size, rb_obj_info(obj)); - RB_DEBUG_COUNTER_INC(theap_alloc); + RB_DEBUG_COUNTER_INC(theap_alloc); - /* ptr is set up; OK to unpoison. */ - asan_unpoison_memory_region(ptr, size - sizeof *header, true); - ret = ptr; - } - else { - if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [no enough space: %ld] %s\n", (long)size, rb_obj_info(obj)); - RB_DEBUG_COUNTER_INC(theap_alloc_fail); - ret = NULL; - } + /* ptr is set up; OK to unpoison. */ + asan_unpoison_memory_region(ptr, size - sizeof *header, true); + ret = ptr; + } + else { + if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [no enough space: %ld] %s\n", (long)size, rb_obj_info(obj)); + RB_DEBUG_COUNTER_INC(theap_alloc_fail); + ret = NULL; } } - RB_VM_LOCK_LEAVE(); return ret; } @@ -775,16 +773,16 @@ transient_heap_update_status(struct transient_heap* theap, enum transient_heap_s static void transient_heap_evacuate(void *dmy) { - RB_VM_LOCK_ENTER(); - rb_vm_barrier(); - { - struct transient_heap* theap = transient_heap_get(); + struct transient_heap* theap = transient_heap_get(); - if (theap->status == transient_heap_marking) { - if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! transient_heap_evacuate: skip while transient_heap_marking\n"); - } - else { - VALUE gc_disabled = rb_gc_disable_no_rest(); + if (theap->total_marked_objects == 0) return; + if (ruby_single_main_ractor == NULL) rb_bug("not single ractor mode"); + if (theap->status == transient_heap_marking) { + if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! transient_heap_evacuate: skip while transient_heap_marking\n"); + } + else { + VALUE gc_disabled = rb_gc_disable_no_rest(); + { struct transient_heap_block* block; RUBY_DEBUG_LOG("start gc_disabled:%d", RTEST(gc_disabled)); @@ -825,12 +823,16 @@ transient_heap_evacuate(void *dmy) transient_heap_verify(theap); transient_heap_update_status(theap, transient_heap_none); - - if (gc_disabled != Qtrue) rb_gc_enable(); - RUBY_DEBUG_LOG("finish", 0); } + if (gc_disabled != Qtrue) rb_gc_enable(); + RUBY_DEBUG_LOG("finish", 0); } - RB_VM_LOCK_LEAVE(); +} + +void +rb_transient_heap_evacuate(void) +{ + transient_heap_evacuate(NULL); } static void @@ -964,9 +966,9 @@ rb_transient_heap_finish_marking(void) struct transient_heap* theap = transient_heap_get(); - if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! rb_transient_heap_finish_marking objects:%d, marked:%d\n", - theap->total_objects, - theap->total_marked_objects); + RUBY_DEBUG_LOG("objects:%d, marked:%d", + theap->total_objects, + theap->total_marked_objects); if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap); TH_ASSERT(theap->total_objects >= theap->total_marked_objects); |