2013-10-03 6 views
5

Nie jestem pewien, czy to pytanie jest związane tylko z rubinem, może uznasz, że jest ono odpowiednie dla każdego innego języka.wydajność: ruby ​​CSV.foreach vs CSV.parse

Zastanawiam się, czy powinienem użyć parse lub foreach:

  • CSV.parse(filepath) będzie analizować całego pliku i zwraca tablicę tablic, które będą odzwierciedlać pliku csv i będą przechowywane w pamięci. Później przetworzę te wiersze tablicy.

  • CSV.foreach(filepath) odczyta/przeanalizuje plik wiersz po rzędzie i przetworzy go wiersz po wierszu.

Jeśli chodzi o wydajność, czy jest jakakolwiek różnica? czy istnieje preferowane podejście?

PS: Wiem, że w Ruby mogę podać blok za pomocą metody parsowania, a następnie zajmie się każdym wierszem osobno.

+1

Różnica w wydajności? To prawdopodobnie zależy od tego, jak duże są twoje pliki CSV i jak z nimi pracujesz. Możesz samodzielnie odpowiedzieć na to pytanie, porównując sposób wykorzystania rzeczy w swojej sytuacji. –

+0

Witaj @muistooshort, dzięki za odpowiedź. Dostałem twoją odpowiedź, a ja po prostu zmierzę, jak szybkie jest przetwarzanie i jak zajęta jest moja pamięć i procesor w trakcie procesu. Ogólnie rzecz biorąc, zazwyczaj bardzo duże pliki powinny być przetwarzane rząd po rzędzie, a jeśli plik jest wystarczająco lekki, można go załadować do pamięci, prawda? – benams

+1

Zazwyczaj przypuszczam. To zależy od tego, jaki styl ma sens w tym, co robisz. –

Odpowiedz

5

Oto moja próba:

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) 

Benchmarki przeprowadzono na Macbook Pro z pamięcią 8GB. Wyniki wskazują, że wydajność jest statystycznie równoważna za pomocą analizy pliku CSV lub narzędzia CSV # foreach.

opcje Nagłówki usunięte (testowane tylko mały plik):

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) 

Uwagi:

large_csv_file miała inną strukturę niż small_csv_file i dlatego wyniki porównujące (czyli wierszy/s) pomiędzy dwoma plikami byłoby być niedokładne.

small_csv_file miał 50000 zapisy

large_csv_file miał 1,000,000 zapisy

Główki opcji wartość prawda zmniejsza wydajność znacznie dzięki budowie mieszania dla każdego pola w wierszu (patrz rozdział HeadersConverters: http://www.ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html)

+0

Wątpię, aby pytanie dotyczyło zarówno użycia procesora, jak i czasu, ponieważ jest to użycie pamięci. Jeśli wykonujesz czynność dla każdego wiersza, to tylko wiersz w pamięci jest konserwatywny. Jeśli otrzymujesz tablicę tablic, użycie pamięci powinno być takie samo. –