以前の関連する質問に基づいて、Enumerator
クラスを使用して無限のシーケンスを生成すると、パフォーマンスに大きなギャップがあることを発見しました。私が信じる前は、問題はEnumerable
方法take
にあると信じていましdrop
たが、次のベンチマークはこの主張を確認していません。
自然数ジェネレーターを作成し、間隔(10e7-10、10e7>:)で数値を表示する例
require 'benchmark'
nats_range = (1..Float::INFINITY)
nats_enum = Enumerator.new {|y| i=1; loop { y << i; i+=1 }}
puts "#{'_'*79+"\n"}Benchmarking Enumerable methods on Range ..."
puts Benchmark.measure { print nats_range.take(10**7).drop(10**7-10), "\n" }
puts "#{'_'*79+"\n"}Benchmarking Enumerable methods on Enumerator ..."
puts Benchmark.measure { print nats_enum.take(10**7).drop(10**7-10), "\n" }
$ ruby a.rb
_______________________________________________________________________________
Benchmarking Enumerable methods on Range ...
[9999991, 9999992, 9999993, 9999994, 9999995, 9999996, 9999997, 9999998, 9999999, 10000000]
1.570000 0.010000 1.580000 ( 1.576761)
_______________________________________________________________________________
Benchmarking Enumerable methods on Enumerator ...
[9999991, 9999992, 9999993, 9999994, 9999995, 9999996, 9999997, 9999998, 9999999, 10000000]
15.620000 0.020000 15.640000 ( 15.665156)
列挙子を使用した同等のコードは10倍遅くなります!
私はここで、この大きな違いを誰かが説明できるかどうか尋ねています。列挙子を不適切に使用しますか?これは現在のRuby実装での既知のリグレッションですか?
MRI Ruby 1.9.3p385