2013-10-03 7 views
5

Je ne suis pas sûr que cette question est liée à ruby ​​seulement, peut-être que vous le trouverez utile à toute autre langue.performance: ruby ​​CSV.foreach vs CSV.parse

Je me demande si je devrais utiliser Parse ou foreach:

  • CSV.parse(filepath) va analyser le fichier entier et retourner un tableau de tableaux, qui reflétera le fichier csv et seront stockés dans la mémoire. Plus tard, je vais traiter ces lignes de tableau.

  • CSV.foreach(filepath) va lire/analyser le fichier ligne par ligne et le traiter ligne par ligne.

En matière de performance, y a-t-il une différence? Y a-t-il une approche préférable? PS: Je sais que dans ruby ​​je peux fournir un bloc avec la méthode d'analyse et ensuite il va gérer chaque rangée séparément.

+1

Différence de performance? Cela dépend probablement de la taille de vos fichiers CSV et de la façon dont vous travaillez avec eux. Vous pouvez répondre vous-même à cette question en comparant la façon dont vous utiliseriez les choses dans votre situation. –

+0

Bonjour @muistooshort, merci pour votre réponse. J'ai eu votre réponse, et je vais simplement mesurer la rapidité de l'analyse et la quantité de mémoire et de CPU utilisée pendant le processus. En général, les très gros fichiers doivent généralement être traités ligne par ligne et si le fichier est suffisamment léger, il peut être chargé en mémoire, n'est-ce pas? – benams

+1

Habituellement je suppose. Cela dépend du style qui a du sens pour ce que vous faites. –

Répondre

5

Voici mon test:

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) 

Les benchmarks ont été réalisés sur un Macbook Pro avec 8 Go de mémoire. Les résultats indiquent que les performances sont statistiquement équivalentes en utilisant CSV # parse ou CSV # foreach.

Options têtes Suppressions (seul petit fichier testé):

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) 

Notes:

large_csv_file était d'une structure différente de celle des résultats small_csv_file et donc de comparaison (c.-à-lignes/sec) entre les deux fichiers serait être inexact.

small_csv_file avait 50.000 dossiers

large_csv_file had 1,000,000 records

option de têtes définie sur true réduit considérablement les performances en raison de la construction d'un hachage pour chaque champ de la ligne (voir la section HeadersConverters: http://www.ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html)

+0

Je doute que la question concerne autant l'utilisation et le temps de l'unité centrale que l'utilisation de la mémoire. Si vous effectuez une action sur chaque ligne, seule la ligne en mémoire est conservatrice. Si vous obtenez un tableau de tableaux, l'utilisation de la mémoire doit être la même. –