動かざることバグの如し

近づきたいよ 君の理想に

Ruby Time.parseよりTime.newの方が高速

環境

結論

  • Time.parse より Time.new の方がメチャクチャ速い

ベンチマーク

require 'benchmark'
require 'time'

# テスト用の ISO8601 形式の時間文字列
time_string = "2024-07-31T12:34:56+09:00"

# 繰り返し回数
n = 100_000

Benchmark.bmbm do |x|
  x.report("Time.parse") { n.times { Time.parse(time_string) } }
  x.report("Time.iso8601") { n.times { Time.iso8601(time_string) } }
  x.report("Time.new") { n.times { Time.new(time_string) } }
end

結果は以下

Rehearsal ------------------------------------------------
Time.parse     0.766202   0.002829   0.769031 (  0.770122)
Time.iso8601   0.249893   0.001080   0.250973 (  0.251185)
Time.new       0.028568   0.000223   0.028791 (  0.028991)
--------------------------------------- total: 1.048795sec

                   user     system      total        real
Time.parse     0.720353   0.002016   0.722369 (  0.722568)
Time.iso8601   0.247730   0.005323   0.253053 (  0.253272)
Time.new       0.028483   0.000214   0.028697 (  0.028856)

理由

Time.parseが遅いのは、汎用的な日時文字列の解析に対応するために複雑な正規表現を使ってるからだ。一方、Time.newはISO8601形式に特化してるから、余分な処理が省ける。さらに、Time.newはC言語レベルで実装されてるから、Rubyで書かれたTime.parseよりも高速に動く。これが、Time.newがTime.parseよりも速い理由だ。