我正在用 ruby 运行一个内存密集型程序,该程序最初速度很快,然后随着内存利用率的增加而减慢。
该程序有两个阶段:(1) 在内存中构建一个大的hash: string => list
,(2) 对散列进行一些计算。减速发生在第 1 阶段。
为什么会这样?是不是垃圾收集器的调用次数多了?还是 ruby 将内存交换到磁盘?
在任何一种情况下,我可以做任何配置来加快速度吗?例如,我可以增加堆大小或允许 ruby 使用的最大内存量吗?我在手册页中没有看到任何内容。
最佳答案
我发现 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]}
将一个问题拆分成许多小程序确实对速度有影响,因为内存中保留的更少,如果对哈希的操作只需要对单个键进行操作,那么很容易将该部分编写为仅读取直到找到新 key ,在最后一个 key 上产生输出,然后继续使用新 key ,其方式与第一轮大致相同。像这样通过在文件上拆分和生成中间结果来降低内存使用率确实大大加快了该过程。如果可以划分数据,则还可以在 shell 中或使用线程同时运行多个第一阶段/映射作业。
关于ruby - 使内存密集型程序的 ruby 更快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7562131/