Ruby 的"懒惰"性能不如分配庞大的列表?



我正在尝试处理大量数字列表:

require 'benchmark'
N = 999999
Benchmark.bm 10 do |bm|
   bm.report 'Eager:' do
 (0..N).select(&:even?).map{|x| x * x}.reduce(&:+)
   end  
   bm.report 'Lazy:' do
 (0..N).lazy.select(&:even?).map{|x| x * x}.reduce(&:+)
   end  
 end;

就我的理解,懒惰的版本应该更快,因为急切的版本需要分配两个半百万个项目的列表(一个用于select,一个用于map),而Lazy版本正在流式传输所有内容。

但是,当我运行它时,懒惰的版本的长度是渴望的两倍以上!(http://rextester.com/otex7399)

         user     system      total        real
Eager:       0.210000   0.010000   0.220000 (  0.216572)
Lazy:        0.580000   0.000000   0.580000 (  0.635091)

怎么可能?

我会说枚举者比内存要慢得多。

这也据报道,Ruby Core Team成员Yusuke Endoh说:

枚举::懒惰不是银弹;它删除了开销 创建一个中间数组,但带来了调用的缺点 一个街区。不幸的是,后者比前者大得多。 因此,通常,懒惰确实带来了性能弊端。


我刚刚想到的一个类比:想象您正在为朋友建造一些家具。

  • 非懒惰:您要建造整个东西,租卡车,然后开车给您的朋友。

  • 懒惰:您要建造一些小块,然后用汽车将其驱车给您的朋友。您可以建造下一个小块,然后用汽车将其驱赶到您的朋友。您可以建造下一个小块,然后用汽车将其驱赶到您的朋友。等等。

是的,租那辆卡车是额外的开销,但是与一遍又一遍地开车相比,这没什么。

懒惰可以节省时间的真正原因是,在您的朋友发现您和他的妻子睡觉的前几件作品之后,现在您不再是朋友,他不再想要您的愚蠢家具根本不构建其余部分。

相关内容

  • 没有找到相关文章

最新更新