我需要编写脚本来解析大型输入数据 (30GB)。我需要从 stdin 文本中提取所有数字并按顺序 desc 输出。
使用示例:
cat text_file_30gb.txt |脚本
现在我用于解析:
numbers = []
$stdin.each_line do |line|
numbers += line.scan(/\d+/).map(&:to_i)
end
numbers.uniq!.sort!.reverse!
但我试图将文本从 60MB 文件传递到脚本,它解析了 50 分钟
有加速脚本的方法吗?
更新。分析结果:
%self total self wait child calls name
95.42 5080.882 4848.293 0.000 232.588 1 IO#each_line
3.33 169.246 169.246 0.000 0.000 378419 String#scan
0.26 15.148 13.443 0.000 1.705 746927 <Class::Time>#now
0.18 9.310 9.310 0.000 0.000 378422 Array#uniq!
0.15 14.446 7.435 0.000 7.011 378423 Array#map
0.14 7.011 7.011 0.000 0.000 8327249 String#to_i
0.10 5.179 5.179 0.000 0.000 378228 Array#sort!
0.03 1.508 1.508 0.000 0.000 339416 String#%
0.03 1.454 1.454 0.000 0.000 509124 Symbol#to_s
0.02 0.993 0.993 0.000 0.000 48488 IO#write
0.02 1.593 0.945 0.000 0.649 742077 Numeric#quo
0.01 0.649 0.649 0.000 0.000 742077 Fixnum#fdiv
0.01 0.619 0.619 0.000 0.000 509124 String#intern
0.01 0.459 0.459 0.000 0.000 315172 Fixnum#to_s
0.01 0.453 0.453 0.000 0.000 746927 Fixnum#+
0.01 0.383 0.383 0.000 0.000 72732 Array#reject
0.01 16.100 0.307 0.000 15.793 96976 *Enumerable#inject
0.00 15.793 0.207 0.000 15.585 150322 *Array#each
...
最佳答案
感谢您提出的出色问题。
我挖了半天。但是,我认为这是将 50 分钟标记减少到 11 分钟的快速修复方法。至少快 4.5 倍。
require 'ruby-prof'
def profile(&block)
RubyProf::FlatPrinter.new(RubyProf.profile(&block)).print($stdout)
end
numbers = []
profile do
$stdin.each_line do |line|
line.scan(/\d+/) {|digit| numbers << digit.to_i }
end
numbers.uniq!.sort!.reverse!
end
原因很简单。如你所见+=
on array 分配新数组而不是将新值推送到现有引用。快速修复是使用 <<
反而。一个巨大的胜利,消除了整个滞后。
如果您处理较大的文件集,仍然会出现一些严重的故障。我脑子里什么都没有。
关于ruby - 解析大型标准输入 ruby,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46749170/