Skip to content

Commit

Permalink
prefer class_serial over m_tbl
Browse files Browse the repository at this point in the history
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
  • Loading branch information
shyouhei committed Nov 27, 2019
1 parent 177bc65 commit 6f27fa4
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 6 deletions.
8 changes: 4 additions & 4 deletions gc.c
Expand Up @@ -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));
}
Expand Down Expand Up @@ -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;
Expand Down
26 changes: 24 additions & 2 deletions internal.h
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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
Expand Down

0 comments on commit 6f27fa4

Please sign in to comment.