【问题标题】:Why does `object_id` of symbols vary between rails console and pry/irb?为什么rails控制台和pry/irb之间符号的“object_id”不同?
【发布时间】:2015-09-02 23:08:55
【问题描述】:

当我在调试BasicObject#method_missing(我有一个No Id Given 错误)时,我得出的结论是rb_method_missing(int argc, const VALUE *argv, VALUE obj) 的第一个参数映射到一个方法名称(在:symbol.object_id 的帮助下)。

我想检查一下,所以我在 rails 控制台(Rails 4.2/Ruby 2.2)中输入了:symbol.object_id

:symbol.object_id
# => 771548

然后我签入了 IRB(Ruby 2.2):

:symbol.object_id
# => 771548

一切看起来都很棒。我在 IRB 试过:

:michał_kulesza.object_id
# => 2531228

然后在 Rails 控制台中:

:michał_kulesza.object_id
# => 7816668

为什么:symbol 在这两种情况下都有相同的object_id:michał_kulesza 却有不同的情况?

【问题讨论】:

    标签: ruby-on-rails ruby irb


    【解决方案1】:

    为什么:symbol 在这两种情况下都有相同的object_id:michał_kulesza 有不同的情况?

    这是因为符号 :symbol 已经生成(通过 gem):

    $ irb
    
    irb(main):001:0> Symbol.all_symbols.grep /sym/
    #=> [:to_sym, :all_symbols, :symlink?, :symlink, :sym, :symbol, :@post_symbeg]
    #                                                      ^^^^^^^
    
    irb(main):002:0> :symbol.object_id
    #=> 771548
    

    如果你在不加载任何 gem 的情况下启动 IRB,你会得到不同的结果:

    $ ruby --disable-gems -S irb
    
    irb(main):001:0> Symbol.all_symbols.grep /sym/
    #=> [:to_sym, :all_symbols, :symlink?, :symlink, :@post_symbeg]
    
    irb(main):002:0> :symbol.object_id
    #=> 833308
    

    :symbol 之前生成另一个符号会产生不同的对象ID:

    $ ruby --disable-gems -S irb
    
    irb(main):001:0> :foo.object_id
    #=> 833308
    
    irb(main):002:0> :symbol.object_id
    #=> 833628
    

    Rails 会生成许多符号,这就是为什么 :michał_kulesza 在 rails 控制台中具有更高的对象 ID。

    【讨论】:

      【解决方案2】:

      为什么不呢? object_ids 只有四个属性:

      • object_idInteger
      • 每个对象都有一个object_id
      • 没有两个对象同时具有相同的object_id(但是请注意,两个不同的对象可能在不同时间具有相同的object_id,即object_ids 可能会重新- 使用)
      • 对象的object_id 在其生命周期内不会改变

      您的观察没有违反这四个属性中的任何一个,因此,它是完全有效的。

      可能正在进行一些优化和/或缓存,因此某些Symbols 始终具有相同的object_id。无论如何,这纯粹是 YARV 的内部实现细节,不是 Ruby 的语义。

      例如,YARV 优化了nilfalsetrueFixnums(Integers 适合 n-1 位,其中 n 是机器字的大小)、flonums ( Floats 适合 n-2 位,对于 n >= 64) 和某些 Symbols,这样做的一个副作用是这些对象总是具有相同的 object_id。但是,这并不能保证,例如,当引入 flonums 时,nilobject_id4 更改为 8

      【讨论】:

      • 所以真正的问题是:为什么:symbol.object_id 在 Rails 控制台和 IRB 中返回相同的值(除非是巧合)?
      • 很可能是某种缓存优化。我没有跟上 YARV 的最新发展,特别是支持 GC 的 Symbols(我发现 JRuby+Truffle 更有趣),所以我不能肯定地说。可能是那些波兰语łs 的编码不同,如果object_id 编码相同,它们将是相同的。或者缓存仅适用于纯 7 位 ASCII Symbols。
      猜你喜欢
      • 2016-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-08
      • 1970-01-01
      相关资源
      最近更新 更多