One of the performance matter we usually encounter is Enumerator. Today, I introduce you a kind of performance issue we ever faced about enumerator.
That’s Enumerator in ruby. The case is when we enumerate a large range. For instance, (1..1000_000). That’s when we just need to use first 100 elements but in fact, system perform all of 1.000.000 elements. It’s not necessary, is it?
The solution we usually see about improving performance is lazy load. We can refer the lazy load for images: https://github.com/verlok/lazyload
Diving deep in ruby library we can see:
Below is the Lazy class in rubystub 2.3 for your reference. Lazy class provided methods to support Lazy load.
class Lazy < Enumerator
end
module Enumerable
def lazy()
#This is a stub, used for indexing
end
end
class Range
include Enumerable
end
Enumerable provided lazy method returned Lazy instance. Making it convenient for us to use with Range:
irb(main):001:0> (1..1000_000).class
=> Range
Thus, our code is:
(1..1000_000).lazy.map {|n| n * 2}.first(100)
Performing below code to see the comparison between normal enumerator and lazy enumerator:
require 'benchmark/ips'
Benchmark.ips do |x|
x.config(:time => 5, :warmup => 2)
x.report("Enumerations") do
(1..1000_000).map {|n| n * 2}.first(100)
end
x.report("Lazy Enumerations") do
(1..1000_000).lazy.map {|n| n * 2}.first(100)
end
x.compare!
end
Result:
➜ performance git:(master) ✗ ruby enum.rb
Warming up --------------------------------------
Enumerations 11.000 i/100ms
Lazy Enumerations 9.730k i/100ms
Calculating -------------------------------------
Enumerations 118.665 (± 5.9%) i/s - 594.000 in 5.024046s
Lazy Enumerations 100.515k (± 4.8%) i/s - 505.960k in 5.045457s
Comparison:
Lazy Enumerations: 100515.4 i/s
Enumerations: 118.7 i/s - 847.05x slower
➜ performance git:(master) ✗ ruby enum.rb
Warming up --------------------------------------
Enumerations 1.000 i/100ms
Lazy Enumerations 2.675k i/100ms
Calculating -------------------------------------
Enumerations 12.166 (± 8.2%) i/s - 61.000 in 5.028548s
Lazy Enumerations 27.269k (± 3.6%) i/s - 136.425k in 5.009590s
Comparison:
Lazy Enumerations: 27269.0 i/s
Enumerations: 12.2 i/s - 2241.44x slower