Project

General

Profile

Bug #10232

Trivial change of IMMEDIATE VALUE bits layout

Added by ko1 (Koichi Sasada) over 4 years ago. Updated about 2 years ago.

Status:
Rejected
Priority:
Normal
Target version:
ruby -v:
2.2
[ruby-core:64979]

Description

The following patch improves performance a bit.

!USE_FLONUM
-------------------------
...xxxx xxx1 Fixnum
...0000 1110 Symbol
...0000 0000 Qfalse
...0000 0010 Qtrue
...0000 0100 Qnil
...0000 0110 Qundef

USE_FLONUM
-------------------------
...xxxx xxx1 Fixnum
...xxxx xx10 Flonum
...0000 1100 Symbol
...0000 0000 Qfalse  0x00 =  0
...0000 1000 Qnil    0x08 =  8
...0001 0100 Qtrue   0x14 = 20
...0011 0100 Qundef  0x34 = 52

#=>

!USE_FLONUM
-------------------------
xxxx xxxx xxx1 Fixnum  0x01
xxxx 0011 0010 Symbol  0x32 = 50
0000 0000 0000 Qfalse  0x00
0000 0000 0010 Qnil    0x02
0000 0001 0010 Qtrue   0x12 = 18
0000 0010 0010 Qundef  0x22 = 32

USE_FLONUM
-------------------------
xxxx xxxx xxx1 Fixnum  0x01
xxxx xxxx xx10 Flonum  0x02
xxxx 0011 0100 Symbol  0x34 = 52
0000 0000 0000 Qfalse  0x00 =  0
0000 0000 0100 Qnil    0x04 =  4
0000 0001 0100 Qtrue   0x14 = 20
0000 0010 0100 Qundef  0x24 = 36
Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h (revision 47531)
+++ include/ruby/ruby.h (working copy)
@@ -395,6 +395,27 @@ USE_FLONUM
 ...0000 1000 Qnil    0x08 =  8
 ...0001 0100 Qtrue   0x14 = 20
 ...0011 0100 Qundef  0x34 = 52
+
+#=>
+
+!USE_FLONUM
+-------------------------
+xxxx xxxx xxx1 Fixnum  0x01
+xxxx 0011 0010 Symbol  0x32 = 50
+0000 0000 0000 Qfalse  0x00
+0000 0000 0010 Qnil    0x02
+0000 0001 0010 Qtrue   0x12 = 18
+0000 0010 0010 Qundef  0x22 = 32
+
+USE_FLONUM
+-------------------------
+xxxx xxxx xxx1 Fixnum  0x01
+xxxx xxxx xx10 Flonum  0x02
+xxxx 0011 0100 Symbol  0x34 = 52
+0000 0000 0000 Qfalse  0x00 =  0
+0000 0000 0100 Qnil    0x04 =  4
+0000 0001 0100 Qtrue   0x14 = 20
+0000 0010 0100 Qundef  0x24 = 36
  */

 /* special constants - i.e. non-zero and non-fixnum constants */
@@ -402,26 +423,26 @@ enum ruby_special_consts {
 #if USE_FLONUM
     RUBY_Qfalse = 0x00,
     RUBY_Qtrue  = 0x14,
-    RUBY_Qnil   = 0x08,
-    RUBY_Qundef = 0x34,
+    RUBY_Qnil   = 0x04,
+    RUBY_Qundef = 0x24,

     RUBY_IMMEDIATE_MASK = 0x07,
     RUBY_FIXNUM_FLAG    = 0x01,
     RUBY_FLONUM_MASK    = 0x03,
     RUBY_FLONUM_FLAG    = 0x02,
-    RUBY_SYMBOL_FLAG    = 0x0c,
+    RUBY_SYMBOL_FLAG    = 0x34,
     RUBY_SPECIAL_SHIFT  = 8
 #else
-    RUBY_Qfalse = 0,
-    RUBY_Qtrue  = 2,
-    RUBY_Qnil   = 4,
-    RUBY_Qundef = 6,
+    RUBY_Qfalse = 0x00,
+    RUBY_Qtrue  = 0x12,
+    RUBY_Qnil   = 0x02,
+    RUBY_Qundef = 0x22,

     RUBY_IMMEDIATE_MASK = 0x03,
     RUBY_FIXNUM_FLAG    = 0x01,
     RUBY_FLONUM_MASK    = 0x00,    /* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */
     RUBY_FLONUM_FLAG    = 0x02,
-    RUBY_SYMBOL_FLAG    = 0x0e,
+    RUBY_SYMBOL_FLAG    = 0x32,
     RUBY_SPECIAL_SHIFT  = 8
 #endif
 };
@@ -1106,7 +1127,7 @@ struct RStruct {
 #define FL_USER18    (((VALUE)1)<<(FL_USHIFT+18))
 #define FL_USER19    (((VALUE)1)<<(FL_USHIFT+19))

-#define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !RTEST(x))
+#define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !(x))

 #define FL_ABLE(x) (!SPECIAL_CONST_P(x) && BUILTIN_TYPE(x) != T_NODE)
 #define FL_TEST_RAW(x,f) (RBASIC(x)->flags&(f))
@@ -1583,11 +1604,9 @@ rb_class_of(VALUE obj)
    if (FLONUM_P(obj)) return rb_cFloat;
    if (obj == Qtrue)  return rb_cTrueClass;
    if (STATIC_SYM_P(obj)) return rb_cSymbol;
-    }
-    else if (!RTEST(obj)) {
    if (obj == Qnil)   return rb_cNilClass;
-   if (obj == Qfalse) return rb_cFalseClass;
     }
+    else if (obj == Qfalse) return rb_cFalseClass;
     return RBASIC(obj)->klass;
 }

@@ -1600,11 +1619,9 @@ rb_type(VALUE obj)
         if (obj == Qtrue)  return T_TRUE;
    if (STATIC_SYM_P(obj)) return T_SYMBOL;
    if (obj == Qundef) return T_UNDEF;
-    }
-    else if (!RTEST(obj)) {
    if (obj == Qnil)   return T_NIL;
-   if (obj == Qfalse) return T_FALSE;
     }
+    else if (obj == Qfalse) return T_FALSE;
     return BUILTIN_TYPE(obj);
 }

The change is:

(1) IMMEDIATE_P(Qnil) => TRUE
(2) SPECIAL_CONST_P(x) becomes a bit simple -> (IMMEDIATE_P(x) || !(x))

(1) can be incompatibility issue so that I don't propose this fix strongly.
Interpreter core doesn't depends on this spec, but C-exts can be affected.

Benchmark result is: http://www.atdot.net/sp/raw/stirbn (gitruby is modified version)

Strange thing is: vm1_const

vm1_const

Const = 1

i = 0
while i<30_000_000 # while loop 1
  i += 1
  j = Const
  k = Const
end

trunk   1.057002067565918
trunk   1.07387113571167
trunk   1.3638195991516113
trunk   1.076874017715454
trunk   1.0717082023620605
gitruby 0.7370171546936035
gitruby 0.7366814613342285
gitruby 0.7377498149871826
gitruby 0.7381434440612793
gitruby 0.7375714778900146

vm1_const only repeats `getinlinecache' instruction. I'm not sure why it has impact.

Change this program to repeat accessing constant more:

Const = 1

i = 0
while i<30_000_000 # while loop 1
  i += 1
  j = Const
  k = Const
    k = Const
  k = Const
  k = Const
  k = Const
  k = Const
  k = Const
  k = Const
  k = Const
  k = Const
  k = Const
  k = Const

end

trunk   2.2485034465789795
trunk   2.2310359477996826
trunk   2.2247872352600098
trunk   2.2434682846069336
trunk   2.225156307220459
gitruby 2.2048048973083496
gitruby 2.2114696502685547
gitruby 2.2110848426818848
gitruby 2.208353042602539
gitruby 2.2142462730407715

It can be accidentally.

Other variations:

vm1_const

Const = 1

i = 0
while i<30_000_000 # while loop 1
  i += 1
  k = Const
end

trunk   0.6202449798583984
trunk   0.8297767639160156
trunk   0.6203830242156982
trunk   0.6206128597259521
trunk   0.6202561855316162
gitruby 0.6209316253662109
gitruby 0.6197938919067383
gitruby 0.6191442012786865
gitruby 0.6194281578063965
gitruby 0.6211118698120117
vm1_const

Const = 1

i = 0
while i<30_000_000 # while loop 1
  i += 1
  j = Const
  k = Const
  l = Const
end

trunk   1.195659875869751
trunk   1.1864018440246582
trunk   1.1857333183288574
trunk   1.17852783203125
trunk   1.177058458328247
gitruby 1.1888437271118164
gitruby 1.1901893615722656
gitruby 1.1873669624328613
gitruby 1.187666893005371
gitruby 1.182875156402588

It seems that such strange behaviour only on two Const accessing.

History

Updated by normalperson (Eric Wong) over 4 years ago

ko1@atdot.net wrote:

(1) can be incompatibility issue so that I don't propose this fix strongly.
Interpreter core doesn't depends on this spec, but C-exts can be affected.

I think the only thing I've seen C-exts depend on is Qfalse == 0
(which this preserves)

Strange thing is: vm1_const

I suspect this is CPU-specific behaviors. I cannot see the difference
on my AMD FX-8320 (on vm1_const, haven't tested others)

Updated by ko1 (Koichi Sasada) over 4 years ago

Eric Wong wrote:

Strange thing is: vm1_const

I suspect this is CPU-specific behaviors. I cannot see the difference
on my AMD FX-8320 (on vm1_const, haven't tested others)

I agree.

Updated by ko1 (Koichi Sasada) over 4 years ago

  • Target version changed from 2.2.0 to 2.6

Updated by ko1 (Koichi Sasada) about 2 years ago

  • Status changed from Open to Rejected

Reject it and revisit sometime.

Also available in: Atom PDF