我需要编写用于解析大输入数据(30GB)的脚本。我需要从stdin文本中提取所有数字并按顺序desc输出。
用法示例:
cat text_file_30gb.txt | script
现在我用于解析:
numbers = []
$stdin.each_line do |line|
numbers += line.scan(/\d+/).map(&:to_i)
end
numbers.uniq!.sort!.reverse!
但我尝试将文本从60MB文件传递到脚本,并将其解析为50分钟
是加速脚本的方法吗?
UPD。分析结果:
%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
...
答案 0 :(得分:4)
感谢您提出的优秀问题。
我无法挖掘很长时间。然而,这是我可以看到的快速解决方案,将缩短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
原因很简单。正如您所看到的,+=
在数组上分配新数组而不是将新值推送到现有引用。快速解决方法是使用<<
代替。一场大胜,一路下滑。
但是,如果你玩更大的文件集,还有一些重大的故障。我头脑中没有任何东西。