我在ruby中运行一个相当大的内存密集型程序,它最初很快,然后随着内存利用率的增加而减慢。
该程序有两个阶段:(1)在内存中构建一个大的hash: string => list
,(2)对哈希进行一些计算。减速发生在第1阶段。
为什么会这样?是否有更多的垃圾收集器调用?或者ruby将内存交换到磁盘?
在任何一种情况下,我都可以采取任何配置来加快速度吗?例如,我可以增加允许ruby使用的堆大小或最大内存量吗?我在手册页中没有看到任何内容。
答案 0 :(得分:1)
我发现使用大型数据集时ruby也非常慢,我处理它的方法是运行ruby 1.9.2或更高版本,如果可能的话甚至是jruby。如果这还不够,当遍历极大的数据集时,我通常会恢复到mapreduce范例,这样我只需要在内存中保留一行。对于类似于构建哈希的问题,我只需要一个ruby程序向$ stdout发出链接或将输出转移到文件:
$ ruby build_csv.rb > items.csv
$ cat items.csv
foo,23
foo,17
bar,42
然后有第二个程序可以将数据结构读入哈希
@hsh = Hash.new { |hash, key| hash[key] = [] }
File.open("items.csv").each_line do |l|
k,v = l.split(',')
@hsh[k] << v
end
如果使用CSV库,以前的程序当然可以更快。无论如何,它会在hsh中读到这样的东西。
@hsh => {"foo"=>[23, 17], "bar"=>[42]}
将问题拆分成许多小程序确实会对速度产生影响,因为在内存中保留较少的内容,如果哈希上的操作只需要在单个键上运行,那么很容易将该部分写为只是读取直到找到新密钥,在最后一个密钥上产生输出,然后继续使用新密钥,与第一轮的方式大致相同。通过在文件中分割和生成中间结果来保持内存使用,这确实加快了这个过程。如果您可以划分数据,还可以在shell中或使用线程一次运行多个第一阶段/映射作业。