我正在尝试处理大量数字列表:
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说:
枚举::懒惰不是银弹;它删除了开销 创建一个中间数组,但带来了调用的缺点 一个街区。不幸的是,后者比前者大得多。 因此,通常,懒惰确实带来了性能弊端。
我刚刚想到的一个类比:想象您正在为朋友建造一些家具。
-
非懒惰:您要建造整个东西,租卡车,然后开车给您的朋友。
-
懒惰:您要建造一些小块,然后用汽车将其驱车给您的朋友。您可以建造下一个小块,然后用汽车将其驱赶到您的朋友。您可以建造下一个小块,然后用汽车将其驱赶到您的朋友。等等。
是的,租那辆卡车是额外的开销,但是与一遍又一遍地开车相比,这没什么。
懒惰可以节省时间的真正原因是,在您的朋友发现您和他的妻子睡觉的前几件作品之后,现在您不再是朋友,他不再想要您的愚蠢家具根本不构建其余部分。