-
Jean Boussier authored
`Array#to_h` is substantially faster than `Hash::[]` because having a stricter interface it can preallocate the hash with the right size. We also freeze the strings early so that `Hash#[]` doesn't have to dup them. ```ruby require 'benchmark/ips' puts RUBY_VERSION class Object def instance_values Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }] end def instance_values_opt instance_variables.to_h do |ivar| [ivar[1..-1].freeze, instance_variable_get(ivar)] end end end SMALL = Object.new 2.times { |i| SMALL.instance_variable_set(:"@variable_#{i}", i) } LARGE = Object.new 15.times { |i| LARGE.instance_variable_set(:"@variable_#{i}", i) } { 'SMALL' => SMALL, 'LARGE' => LARGE }.each do |size, object| puts "=== #{size} ===" Benchmark.ips do |x| x.report('original') { object.instance_values } x.report('patched') { object.instance_values_opt } x.compare! end end ``` ``` 3.1.0 === SMALL === Warming up -------------------------------------- original 95.429k i/100ms patched 116.046k i/100ms Calculating ------------------------------------- original 963.241k (± 1.3%) i/s - 4.867M in 5.053433s patched 1.246M (± 0.8%) i/s - 6.266M in 5.031372s Comparison: patched: 1245570.0 i/s original: 963240.9 i/s - 1.29x (± 0.00) slower === LARGE === Warming up -------------------------------------- original 15.799k i/100ms patched 18.285k i/100ms Calculating ------------------------------------- original 157.163k (± 1.3%) i/s - 789.950k in 5.027176s patched 181.587k (± 1.1%) i/s - 914.250k in 5.035344s Comparison: patched: 181587.4 i/s original: 157163.4 i/s - 1.16x (± 0.00) slower ```
Jean Boussier authored`Array#to_h` is substantially faster than `Hash::[]` because having a stricter interface it can preallocate the hash with the right size. We also freeze the strings early so that `Hash#[]` doesn't have to dup them. ```ruby require 'benchmark/ips' puts RUBY_VERSION class Object def instance_values Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }] end def instance_values_opt instance_variables.to_h do |ivar| [ivar[1..-1].freeze, instance_variable_get(ivar)] end end end SMALL = Object.new 2.times { |i| SMALL.instance_variable_set(:"@variable_#{i}", i) } LARGE = Object.new 15.times { |i| LARGE.instance_variable_set(:"@variable_#{i}", i) } { 'SMALL' => SMALL, 'LARGE' => LARGE }.each do |size, object| puts "=== #{size} ===" Benchmark.ips do |x| x.report('original') { object.instance_values } x.report('patched') { object.instance_values_opt } x.compare! end end ``` ``` 3.1.0 === SMALL === Warming up -------------------------------------- original 95.429k i/100ms patched 116.046k i/100ms Calculating ------------------------------------- original 963.241k (± 1.3%) i/s - 4.867M in 5.053433s patched 1.246M (± 0.8%) i/s - 6.266M in 5.031372s Comparison: patched: 1245570.0 i/s original: 963240.9 i/s - 1.29x (± 0.00) slower === LARGE === Warming up -------------------------------------- original 15.799k i/100ms patched 18.285k i/100ms Calculating ------------------------------------- original 157.163k (± 1.3%) i/s - 789.950k in 5.027176s patched 181.587k (± 1.1%) i/s - 914.250k in 5.035344s Comparison: patched: 181587.4 i/s original: 157163.4 i/s - 1.16x (± 0.00) slower ```
Loading