2013-10-03 21 views
5

Non sono sicuro che questa domanda sia correlata solo a Ruby, forse la troverai rilevante per qualsiasi altra lingua.prestazioni: ruby ​​CSV.foreach vs CSV.parse

mi chiedo se dovrei usare analizzare o foreach:

  • CSV.parse(filepath) analizzerà l'intero file e restituire un array di array, che rifletterà il file CSV e verranno memorizzati nella memoria. Successivamente, elaborerò queste righe dell'array.

  • CSV.foreach(filepath) legge/analizza il file riga per riga e lo elabora riga per riga.

Quando si tratta di prestazioni, c'è qualche differenza? c'è un approccio preferibile?

PS: So che in ruby ​​posso fornire un blocco con il metodo parse e quindi gestirà ogni riga separatamente.

+1

Differenza di prestazioni? Ciò dipende probabilmente dalla grandezza dei tuoi file CSV e dal modo in cui stai lavorando con loro. Puoi rispondere a questa domanda abbastanza facilmente da te confrontandoti su come useresti le cose nella tua situazione. –

+0

Ciao @muistooshort, grazie per la tua risposta. Ho ricevuto la tua risposta e misurerò semplicemente quanto è veloce l'analisi e quanto è occupata la mia memoria e CPU durante il processo. In generale, i file di solito molto grandi devono essere elaborati riga per riga e se il file è sufficientemente leggero può essere caricato nella memoria, giusto? – benams

+1

Di solito suppongo. Dipende da quale stile ha senso per quello che stai facendo. –

risposta

5

Ecco la mia prova:

require 'csv' 
require 'benchmark' 

small_csv_file = "test_data_small_50k.csv" 
large_csv_file = "test_data_large_20m.csv" 

Benchmark.bmbm do |x| 
    x.report("Small: CSV #parse") do 
     CSV.parse(File.open(small_csv_file), headers: true) do |row| 
      row 
     end 
    end 

    x.report("Small: CSV #foreach") do 
     CSV.foreach(small_csv_file, headers: true) do |row| 
      row 
     end 
    end 

    x.report("Large: CSV #parse") do 
     CSV.parse(File.open(large_csv_file), headers: true) do |row| 
      row 
     end 
    end 

    x.report("Large: CSV #foreach") do 
     CSV.foreach(large_csv_file, headers: true) do |row| 
      row 
     end 
    end 
end 

Rehearsal ------------------------------------------------------- 
Small: CSV #parse  0.950000 0.000000 0.950000 ( 0.952493) 
Small: CSV #foreach 0.950000 0.000000 0.950000 ( 0.953514) 
Large: CSV #parse 659.000000 2.120000 661.120000 (661.280070) 
Large: CSV #foreach 648.240000 1.800000 650.040000 (650.062963) 
------------------------------------------- total: 1313.060000sec 

          user  system  total  real 
Small: CSV #parse  1.000000 0.000000 1.000000 ( 1.143246) 
Small: CSV #foreach 0.990000 0.000000 0.990000 ( 0.984285) 
Large: CSV #parse 646.380000 1.890000 648.270000 (648.286247) 
Large: CSV #foreach 651.010000 1.840000 652.850000 (652.874320) 

I benchmark sono stati eseguiti su un MacBook Pro con 8GB di memoria. I risultati indicano che le prestazioni sono statisticamente equivalenti utilizzando CSV # parse o CSV # foreach.

mangiare Headers rimosso (solo file di piccole testate):

require 'csv' 
require 'benchmark' 

small_csv_file = "test_data_small_50k.csv" 

Benchmark.bmbm do |x| 
    x.report("Small: CSV #parse") do 
     CSV.parse(File.open(small_csv_file)) do |row| 
      row 
     end 
    end 

    x.report("Small: CSV #foreach") do 
     CSV.foreach(small_csv_file) do |row| 
      row 
     end 
    end 
end 

Rehearsal ------------------------------------------------------- 
Small: CSV #parse  0.590000 0.010000 0.600000 ( 0.597775) 
Small: CSV #foreach 0.620000 0.000000 0.620000 ( 0.621950) 
---------------------------------------------- total: 1.220000sec 

          user  system  total  real 
Small: CSV #parse  0.590000 0.000000 0.590000 ( 0.597594) 
Small: CSV #foreach 0.610000 0.000000 0.610000 ( 0.604537) 

Note:

large_csv_file sia di una struttura diversa rispetto small_csv_file e quindi confrontando i risultati (cioè righe/sec) tra i due file sarebbero essere impreciso

small_csv_file avuto 50.000 record

large_csv_file avuto 1.000.000 record

opzione

intestazioni impostata su true riduce prestazioni significativamente a causa di costruire un hash per ogni campo nella riga (vedere la sezione HeadersConverters: http://www.ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html)

+0

dubito la questione è tanto circa l'utilizzo della CPU e il tempo come lo è l'utilizzo della memoria. Se si esegue un'azione su ogni riga, poi solo avendo la riga in memoria è conservativa. Se hai trovato un array di array, quindi l'utilizzo della memoria dovrebbe essere lo stesso. –