🌟

[Feature #20415] 文字列リテラルの hash 値をコンパイル時に計算することで高速化する

2024/06/10に公開

[Feature #20415] Precompute literal String hash code during compilation

  • 文字列リテラルの hash 値をコンパイル時に計算することで Hash へのアクセスを高速化するチケット
  • これにより hash["hoge"]hash[:hoge] のような Symbol でのアクセスと同等の速さにすることを目標としているらしい
  • こういう高速化のアイディア面白いですよねーそして実際に開発版の Ruby 3.4 で取り込まれました
  • 手元で試してみたら確かに高速化してた
require "benchmark/ips"

hash = 10.times.to_h do |i|
  [i, i]
end

dyn_sym = "dynamic_symbol".to_sym
hash[:some_symbol] = 1
hash[dyn_sym] = 1
hash["small"] = 2
hash["frozen_string_literal"] = 2

Benchmark.ips do |x|
  x.report("symbol") { hash[:some_symbol] }
  x.report("dyn_symbol") { hash[:some_symbol] }
  x.report("small_lit") { hash["small"] }
  x.report("frozen_lit") { hash["frozen_string_literal"] }
  x.compare!(order: :baseline)
end
ruby 3.3.2 (2024-05-30 revision e5a195edf6) [x86_64-linux]
Warming up --------------------------------------
              symbol     2.666M i/100ms
          dyn_symbol     2.781M i/100ms
           small_lit     2.366M i/100ms
          frozen_lit     2.274M i/100ms
Calculating -------------------------------------
              symbol     26.179M (± 0.8%) i/s -    133.279M in   5.091356s
          dyn_symbol     26.336M (± 1.0%) i/s -    133.485M in   5.069139s
           small_lit     23.766M (± 1.6%) i/s -    120.667M in   5.078672s
          frozen_lit     22.788M (± 0.9%) i/s -    115.979M in   5.089744s

Comparison:
              symbol: 26179265.3 i/s
          dyn_symbol: 26335757.4 i/s - same-ish: difference falls within error
           small_lit: 23765856.6 i/s - 1.10x  slower
          frozen_lit: 22788460.8 i/s - 1.15x  slower
ruby 3.4.0dev (2024-06-07T21:59:59Z master 0d91887c6a) [x86_64-linux]
Warming up --------------------------------------
              symbol     1.933M i/100ms
          dyn_symbol     1.926M i/100ms
           small_lit     1.936M i/100ms
          frozen_lit     1.929M i/100ms
Calculating -------------------------------------
              symbol     19.662M (± 2.1%) i/s -     98.563M in   5.015106s
          dyn_symbol     19.632M (± 2.5%) i/s -     98.226M in   5.006520s
           small_lit     19.386M (± 1.3%) i/s -     98.714M in   5.092814s
          frozen_lit     19.253M (± 1.7%) i/s -     96.426M in   5.009729s

Comparison:
              symbol: 19661821.9 i/s
          dyn_symbol: 19631729.0 i/s - same-ish: difference falls within error
           small_lit: 19386290.5 i/s - same-ish: difference falls within error
          frozen_lit: 19253290.4 i/s - same-ish: difference falls within error
  • 実アプリケーションでも文字列リテラれるでアクセスすることはまあまあありそう
GitHubで編集を提案

Discussion