Slide 1

Slide 1 text

© 2024 Wantedly, Inc. object_id Rubyの Aug. 28 2024 - Masaki Hara @ Gotanda.rb #60

Slide 2

Slide 2 text

© 2024 Wantedly, Inc. Rubyの object_id

Slide 3

Slide 3 text

© 2024 Wantedly, Inc. Quiz 1 p 1.object_id == 1.object_id p "foo".object_id == "foo".object_id p [].object_id == [].object_id

Slide 4

Slide 4 text

© 2024 Wantedly, Inc. Quiz 1 p 1.object_id == 1.object_id # => true p "foo".object_id == "foo".object_id # => frozen_string_literal に依存 p [].object_id == [].object_id # => false とは断言できない

Slide 5

Slide 5 text

© 2024 Wantedly, Inc. object_id ● オブジェクトの同一性をあらわす整数 ○ Kernel#object_id または BasicObject#__id__ ● #equal? と同等 ○ a.equal?(b) ⇔ a.__id__ == b.__id__

Slide 6

Slide 6 text

© 2024 Wantedly, Inc. object_idの永続性 ● object_id は現存する他のオブジェクトとは重複しない ● 過去に存在したオブジェクトとは重複しうる ○ ……ということになっているが、実は現行の CRuby実装では重複しない (後述)

Slide 7

Slide 7 text

© 2024 Wantedly, Inc. object_idの永続性 RubyVM::InstructionSequence.compile( "[].object_id == [].object_id" ).to_a[13]

Slide 8

Slide 8 text

© 2024 Wantedly, Inc. object_idの永続性 [1, :RUBY_EVENT_LINE, [:newarray, 0], [:opt_send_without_block, {:mid=>:object_id, :flag=>16, :orig_argc=>0}], [:newarray, 0], [:opt_send_without_block, {:mid=>:object_id, :flag=>16, :orig_argc=>0}], [:opt_eq, {:mid=>:==, :flag=>16, :orig_argc=>1}], [:leave]]

Slide 9

Slide 9 text

© 2024 Wantedly, Inc. object_idの永続性 [1, :RUBY_EVENT_LINE, [:newarray, 0], [:opt_send_without_block, {:mid=>:object_id, :flag=>16, :orig_argc=>0}], [:newarray, 0], [:opt_send_without_block, {:mid=>:object_id, :flag=>16, :orig_argc=>0}], [:opt_eq, {:mid=>:==, :flag=>16, :orig_argc=>1}], [:leave]] stack = [] stack = [[]] stack = [oid1] stack = [oid1, []] stack = [oid1, oid2] stack = [false]

Slide 10

Slide 10 text

© 2024 Wantedly, Inc. CRuby の object_id

Slide 11

Slide 11 text

© 2024 Wantedly, Inc. Quiz 2 p false.object_id p 100.object_id p 10000000000.object_id ※CRubyの場合

Slide 12

Slide 12 text

© 2024 Wantedly, Inc. Quiz 2 p false.object_id # => 0 p 100.object_id # => 201 p 10000000000.object_id # => 32bit環境と64bit環境で異なる ※CRubyの場合

Slide 13

Slide 13 text

© 2024 Wantedly, Inc. 特別な値 ● false, true, nil, および小さい整数値は特別なobject_id値 をもつ (即値) ○ 短い整数値はFixnumとも呼ばれる ● 小さい整数値の上限は32bit環境と64bit環境で異なる ○ 32bitなら −230 ≤ n < 230, 64bitなら −262 ≤ n < 262

Slide 14

Slide 14 text

© 2024 Wantedly, Inc. Quiz 3 p [].object_id - [].object_id ※CRubyの一般的な結果

Slide 15

Slide 15 text

© 2024 Wantedly, Inc. Quiz 3 p [].object_id - [].object_id # => -8 (Ruby >= 3.4.0) # => -20 (Ruby >= 2.7.0) # => 20 (Ruby < 2.7.0) # ※GCの挙動に依存、64bit環境の例 ※CRubyの一般的な結果

Slide 16

Slide 16 text

© 2024 Wantedly, Inc. 人工的なオブジェクトID ● Ruby 2.7より前: オブジェクトID = アドレス÷2 ○ GCの挙動に依存するが、降順に割り当てられるため正の値が出ることが多い ○ 20 は64bit環境における sizeof(RVALUE) / 2 ● Ruby 2.7以降: オブジェクトID = カウンタの値 ○ コンパクションが実装されたため、アドレスが安定的に使えない ○ かわりにカウンタの値を払い出して使っている ○ sizeof(RVALUE) の倍数になるよう工夫されている (3.3以前はその半分) ○ そのため、object_id を呼んだ順に依存して安定的に 8ずつ増える (3.3以前は20ずつ)

Slide 17

Slide 17 text

© 2024 Wantedly, Inc. Quiz 4 p :foo.object_id p "bar".to_sym.object_id ※CRubyの一般的な結果

Slide 18

Slide 18 text

© 2024 Wantedly, Inc. Quiz 4 p :foo.object_id # => 12280076 (一例) p "bar".to_sym.object_id # => 8 (一例) ※CRubyの一般的な結果

Slide 19

Slide 19 text

© 2024 Wantedly, Inc. シンボルGC ● 静的シンボル: GCされない。IDは 256n + 12 ○ :foo など静的な構文によって生成されるとこの形になる ○ Ruby 3.3 以前は別仕様 ● 動的シンボル: GCされる。IDは 40n ○ 一般のオブジェクトと同じ扱い ○ 40 は 64bit環境における sizeof(RVALUE) ○ String#to_sym など動的な処理で生成されるとこの形になる ○ すでに静的シンボルが生成されていればそちらが使われる (逆も然り)

Slide 20

Slide 20 text

© 2024 Wantedly, Inc. ID ● ID: Symbolの内部表現 ○ rb_sym2id, rb_id2sym ○ sym.object_id / 256 (Ruby 3.4〜, 静的シンボルの場合) ○ sym.object_id / 20 (Ruby 〜3.3) ● VALUE表現ともobject_idとも異なる

Slide 21

Slide 21 text

© 2024 Wantedly, Inc. ID IDのフラグ 形式 ID (動的) ID (静的) 例 ローカル 16n + 0 16n + 1 :foo インスタンス 16n + 2 16n + 3 :@foo – 16n + 4 16n + 5 – グローバル 16n + 6 16n + 7 :$foo 形式 ID (動的) ID (静的) 例 セッター 16n + 8 16n + 9 :foo= 定数 16n + 10 16n + 11 :Foo クラス変数 16n + 12 16n + 13 :@@foo その他 16n + 14 16n + 15 :")(" ※演算子類は上の形式によらず、 ASCII符号値または128〜150の値が割り当てられる

Slide 22

Slide 22 text

© 2024 Wantedly, Inc. Quiz 5 p 0.0.object_id p (-0.0).object_id ※CRubyの場合

Slide 23

Slide 23 text

© 2024 Wantedly, Inc. Quiz 5 p 0.0.object_id # => -9223372036854775806 p (-0.0).object_id # => 8 (一例) ※CRubyの場合

Slide 24

Slide 24 text

© 2024 Wantedly, Inc. Flonum ● Ruby 2.0以降では、64bit環境でFlonumが有効 ● Flonum: 特定範囲の浮動小数点数を即値で表現 ○ 10-77 〜 1077 に限定すれば62bitで済む ○ 使う機会の多い +0 は例外的に追加の即値として表現

Slide 25

Slide 25 text

© 2024 Wantedly, Inc. Flonum 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 オブジェクト 1…010 0…010 オブジェクト 1…110 0…110 オブジェクト +0 1.73 × 10-77 2.32 × 1077 +∞, NaN -0 -1.73 × 10-77 -2.32 × 1077 -∞, NaN 0

Slide 26

Slide 26 text

© 2024 Wantedly, Inc. 64bit (Ruby 3.4-nightly-20240718) *1 *10 Fixnum (63bit) VALUE = 2n + 1 object_id = 2n + 1 Flonum (62bit) VALUE = 4n + 2 object_id = 4n + 2 *100 *000 Static Symbol 4 20 nil true 36 undef General Object 0 false

Slide 27

Slide 27 text

© 2024 Wantedly, Inc. 64bit (Ruby 3.4-nightly-20240718) *1 *10 Fixnum (63bit) VALUE = 2n + 1 object_id = 2n + 1 Flonum (62bit) VALUE = 4n + 2 object_id = 4n + 2 *100 *000 Static Symbol 4 20 nil true 36 undef General Object 0 false VALUE = 256n + 12 object_id = 256n + 12 (nは奇数) VALUE = 8n object_id = 8k

Slide 28

Slide 28 text

© 2024 Wantedly, Inc. 32bit (Ruby 3.4-nightly-20240718) *1 *10 Fixnum (31bit) VALUE = 2n + 1 object_id = 2n + 1 2 6 nil true 10 undef General Object 0 false *00 Static Symbol VALUE = 4n object_id = 4k VALUE = 256n + 14 object_id = 256n + 14 (nは奇数)

Slide 29

Slide 29 text

© 2024 Wantedly, Inc. まとめ ● #object_id は内部表現 (VALUE) をそのまま返しているわ けではない ● とはいえ、Ruby 3.4では即値はそのまま返される ● 小さいInteger, 妥当な範囲のFloat, 静的なSymbolは即値 で表現される ● Ruby 2.7以降ではobject_idは再利用されない

Slide 30

Slide 30 text

© 2024 Wantedly, Inc. おまけ: JRuby の object_id

Slide 31

Slide 31 text

© 2024 Wantedly, Inc. JRuby JRubyにおける VALUE ● Ruby ObjectをJavaのObjectとして表現 ○ Rubyの整数なども内部的にはJavaのObjectになる ● JRubyからはJavaのObject IDは見えない ○ System.identityHashCode がそれに近いが、32bitしかないので厳密な一意性は望 めない ● したがって、VALUE相当の表現はないと言える

Slide 32

Slide 32 text

© 2024 Wantedly, Inc. JRuby JRubyにおける object_id (v9.4.8.0 時点) ● 即値の処理は64bit環境のRuby 3.1.0を再現 ○ Ruby 3.2での変更にはまだ追従していない ● ObjectとSymbolにはカウンタを4倍した値を使用 ○ Symbol専用の即値形式はなく、単なる interned Objectとして扱われる 関連するソース: ● RubyKernel.object_id ● IRubyObject.id ○ RubyBasicObject.id, RubyBasicObject.getObjectId ○ RubyBoolean.id ○ RubyFixnum.id ○ RubyFloat.id ○ RubyNil.id

Slide 33

Slide 33 text

© 2024 Wantedly, Inc. おまけ: mruby の object_id

Slide 34

Slide 34 text

© 2024 Wantedly, Inc. mruby ● mrubyは多様な環境で動くことを想定しているため、各環境 に適した動作ができるようになっている ○ ポインタサイズ、整数サイズ ○ boxing mode (後述) ○ Floatの有無 ● 環境によっては整数のビット数不足により object_id のユ ニーク性を担保できない ○ 整数のビット数が十分な場合でも、 object_idのユニーク性については現時点であまり 考慮されていない

Slide 35

Slide 35 text

© 2024 Wantedly, Inc. boxing mode mrubyは3つのうちのいずれかのモードで動作する: ● Unboxed (No Boxing) ○ 2ワード利用するシンプルな表現 ● Word Boxing ○ CRubyと似たアプローチ ● NaN Boxing ○ JavaScript処理系でよく使われるアプローチ rake MRUBY_CONFIG=build_config/boxing.rb でビルドしてテストできる

Slide 36

Slide 36 text

© 2024 Wantedly, Inc. Unboxed ● UnboxedのVALUE表現 ○ 型タグ + 整数 または ○ 型タグ + ポインタ ○ nilはfalseと同じ型タグを持ち、整数部分で区別 ● Unboxedのobject_id (3.3.0時点) ○ 型タグと値(整数またはポインタ)のXOR ○ 容易にコンフリクトする (たとえば nil.object_id == 2.object_id)

Slide 37

Slide 37 text

© 2024 Wantedly, Inc. Word Boxing ● Word BoxingのVALUE表現 (3.3.0時点) ○ nil = 0, false = 4, true = 12, undef = 20 (nilが0になる点が特徴的!) ○ Fixnum = 2n + 1 ○ Float = 4n + 2 (Floatの切り捨て許可の場合) ■ CRubyのFlonumとは異なる表現である点に注意 ○ Symbol = 4n + 2 (Floatの切り捨て禁止の場合), 232n + 28 (64bitの場合), 32n + 28 (32bitの場合) ○ その他 = struct RBasic* のポインタ値

Slide 38

Slide 38 text

© 2024 Wantedly, Inc. Word Boxing ● Word Boxingのobject_id (3.3.0時点) ○ 原則としてVALUEをそのまま返す ○ 整数サイズに収まるBignumは、その整数値を返す ■ たとえば ポインタサイズ = 整数サイズ = 64 のとき、 262 はFixnumには入らないが、64bit符 号つき整数では表現できる。 結果として、 ((1 << 62) + 1).object_id == (1 << 61).object_id となってしまう ○ Floatは、ビット表現のハッシュ値を計算して返す。ただし、 -0.0 はあらかじめ 0.0 に正 規化する。

Slide 39

Slide 39 text

© 2024 Wantedly, Inc. NaN Boxing ● NaN BoxingのVALUE表現 (3.3.0時点) ○ Floatは必ず64bitで、ビット表現に 0x8004000000000000 を足して保管する ■ 言い換えると、ビット表現から 0x7ffc000000000000 を引く。この値は正規 NaNのビット表現 よりちょっと大きい ○ ただしNaNは正規化する ■ ここでの正規NaNとは、符号が正で仮数部の最上位ビットが 1、残りが0のもの、つまり 0x7ff8000000000000 とする (正式ではないがよく使われる正規化形式 ) ○ Float以外のデータは約53bitある非正規NaNの空間に押しこめる ■ 負数と仮数部空間下半分は使わないので、 51bit分から正規NaNを除いて48bit空間7本分を 確保できる

Slide 40

Slide 40 text

© 2024 Wantedly, Inc. NaN Boxing ● NaN BoxingのVALUE表現 (3.3.0時点) ○ Fixnumは -231 〜 231 - 1 の範囲で固定、空間1を利用 ○ Symbolとfalse, true, undef は空間6を利用 ○ Objectとnilは空間4を利用 ■ Floatのシフト値 0x8004000000000000 は、空間4がちょうど0になるように選ばれている ■ よく知られている64bitアーキテクチャでは (ユーザーランドの)ポインタサイズが48bitに抑えら れているので、これで問題なく表現できる ○ 生ポインタのVALUE表現 (cptr) が欲しいときは空間7を利用

Slide 41

Slide 41 text

© 2024 Wantedly, Inc. NaN Boxing ● NaN Boxingのobject_id (3.3.0時点) ○ VALUE表現をそのまま返す ○ ただし、整数サイズが32bitの場合は上位32bitと下位32bitのXORに圧縮する (当然、 重複は発生する)

Slide 42

Slide 42 text

© 2024 Wantedly, Inc. おまけ: CRuby の object_id の歴史

Slide 43

Slide 43 text

© 2024 Wantedly, Inc. Ruby 0.49 Ruby 0.49 ● 現存する最古のバージョン ● true/falseは無い (1/nilで代用) ● Symbolも無い (String, Integerで代用) ○ IDはあった ● Kernel#id はあった ○ 現在の #object_id に相当 ○ n|1 を返す処理のため、重複が発生しうる

Slide 44

Slide 44 text

© 2024 Wantedly, Inc. Ruby 0.49 ● VALUE object_id nil 0 0 Fixnum 2n + 1 n Object 4n 2n ※ alignof(RBasic) = 4

Slide 45

Slide 45 text

© 2024 Wantedly, Inc. Ruby 0.49 ● 形式 ID 例 演算子 < LAST_ID :+ ローカル 8n + 0 :foo インスタンス 8n + 2 :@foo グローバル 8n + 3 :$foo セッター 8n + 4 :foo= 定数 8n + 6 :%foo Ruby 0.66で :Foo に変更

Slide 46

Slide 46 text

© 2024 Wantedly, Inc. Ruby 0.69 Ruby 0.69 ● $1, $2, … が登場 ○ これにあわせて、IDのフラグ割り当てが変更

Slide 47

Slide 47 text

© 2024 Wantedly, Inc. Ruby 0.69 ● 形式 ID 例 演算子 < LAST_ID :+ ローカル 8n + 0 :foo インスタンス 8n + 1 :@foo 形式 ID 例 グローバル 8n + 2 :$foo セッター 8n + 3 :foo= 定数 8n + 4 :Foo グループ参照 8n + 5 :$1

Slide 48

Slide 48 text

© 2024 Wantedly, Inc. Ruby 0.77 〜 0.95 Ruby 0.77 〜 0.95 のどこか ● $1, $2, … のID は $foo と区別されなくなった ○ 具体的なバージョンは不明

Slide 49

Slide 49 text

© 2024 Wantedly, Inc. Ruby 0.77 〜 0.95 ● 形式 ID 例 演算子 < LAST_ID :+ ローカル 8n + 0 :foo インスタンス 8n + 1 :@foo 形式 ID 例 グローバル 8n + 2 :$foo セッター 8n + 3 :foo= 定数 8n + 4 :Foo グループ参照 8n + 5 :$1

Slide 50

Slide 50 text

© 2024 Wantedly, Inc. Ruby 0.96 Ruby 0.96 ● true/falseが追加

Slide 51

Slide 51 text

© 2024 Wantedly, Inc. Ruby 0.96 ● VALUE object_id nil 4 2 false 0 0 true 2 1 Fixnum 2n + 1 n Object 4n 2n

Slide 52

Slide 52 text

© 2024 Wantedly, Inc. Ruby 0.96 〜 0.99 Ruby 0.96 〜 0.99 のどこか ● IDの割り当て変更 ○ 具体的なバージョンは不明

Slide 53

Slide 53 text

© 2024 Wantedly, Inc. Ruby 0.96 〜 0.99 ● 形式 ID 例 演算子 < LAST_ID :+ ローカル 8n + 1 :foo インスタンス 8n + 2 :@foo 形式 ID 例 グローバル 8n + 3 :$foo セッター 8n + 4 :foo= 定数 8n + 5 :Foo

Slide 54

Slide 54 text

© 2024 Wantedly, Inc. Ruby 1.1 Ruby 1.1 ● Kernel#id が INT2NUM を使うようになった ○ 1/2ではなく、そのままの値が見えるようになる

Slide 55

Slide 55 text

© 2024 Wantedly, Inc. Ruby 1.1 ● VALUE object_id nil 4 4 false 0 0 true 2 2 Fixnum 2n + 1 2n + 1 Object 4n 4n

Slide 56

Slide 56 text

© 2024 Wantedly, Inc. Ruby 1.1b9-07 Ruby 1.1b9-07 ● Kernel#__id__ が新設 7253910 ○ Kernel#id と同じ

Slide 57

Slide 57 text

© 2024 Wantedly, Inc. Ruby 1.2 Ruby 1.2 ● 64bitアーキテクチャへの対応開始 ○ 64bitアーキテクチャではVALUEが64bitになり、sizeof(RVALUE), alignof(RVALUE) が大きくなる

Slide 58

Slide 58 text

© 2024 Wantedly, Inc. Ruby 1.3 Ruby 1.3 ● オブジェクトのIDはアドレスの1/2

Slide 59

Slide 59 text

© 2024 Wantedly, Inc. Ruby 1.3 ● VALUE object_id nil 4 4 false 0 0 true 2 2 Fixnum 2n + 1 2n + 1 Object 4n 2n

Slide 60

Slide 60 text

© 2024 Wantedly, Inc. Ruby 1.6 Ruby 1.6 ● undef (Qundef) 導入 de71615 ○ Cコード用であり、Rubyの世界に出現することはない ● クラス変数が登場 3d6fde3 ○ 旧名: 共有変数。 Ruby 1.5で導入しようとしたものの再挑戦。 ● Symbolが登場 4d215cd ○ Internされた状態の文字列をRuby側から保持できるようになった。

Slide 61

Slide 61 text

© 2024 Wantedly, Inc. Ruby 1.6 ● VALUE object_id nil 4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Symbol 256 × ID + 14 256 × ID + 14 Object 8n 4n Object 4n 2n 32bitの場合

Slide 62

Slide 62 text

© 2024 Wantedly, Inc. Ruby 1.6 ● 形式 ID 例 演算子 < LAST_ID :+ ローカル 8n + 1 :foo インスタンス 8n + 2 :@foo グローバル 8n + 3 :$foo 形式 ID 例 セッター 8n + 4 :foo= 定数 8n + 5 :Foo クラス変数 8n + 6 :@@foo

Slide 63

Slide 63 text

© 2024 Wantedly, Inc. Ruby 1.8.0 Ruby 1.8.0 ● IDの拡張 b12904e ○ 任意の文字列をinternできるように、未分類のIDを表すフラグが追加 ● Kernel#object_id aae3675 ○ Kernel#id を置き換える。 ○ Kernel#id はこの時点では非推奨化されただけで、まだ使える

Slide 64

Slide 64 text

© 2024 Wantedly, Inc. Ruby 1.8.0 ● 形式 ID 例 演算子 < LAST_ID :+ ローカル 8n + 1 :foo インスタンス 8n + 2 :@foo グローバル 8n + 3 :$foo 形式 ID 例 セッター 8n + 4 :foo= 定数 8n + 5 :Foo クラス変数 8n + 6 :@@foo その他 8n + 7 :")("

Slide 65

Slide 65 text

© 2024 Wantedly, Inc. Ruby 1.8.5 Ruby 1.8.5 ● SymbolとObjectの衝突回避 6828bbe ○ ObjectのC表現は4の倍数だが、object_idは2で割っているので2の倍数しか保証さ れず、そのままではSymbolと衝突する ● Objectのアラインメント保証 (同上) ○ 通常、ポインタのアラインメントは alignof(T) の範囲内でしか保証されない ○ CRuby側で開始位置を調整することで、 sizeof(RVALUE) の倍数であることを保証す るようにした

Slide 66

Slide 66 text

© 2024 Wantedly, Inc. Ruby 1.8.5 ● VALUE object_id nil 4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Symbol 256 × ID + 14 20 × ID + 8 Object 40n 20n Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10n 32bitの場合 (alignof(double) == 4 の場合)

Slide 67

Slide 67 text

© 2024 Wantedly, Inc. Ruby 1.9.0 Ruby 1.9.0 ● Kernel#id 削除 ○ Kernel#object_id への移行のため ● ID割り当て変更 72f2d2a b83ed6d ○ @_foo のような変数を「プライベートインスタンス変数」として特別扱いしようとしたが、 revertされた。この影響でIDのフラグ割り当てが変更に。

Slide 68

Slide 68 text

© 2024 Wantedly, Inc. Ruby 1.9.0 ● 形式 ID 例 演算子 < LAST_ID :+ ローカル 8n + 0 :foo インスタンス 8n + 1 :@foo グローバル 8n + 3 :$foo 形式 ID 例 セッター 8n + 4 :foo= 定数 8n + 5 :Foo クラス変数 8n + 6 :@@foo その他 8n + 7 :")("

Slide 69

Slide 69 text

© 2024 Wantedly, Inc. Ruby 1.9.3 Ruby 1.9.3 ● Kernel#__id__ 移動 591ae37 049cdff ○ BasicObjectに移動され、Proxy Objectからでも使えるようになった

Slide 70

Slide 70 text

© 2024 Wantedly, Inc. Ruby 2.0.0 Ruby 2.0.0 ● Flonum導入 b3b5e62 ○ 64bit環境で、範囲内のFloatが即値で表現されるようになった ○ これらとの衝突を避けるため、定数やシンボルが移動し、 8n+4型の値を利用するように ● 演算子IDの安定化 470c941 ○ Yacc/BisonのLAST_TOKEN値に依存していた処理を書き直して、演算子に付与され るIDを安定化

Slide 71

Slide 71 text

© 2024 Wantedly, Inc. Ruby 2.0.0 ● 64bit VALUE object_id nil 8 8 false 0 0 true 20 20 undef 52 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 Symbol 256 × ID + 12 20 × ID + 8 Object 40n 20n

Slide 72

Slide 72 text

© 2024 Wantedly, Inc. Ruby 2.0.0 ● 32bit VALUE object_id nil 4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10n (alignof(double) == 4 の場合)

Slide 73

Slide 73 text

© 2024 Wantedly, Inc. Ruby 2.2.0 Ruby 2.2.0 ● シンボルGC 90b7073 ○ String#to_sym などで動的に作成されたSymbolはGCの対象になる ○ 内部的には、普通の RVALUE* オブジェクトとして確保されることになる ○ これに合わせて、IDにフラグビットが追加 ● セッターID紐付けの廃止 3e69b07 ○ :foo と :foo= のように対応するSymbolに、同じカウンタに由来するIDを付与する機能 があったが、これが廃止された。

Slide 74

Slide 74 text

© 2024 Wantedly, Inc. Ruby 2.2.0 ● 64bit VALUE object_id nil 8 8 false 0 0 true 20 20 undef 52 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 静的Symbol 256 × ID + 12 20 × ID + 8 Object 40n 20n

Slide 75

Slide 75 text

© 2024 Wantedly, Inc. Ruby 2.2.0 ● 32bit VALUE object_id nil 4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – 静的Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10n (alignof(double) == 4 の場合)

Slide 76

Slide 76 text

© 2024 Wantedly, Inc. Ruby 2.2.0 ● 形式 ID (動的) ID (静的) 例 演算子 < LAST_ID :+ ローカル 16n + 0 16n + 1 :foo インスタンス 16n + 2 16n + 3 :@foo グローバル 16n + 6 16n + 7 :$foo 形式 ID (動的) ID (静的) 例 セッター 16n + 8 16n + 9 :foo= 定数 16n + 10 16n + 11 :Foo クラス変数 16n + 12 16n + 13 :@@foo その他 16n + 14 16n + 15 :")("

Slide 77

Slide 77 text

© 2024 Wantedly, Inc. Ruby 2.7.0 Ruby 2.7.0 ● コンパクションGC 91793b8 b99833b ○ コンパクションが起こると、オブジェクトのアドレスが変化するため、アドレスを object_id として使うことができない。 ○ かわりに、object_idが必要になったタイミングでカウンタからユニークな値を生成し、そ れを使うようになった ○ 既存のobject_idの計算に合わせるため、カウンタの値を sizeof(RVALUE)/2 倍して 使用

Slide 78

Slide 78 text

© 2024 Wantedly, Inc. Ruby 2.7.0 ● 64bit VALUE object_id nil 8 8 false 0 0 true 20 20 undef 52 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 静的Symbol 256 × ID + 12 20 × ID + 8 Object 40n 20k

Slide 79

Slide 79 text

© 2024 Wantedly, Inc. Ruby 2.7.0 ● 32bit VALUE object_id nil 4 4 false 0 0 true 2 2 undef 6 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – 静的Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10k (alignof(double) == 4 の場合)

Slide 80

Slide 80 text

© 2024 Wantedly, Inc. Ruby 3.2.0 Ruby 3.2.0 ● 定数値の変更 f55212b ○ 計算しやすいようにnil, true, undefの定数値を変更

Slide 81

Slide 81 text

© 2024 Wantedly, Inc. Ruby 3.2.0 ● 64bit VALUE object_id nil 4 4 false 0 0 true 20 20 undef 36 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 静的Symbol 256 × ID + 12 20 × ID + 8 Object 40n 20k

Slide 82

Slide 82 text

© 2024 Wantedly, Inc. Ruby 3.2.0 ● 32bit VALUE object_id nil 2 2 false 0 0 true 6 6 undef 10 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – 静的Symbol 256 × ID + 14 10 × ID + 8 Object 20n 10k (alignof(double) == 4 の場合)

Slide 83

Slide 83 text

© 2024 Wantedly, Inc. Ruby 3.4.0 Ruby 3.4.0 (未リリース) ● SymbolとObjectの整理 edec690 403f44e ○ Symbolのobject_idが複雑な変換を経ていたのをやめて、 VALUE値をそのまま返す ように変更 ○ Objectは下位ビットが衝突しなければいいので、単に 4または8の倍数としてカウントす るように変更 (sizeof(RVALUE) が無関係に) ● object_idカウンタの拡張 ee6e591 ○ 32bit環境でも64bitカウンタを利用することで枯渇に対応

Slide 84

Slide 84 text

© 2024 Wantedly, Inc. Ruby 3.4.0 ● 64bit VALUE object_id nil 4 4 false 0 0 true 20 20 undef 36 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum 4F(x) + 2 4F(x) + 2 静的Symbol 256 × ID + 12 256 × ID + 12 Object 8n 8k

Slide 85

Slide 85 text

© 2024 Wantedly, Inc. Ruby 3.4.0 ● 32bit VALUE object_id nil 2 2 false 0 0 true 6 6 undef 10 – VALUE object_id Fixnum 2n + 1 2n + 1 Flonum – – 静的Symbol 256 × ID + 14 256 × ID + 14 Object 4n 4k

Slide 86

Slide 86 text

© 2024 Wantedly, Inc. 以上