[前][次][番号順一覧][スレッド一覧]

ruby-changes:63978

From: Koichi <ko1@a...>
Date: Mon, 7 Dec 2020 08:28:59 +0900 (JST)
Subject: [ruby-changes:63978] 307732ccee (master): cancel theap on multi-ractors

https://git.ruby-lang.org/ruby.git/commit/?id=307732ccee

From 307732ccee7f9f28f8422bab2f839da021d8cdec Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Sat, 5 Dec 2020 06:15:17 +0900
Subject: 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.

diff --git a/common.mk b/common.mk
index b334056..158828a 100644
--- a/common.mk
+++ b/common.mk
@@ -10384,6 +10384,7 @@ ractor.$(OBJEXT): {$(VPATH)}subst.h https://github.com/ruby/ruby/blob/trunk/common.mk#L10384
 ractor.$(OBJEXT): {$(VPATH)}thread.h
 ractor.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
 ractor.$(OBJEXT): {$(VPATH)}thread_native.h
+ractor.$(OBJEXT): {$(VPATH)}transient_heap.h
 ractor.$(OBJEXT): {$(VPATH)}variable.h
 ractor.$(OBJEXT): {$(VPATH)}vm_core.h
 ractor.$(OBJEXT): {$(VPATH)}vm_debug.h
diff --git a/ractor.c b/ractor.c
index 1ed0272..49a92a2 100644
--- a/ractor.c
+++ b/ractor.c
@@ -14,6 +14,7 @@ https://github.com/ruby/ruby/blob/trunk/ractor.c#L14
 #include "internal/struct.h"
 #include "variable.h"
 #include "gc.h"
+#include "transient_heap.h"
 
 VALUE rb_cRactor;
 static VALUE rb_eRactorError;
@@ -1127,16 +1128,33 @@ ractor_next_id(void) https://github.com/ruby/ruby/blob/trunk/ractor.c#L1128
 }
 
 static void
-vm_insert_ractor0(rb_vm_t *vm, rb_ractor_t *r)
+vm_insert_ractor0(rb_vm_t *vm, rb_ractor_t *r, bool single_ractor_mode)
 {
     RUBY_DEBUG_LOG("r:%u ractor.cnt:%u++", r->id, vm->ractor.cnt);
-    VM_ASSERT(!rb_multi_ractor_p() || RB_VM_LOCKED_P());
+    VM_ASSERT(single_ractor_mode || RB_VM_LOCKED_P());
 
     list_add_tail(&vm->ractor.set, &r->vmlr_node);
     vm->ractor.cnt++;
 }
 
 static void
+cancel_single_ractor_mode(void)
+{
+    // enable multi-ractor mode
+    RUBY_DEBUG_LOG("enable multi-ractor mode", 0);
+
+    rb_gc_start();
+    rb_transient_heap_evacuate();
+
+    if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
+        rb_warn("Ractor is experimental, and the behavior may change in future versions of Ruby! "
+                "Also there are many implementation issues.");
+    }
+
+    ruby_single_main_ractor = NULL;
+}
+
+static void
 vm_insert_ractor(rb_vm_t *vm, rb_ractor_t *r)
 {
     VM_ASSERT(ractor_status_p(r, ractor_created));
@@ -1144,29 +1162,22 @@ vm_insert_ractor(rb_vm_t *vm, rb_ractor_t *r) https://github.com/ruby/ruby/blob/trunk/ractor.c#L1162
     if (rb_multi_ractor_p()) {
         RB_VM_LOCK();
         {
-            vm_insert_ractor0(vm, r);
+            vm_insert_ractor0(vm, r, false);
             vm_ractor_blocking_cnt_inc(vm, r, __FILE__, __LINE__);
         }
         RB_VM_UNLOCK();
     }
     else {
-        vm_insert_ractor0(vm, r);
-
-        if (vm->ractor.cnt == 1) {
+        if (vm->ractor.cnt == 0) {
             // main ractor
+            vm_insert_ractor0(vm, r, true);
             ractor_status_set(r, ractor_blocking);
             ractor_status_set(r, ractor_running);
         }
         else {
+            cancel_single_ractor_mode();
+            vm_insert_ractor0(vm, r, true);
             vm_ractor_blocking_cnt_inc(vm, r, __FILE__, __LINE__);
-
-            // enable multi-ractor mode
-            RUBY_DEBUG_LOG("enable multi-ractor mode", 0);
-            ruby_single_main_ractor = NULL;
-
-            if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
-                rb_warn("Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.");
-            }
         }
     }
 }
diff --git a/transient_heap.c b/transient_heap.c
index 357e4a4..5b6fd89 100644
--- a/transient_heap.c
+++ b/transient_heap.c
@@ -364,74 +364,72 @@ transient_heap_allocatable_header(struct transient_heap* theap, size_t size) https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L364
 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 https://github.com/ruby/ruby/blob/trunk/transient_heap.c#L773
 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 transie (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]