2017-10-14 35 views
2

我需要編寫解析大型輸入數據(30GB)的腳本。我需要從標準輸入文本中提取所有數字並通過順序desc輸出。用法解析大型stdin ruby​​

例子: 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

好吧,您可能無法一次保存所有30 GB的內存,因此您需要將它們排序在磁盤上。另外,如果你沒有使用ruby做這個(而不是使用C或者其他),它可能會更快。 – Adrian

+0

@Adrian我絕對同意你的意見,但我需要在Ruby上做這個考試:( – QNester

+0

)你是否嘗試過類似'IO.foreach('text_file_30gb.txt').lazy.grep(/ \ d + /)'。這可能有所幫助:http://blog.honeybadger.io/using-lazy-enumerators-to-work-with-large-files-in-ruby/ – Cyzanfar

回答

2

感謝您的出色問題。

我很久沒挖了。不過,這是我可以看到的一個快速解決方案,以減少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 

原因很簡單。正如你可以看到在陣列上+=分配新的數組,而不是將新值推送到現有的引用。快速解決方法是使用<<。在整個滯後期間取得巨大成功。

儘管如此,如果您使用更大的文件集,還是會出現一些重大的故障。我沒有什麼頭腦。

+0

這太棒了!非常感謝你 – QNester

+0

不客氣,希望有所幫助。 @QNester –