summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2019-11-27 14:42:30 +0900
committer卜部昌平 <shyouhei@ruby-lang.org>2019-11-27 21:38:07 +0900
commit6f27fa4f7d52bfaea4fd1bd7605bda28e302e74c (patch)
treebbe0c2cd3e9eb33bf0c38e6d6d185dc1f916441c
parent177bc652a8110c1350c0e6df8cb17158e44e18dd (diff)
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
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2701
-rw-r--r--gc.c8
-rw-r--r--internal.h26
2 files changed, 28 insertions, 6 deletions
diff --git a/gc.c b/gc.c
index 9cc230bd3d..4d99261e39 100644
--- a/gc.c
+++ b/gc.c
@@ -3794,10 +3794,10 @@ obj_memsize_of(VALUE obj, int use_all_types)
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)
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 1ab70cf8ae..50c129e7cd 100644
--- a/internal.h
+++ b/internal.h
@@ -1004,19 +1004,25 @@ struct rb_subclass_entry {
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 {
* 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 {
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);
#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