Skip to content

Possible optimization of instance_variable_get ? #3419

@PragTob

Description

@PragTob

.@mrbrdo posed an interesting question in a comment to my meta programming benchmarking post about whether instance_variable get for strings/symbols could be optimized in the VM somehow.

Right now, according to my benchmark, it is about 3 times as slow to call instance_variable_get with a frozen string than it is to use the instance variable directly.

Benchmark code for direct reference:

class Test
  def intitialize
    @ivar = 'test'
  end

  def direct
    @ivar
  end

  IVAR_NAME = "@ivar"
  def hoist_ivar_name
    instance_variable_get IVAR_NAME
  end

  def instance_variable_get_symbol
    instance_variable_get :"@ivar"
  end

  def instance_variable_get_frozen
    instance_variable_get('@ivar'.freeze)
  end

  def instance_variable_get_frozen_symbol
    instance_variable_get('@ivar'.freeze.to_sym)
  end
end

Benchmark.ips do |benchmark|

  instance = Test.new
  benchmark.report("direct") {instance.direct}
  benchmark.report("hoist_ivar_name") {instance.hoist_ivar_name}
  benchmark.report("ivar get symbol") {instance.instance_variable_get_symbol}
  benchmark.report("ivar get frozen") {instance.instance_variable_get_frozen}
  benchmark.report("ivar get frozen sym") {instance.instance_variable_get_frozen_symbol}
end

Results with JRuby 9.0.0.3:

tobi@airship ~ $ ruby ivar_get.rb 
Calculating -------------------------------------
              direct   150.109k i/100ms
     hoist_ivar_name   140.955k i/100ms
     ivar get symbol   192.115k i/100ms
     ivar get frozen   158.494k i/100ms
 ivar get frozen sym   148.150k i/100ms
-------------------------------------------------
              direct     10.335M (±22.3%) i/s -     48.185M
     hoist_ivar_name      4.713M (±28.6%) i/s -     21.425M
     ivar get symbol      8.628M (±27.8%) i/s -     39.191M
     ivar get frozen      3.109M (± 4.7%) i/s -     15.532M
 ivar get frozen sym      5.500M (±15.0%) i/s -     26.519M
tobi@airship ~ $ ruby --server -Xcompile.invokedynamic=true ivar_get.rb 
Calculating -------------------------------------
              direct    91.369k i/100ms
     hoist_ivar_name   112.476k i/100ms
     ivar get symbol   113.564k i/100ms
     ivar get frozen   160.592k i/100ms
 ivar get frozen sym   158.691k i/100ms
-------------------------------------------------
              direct     10.812M (±19.7%) i/s -     50.162M
     hoist_ivar_name      5.402M (±28.8%) i/s -     24.070M
     ivar get symbol     10.310M (±12.7%) i/s -     49.968M
     ivar get frozen      3.163M (± 5.0%) i/s -     15.899M
 ivar get frozen sym      5.428M (±17.5%) i/s -     26.025M

Thanks for all your work, my original got faster thanks to Jruby 9.0.3.0 :)
Tobi

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions