ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: ko1@atdot.net
To: ruby-core@ruby-lang.org
Subject: [ruby-core:66522] [ruby-trunk - Bug #10232] Trivial change of IMMEDIATE VALUE bits layout
Date: Thu, 27 Nov 2014 11:28:15 +0000	[thread overview]
Message-ID: <redmine.journal-50137.20141127112814.ff7fbf17523ea65d@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-10232.20140912012732@ruby-lang.org

Issue #10232 has been updated by Koichi Sasada.

Target version changed from current: 2.2.0 to next minor

----------------------------------------
Bug #10232: Trivial change of IMMEDIATE VALUE bits layout
https://bugs.ruby-lang.org/issues/10232#change-50137

* Author: Koichi Sasada
* Status: Open
* Priority: Normal
* Assignee: Koichi Sasada
* Category: core
* Target version: next minor
* ruby -v: 2.2
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN
----------------------------------------

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
```

```patch
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.





-- 
https://bugs.ruby-lang.org/

  parent reply	other threads:[~2014-11-27 11:37 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-10232.20140912012732@ruby-lang.org>
2014-09-12  1:27 ` [ruby-core:64979] [ruby-trunk - Bug #10232] [Open] Trivial change of IMMEDIATE VALUE bits layout ko1
2014-09-12  2:59   ` [ruby-core:64985] " Eric Wong
2014-09-12  3:10 ` [ruby-core:64986] [ruby-trunk - Bug #10232] " normalperson
2014-09-12  3:31 ` [ruby-core:64987] " ko1
2014-11-27 11:28 ` ko1 [this message]
2017-02-06  2:55 ` [ruby-core:79444] [Ruby trunk Bug#10232][Rejected] " ko1

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-50137.20141127112814.ff7fbf17523ea65d@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).