我想以相当快速和有效的方式对大型数据文件进行切片和切块,直至演出。如果我使用 UNIX 的“CUT”之类的东西,它会非常快,即使在 CYGWIN 环境中也是如此。
我已经尝试开发各种 Ruby 脚本并对其进行基准测试来处理这些文件,并且总是以冰冷的结果结束。
你会在 Ruby 中做什么来让这条狗不那么慢?
我想以相当快速和有效的方式对大型数据文件进行切片和切块,直至演出。如果我使用 UNIX 的“CUT”之类的东西,它会非常快,即使在 CYGWIN 环境中也是如此。
我已经尝试开发各种 Ruby 脚本并对其进行基准测试来处理这些文件,并且总是以冰冷的结果结束。
你会在 Ruby 中做什么来让这条狗不那么慢?
这个问题让我想起了 Tim Bray 的Wide Finder 项目。他可以使用 Ruby 读取 Apache 日志文件并找出哪些文章被获取最多的最快方法是使用以下脚本:
counts = {}
counts.default = 0
ARGF.each_line do |line|
if line =~ %r{GET /ongoing/When/\d\d\dx/(\d\d\d\d/\d\d/\d\d/[^ .]+) }
counts[$1] += 1
end
end
keys_by_count = counts.keys.sort { |a, b| counts[b] <=> counts[a] }
keys_by_count[0 .. 9].each do |key|
puts "#{counts[key]}: #{key}"
end
在去年的 1.67Ghz PowerBook 上,这段代码花费了 7.5 秒的 CPU 时间,13.5 秒的时间,处理了一百万个并更改了大约四分之一 g 的记录。
我猜您的 Ruby 实现在处理之前正在读取整个文件。Unix 的剪切通过一次读取一个字节并立即转储到输出文件来工作。当然会涉及一些缓冲,但不会超过几 KB。
我的建议:尝试使用尽可能少的分页或回溯进行就地处理。
为什么不将它们结合在一起 - 使用 cut 来做它最擅长的事情并使用 ruby 来提供胶水/增值以及 CUT 的结果?您可以通过将它们放在反引号中来运行 shell 脚本,如下所示:
puts `cut somefile > foo.fil`
# process each line of the output from cut
f = File.new("foo.fil")
f.each{|line|
}
我怀疑问题是红宝石正在读取内存中的整个文件。运行命令时查看内存和磁盘使用情况进行验证。
我猜主要原因是因为 cut 是用 C 编写的并且只做一件事,所以它可能已经被编译成非常金属。它可能并没有比调用系统调用做更多的事情。
然而,ruby 版本可以同时做很多事情。在 ruby 中调用方法比 C 函数调用慢得多。
记住老年和背叛在 unix 中击败了青年和技能:http ://ridiculousfish.com/blog/archives/2006/05/30/old-age-and-treachery/