fastruby / fast-ruby

:dash: Writing Fast Ruby :heart_eyes: -- Collect Common Ruby idioms.
https://github.com/fastruby/fast-ruby
5.67k stars 376 forks source link

Enumerable#reverse_each.detect is even faster than Enumerable#reverse.detect #54

Closed michaelmior closed 9 years ago

michaelmior commented 9 years ago

This also avoids an extra array allocation for #reverse

require 'benchmark/ips'

ARRAY = [*1..100]

def really_fast
    ARRAY.reverse_each.detect { |x| (x % 10).zero? }
end

def fast
  ARRAY.reverse.detect { |x| (x % 10).zero? }
end

def slow
  ARRAY.select { |x| (x % 10).zero? }.last
end

Benchmark.ips do |x|
  x.report('Enumerable#reverse_each.detect') { really_fast }
  x.report('Enumerable#reverse.detect') { fast }
  x.report('Enumerable#select.last')    { slow }
  x.compare!
end
Calculating -------------------------------------
Enumerable#reverse_each.detect
                        46.838k i/100ms
Enumerable#reverse.detect
                        42.859k i/100ms
Enumerable#select.last
                        11.124k i/100ms
-------------------------------------------------
Enumerable#reverse_each.detect
                        933.887k (± 1.9%) i/s -      4.684M
Enumerable#reverse.detect
                        808.326k (± 3.1%) i/s -      4.072M
Enumerable#select.last
                        127.865k (± 4.4%) i/s -    645.192k

Comparison:
Enumerable#reverse_each.detect:   933887.0 i/s
Enumerable#reverse.detect:   808325.8 i/s - 1.16x slower
Enumerable#select.last:   127865.2 i/s - 7.30x slower
JuanitoFatas commented 9 years ago

reverse_each vs reverse.each already been covered by this example. So I did not include here. Feel free to include this one with a Pull Request, thank you! @michaelmior

michaelmior commented 9 years ago

True. It just seems odd to use something which is explicitly shown elsewhere to be slower.