I've got smth for you! May be it is a bit outdated but nevertheless – do you you Range#include? or Range#cover? when you want to check if the value is inside the range?

The spoiler is use Range#cover?. Some benchmarks under the cut.


Here is a piece of code that performs benchmark:

require 'benchmark'
require 'benchmark/ips'
require 'date'

TEST_METHODS = %w(include? cover?)

def test_range power
  (Date.today - 10 ** power)..Date.today

def report_name range, test_method
  "#{(range.max - range.min).to_i}_#{test_method}"

def benchmark! powers = 1..5, date = Date.today
  Benchmark.ips do |report|
    powers.each do |power|
      TEST_METHODS.each do |test_method|
        range = test_range(power)

        report.report(report_name(range, test_method)) do
          range.send(test_method, date)


# -------------------------------------------------
#          10_include?   115259.6 (±20.8%) i/s -     556149 in   5.057327s
#            10_cover?  1753269.8 (±12.9%) i/s -    8638700 in   5.034635s
#         100_include?    14864.8 (±16.9%) i/s -      72750 in   5.032755s
#           100_cover?  1798267.7 (±6.5%) i/s -    8970676 in   5.013039s
#        1000_include?     1482.4 (±18.2%) i/s -       7203 in   5.021981s
#          1000_cover?  1812622.5 (±5.8%) i/s -    9037590 in   5.005734s
#       10000_include?      160.4 (±17.5%) i/s -        784 in   5.037745s
#         10000_cover?  1791249.5 (±6.6%) i/s -    8909254 in   4.997718s
#      100000_include?       15.8 (±25.3%) i/s -         75 in   5.048941s
#        100000_cover?  1854601.5 (±3.6%) i/s -    9290084 in   5.016394s

range benchmark

As you can see cover? is much faster and its speed is independent of range size. Why it is so?




Take a look at the method source and you will see that it simply compares input value with min (left) and max (right) values of range. So it is obvious that speed of method is independent of range size – it is just several comparisons which need constant time.



From the first view it is obvious that there are more work inside include? – 45 vs 18 LOC. The thing is that inside include? method every point of range gets instantiated and compared to value. So as you can see there is perfect O(N) on the graph.

include? is optimized for numbers and strings but if you have more complex range (with Date for example) you should be careful.


Be careful when using include? and cover? simply because of that:

# => false 
# => true 
'a' < 'blah'
# => true 
'blah' < 'z'
# => true 

Great thx to @Mik-die for reviewing this post.

Good luck with factoring fast code!

#ruby #benchmark