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

ruby-changes:58924

From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Wed, 27 Nov 2019 21:38:34 +0900 (JST)
Subject: [ruby-changes:58924] 6f27fa4f7d (master): prefer class_serial over m_tbl

https://git.ruby-lang.org/ruby.git/commit/?id=6f27fa4f7d

From 6f27fa4f7d52bfaea4fd1bd7605bda28e302e74c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?=
 <shyouhei@r...>
Date: Wed, 27 Nov 2019 14:42:30 +0900
Subject: prefer class_serial over m_tbl

Decades ago, among all the data that a class has, its method
table was no doubt the most frequently accessed data.  Previous
data structures were based on that assumption.

Today that is no longer true.  The most frequently accessed field
moved to class_serial.  That field is not always as wide as VALUE
but if it is, let us swap m_tbl and class_serial.

Calculating -------------------------------------
                               ours       trunk
Optcarrot Lan_Master.nes     47.363      46.630 fps

Comparison:
             Optcarrot Lan_Master.nes
                    ours:        47.4 fps
                   trunk:        46.6 fps - 1.02x  slower

diff --git a/gc.c b/gc.c
index 9cc230b..4d99261 100644
--- a/gc.c
+++ b/gc.c
@@ -3794,10 +3794,10 @@ obj_memsize_of(VALUE obj, int use_all_types) https://github.com/ruby/ruby/blob/trunk/gc.c#L3794
 	break;
       case T_MODULE:
       case T_CLASS:
-	if (RCLASS_M_TBL(obj)) {
-	    size += rb_id_table_memsize(RCLASS_M_TBL(obj));
-	}
 	if (RCLASS_EXT(obj)) {
+            if (RCLASS_M_TBL(obj)) {
+                size += rb_id_table_memsize(RCLASS_M_TBL(obj));
+            }
 	    if (RCLASS_IV_TBL(obj)) {
 		size += st_memsize(RCLASS_IV_TBL(obj));
 	    }
@@ -5306,11 +5306,11 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj) https://github.com/ruby/ruby/blob/trunk/gc.c#L5306
     switch (BUILTIN_TYPE(obj)) {
       case T_CLASS:
       case T_MODULE:
-	mark_m_tbl(objspace, RCLASS_M_TBL(obj));
         if (RCLASS_SUPER(obj)) {
             gc_mark(objspace, RCLASS_SUPER(obj));
         }
 	if (!RCLASS_EXT(obj)) break;
+        mark_m_tbl(objspace, RCLASS_M_TBL(obj));
         mark_tbl_no_pin(objspace, RCLASS_IV_TBL(obj));
 	mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
 	break;
diff --git a/internal.h b/internal.h
index 1ab70cf..50c129e 100644
--- a/internal.h
+++ b/internal.h
@@ -1004,19 +1004,25 @@ struct rb_subclass_entry { https://github.com/ruby/ruby/blob/trunk/internal.h#L1004
 typedef unsigned LONG_LONG rb_serial_t;
 #define SERIALT2NUM ULL2NUM
 #define PRI_SERIALT_PREFIX PRI_LL_PREFIX
+#define SIZEOF_SERIAL_T SIZEOF_LONG_LONG
 #elif defined(HAVE_UINT64_T)
 typedef uint64_t rb_serial_t;
 #define SERIALT2NUM SIZET2NUM
 #define PRI_SERIALT_PREFIX PRI_64_PREFIX
+#define SIZEOF_SERIAL_T SIZEOF_UINT64_T
 #else
 typedef unsigned long rb_serial_t;
 #define SERIALT2NUM ULONG2NUM
 #define PRI_SERIALT_PREFIX PRI_LONG_PREFIX
+#define SIZEOF_SERIAL_T SIZEOF_LONG
 #endif
 
 struct rb_classext_struct {
     struct st_table *iv_index_tbl;
     struct st_table *iv_tbl;
+#if SIZEOF_SERIAL_T == SIZEOF_VALUE /* otherwise m_tbl is in struct RClass */
+    struct rb_id_table *m_tbl;
+#endif
     struct rb_id_table *const_tbl;
     struct rb_id_table *callable_m_tbl;
     rb_subclass_entry_t *subclasses;
@@ -1027,7 +1033,9 @@ struct rb_classext_struct { https://github.com/ruby/ruby/blob/trunk/internal.h#L1033
      * included. Hopefully that makes sense.
      */
     rb_subclass_entry_t **module_subclasses;
+#if SIZEOF_SERIAL_T != SIZEOF_VALUE /* otherwise class_serial is in struct RClass */
     rb_serial_t class_serial;
+#endif
     const VALUE origin_;
     const VALUE refined_class;
     rb_alloc_func_t allocator;
@@ -1040,7 +1048,13 @@ struct RClass { https://github.com/ruby/ruby/blob/trunk/internal.h#L1048
     struct RBasic basic;
     VALUE super;
     rb_classext_t *ptr;
+#if SIZEOF_SERIAL_T == SIZEOF_VALUE
+    /* Class serial is as wide as VALUE.  Place it here. */
+    rb_serial_t class_serial;
+#else
+    /* Class serial does not fit into struct RClass. Place m_tbl instead. */
     struct rb_id_table *m_tbl;
+#endif
 };
 
 void rb_class_subclass_add(VALUE super, VALUE klass);
@@ -1050,12 +1064,20 @@ int rb_singleton_class_internal_p(VALUE sklass); https://github.com/ruby/ruby/blob/trunk/internal.h#L1064
 #define RCLASS_EXT(c) (RCLASS(c)->ptr)
 #define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl)
 #define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl)
-#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
+#if SIZEOF_SERIAL_T == SIZEOF_VALUE
+# define RCLASS_M_TBL(c) (RCLASS_EXT(c)->m_tbl)
+#else
+# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
+#endif
 #define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl)
 #define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl)
 #define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_)
 #define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
-#define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial)
+#if SIZEOF_SERIAL_T == SIZEOF_VALUE
+# define RCLASS_SERIAL(c) (RCLASS(c)->class_serial)
+#else
+# define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial)
+#endif
 
 #define RCLASS_CLONED     FL_USER6
 #define RICLASS_IS_ORIGIN FL_USER5
-- 
cgit v0.10.2


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

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