2014-05-07 23 views
6

Ho scritto un semplice script che dovrebbe leggere un'intera directory e quindi analizzare i dati HTML in uno script normale eliminando i tag HTML e quindi scrivendoli in un unico file.Impossibile allocare memoria (No MemoryError) in Ruby?

Ho una memoria da 8 GB e anche molta memoria virtuale disponibile. Quando lo faccio ho più di 5 GB di RAM disponibili. Il file più grande nella directory è 3,8 GB.

Lo script è

file_count = 1 
File.open("allscraped.txt", 'w') do |out1| 
    for file_name in Dir["allParts/*.dat"] do 
     puts "#{file_name}#:#{file_count}" 
     file_count +=1 
     File.open(file_name, "r") do |file| 
      source = "" 
      tmp_src = "" 
      counter = 0 
      file.each_line do |line| 
       scraped_content = line.gsub(/<.*?\/?>/, '') 
       tmp_src << scraped_content 
       if (counter % 10000) == 0 
        tmp_src = tmp_src.gsub(/\s{2,}/, "\n") 
        source << tmp_src 
        tmp_src = "" 
        counter = 0 
       end 
       counter += 1 
      end 
      source << tmp_src.gsub(/\s{2,}/, "\n") 
      out1.write(source) 
      break 
     end 
    end 
end 

Il codice di errore completo è:

realscraper.rb:33:in `block (4 levels) in <main>': failed to allocate memory (No 
MemoryError) 
     from realscraper.rb:27:in `each_line' 
     from realscraper.rb:27:in `block (3 levels) in <main>' 
     from realscraper.rb:23:in `open' 
     from realscraper.rb:23:in `block (2 levels) in <main>' 
     from realscraper.rb:13:in `each' 
     from realscraper.rb:13:in `block in <main>' 
     from realscraper.rb:12:in `open' 
     from realscraper.rb:12:in `<main>' 

Dove linea # 27 è file.each_line do |line| e 33 è source << tmp_src. Il file in errore è il più grande (3,8 GB). Qual è il problema qui? Perché ricevo questo errore anche se ho abbastanza memoria? Inoltre come posso ripararlo?

+0

Quanto è grande il file che non riesce? Ha newlines? – Patru

+0

Inizia aggiungendo la registrazione per vedere se fallisce su un file specifico o dopo un certo tempo. Se fallisce sempre nello stesso file, prova ad eseguirlo su una cartella con solo questo file. Ti darebbe preziose informazioni. – Martin

+0

@Patru, grazie per l'avviso, ho aggiornato la mia risposta. È il più grande. –

risposta

9

Il problema è su queste due linee:

source << tmp_src 
source << tmp_src.gsub(/\s{2,}/, "\n") 

Quando si legge un file di grandi dimensioni che si sta lentamente crescendo una stringa di grandi dimensioni in memoria.

La soluzione più semplice è di non utilizzare questa stringa temporanea source, ma di scrivere i risultati direttamente nel file. Basta sostituire quelle due righe con questo, invece:

# source << tmp_src 
out1.write(tmp_src) 

# source << tmp_src.gsub(/\s{2,}/, "\n") 
out1.write(tmp_src.gsub(/\s{2,}/, "\n"))      

In questo modo non sta creando grossi stringhe temporanee in memoria e dovrebbe funzionare meglio (e più veloce) in questo modo.

Problemi correlati