5

我想以相当快速和有效的方式对大型数据文件进行切片和切块,直至演出。如果我使用 UNIX 的“CUT”之类的东西,它会非常快,即使在 CYGWIN 环境中也是如此。

我已经尝试开发各种 Ruby 脚本并对其进行基准测试来处理这些文件,并且总是以冰冷的结果结束。

你会在 Ruby 中做什么来让这条狗不那么慢?

4

4 回答 4

2

这个问题让我想起了 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 的记录。

于 2008-09-23T21:43:14.627 回答
1

我猜您的 Ruby 实现在处理之前正在读取整个文件。Unix 的剪切通过一次读取一个字节并立即转储到输出文件来工作。当然会涉及一些缓冲,但不会超过几 KB。

我的建议:尝试使用尽可能少的分页或回溯进行就地处理。

于 2008-09-23T21:50:01.630 回答
1

为什么不将它们结合在一起 - 使用 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|
}
于 2008-09-23T22:20:42.540 回答
0

我怀疑问题是红宝石正在读取内存中的整个文件。运行命令时查看内存和磁盘使用情况进行验证。

我猜主要原因是因为 cut 是用 C 编写的并且只做一件事,所以它可能已经被编译成非常金属。它可能并没有比调用系统调用做更多的事情。

然而,ruby 版本可以同时做很多事情。在 ruby​​ 中调用方法比 C 函数调用慢得多。

记住老年和背叛在 unix 中击败了青年和技能:http ://ridiculousfish.com/blog/archives/2006/05/30/old-age-and-treachery/

于 2008-09-23T21:56:20.163 回答