1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

高速なのは Range#cover? or Range#include? or ActiveSupport::TimeWithZone#between? それとも?

Last updated at Posted at 2020-07-15

rubocop-performance を確認していたら、

Performance/RangeInclude: Use Range#cover? instead of Range#include?.

が出たのでベンチマークを取ってみました。

require 'bundler/setup'
require 'benchmark_driver'

Benchmark.driver do |x|
  x.prelude <<~RUBY
  require 'active_support/time'
  t = Time.current + 5.minutes
  RUBY

  x.report 'include?', %[ (Time.current..Float::INFINITY).include?(t) ]
  x.report 'cover?', %[ (Time.current..Float::INFINITY).cover?(t) ]
  x.report 'between?', %[ t.between?(Time.current, Float::INFINITY) ]
  x.report 'raw_function', %[ t >= Time.current && t <=  Float::INFINITY ]
end

結果

Warming up --------------------------------------
            include?    85.071k i/s -     86.456k times in 1.016282s (11.75μs/i)
              cover?   131.933k i/s -    135.600k times in 1.027793s (7.58μs/i)
            between?   276.108k i/s -    285.615k times in 1.034434s (3.62μs/i)
        raw_function   285.200k i/s -    291.396k times in 1.021725s (3.51μs/i)
Calculating -------------------------------------
            include?   125.985k i/s -    255.212k times in 2.025732s (7.94μs/i)
              cover?   133.774k i/s -    395.799k times in 2.958713s (7.48μs/i)
            between?   304.505k i/s -    828.322k times in 2.720227s (3.28μs/i)
        raw_function   304.348k i/s -    855.600k times in 2.811255s (3.29μs/i)

Comparison:
            between?:    304504.7 i/s
        raw_function:    304348.1 i/s - 1.00x  slower
              cover?:    133774.0 i/s - 2.28x  slower
            include?:    125985.1 i/s - 2.42x  slower

include? から cover? に変更したほうが早いが、between? や便利機能使わずに普通に書いた raw_function の方が早くなりました。 後者の2つは実行するタイミングで順位がわかりましたが、ほぼ誤差の範囲だと思います。

ちなみに benchmark_driver では、 ymlで入力することもサポートしているので、

# range.yml
prelude: |
  require 'bundler/setup'
  require 'active_support/time'
  t = Time.current + 5.minutes

benchmark:
  include?: (Time.current..Float::INFINITY).include?(t)
  cover?: (Time.current..Float::INFINITY).cover?(t)
  between?: t.between?(Time.current, Float::INFINITY)
  raw_function: t >= Time.current && t <= Float::INFINITY

のようなファイルを用意して、

$ benchmark-driver range.yml

と書いても似たような結果を得られました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?