2013-10-03 3 views
5

Я не уверен, что этот вопрос связан только с рубином, возможно, вы найдете его соответствующим любому другому языку.Производительность: ruby ​​CSV.foreach vs CSV.parse

Интересно, если я должен использовать парсер или Еогеасп:

  • CSV.parse(filepath) будет разбирать весь файл и возвращает массив массивов, который будет отражать файл CSV и будет храниться в памяти. Позже я обработаю эти строки массива.

  • CSV.foreach(filepath) будет читать/разбирать файл по строкам и обрабатывать его по строкам.

Когда дело доходит до исполнения, есть ли разница? есть ли предпочтительный подход?

PS: Я знаю, что в рубине я могу предоставить блок с помощью метода синтаксического анализа, а затем он будет обрабатывать каждую строку отдельно.

+1

Разница в производительности? Вероятно, это зависит от того, насколько велики ваши файлы CSV и как вы работаете с ними. Вы можете легко ответить на этот вопрос, сравнив, как вы будете использовать вещи в своей ситуации. –

+0

Здравствуйте, @muistooshort, спасибо за ваш ответ. Я получил ваш ответ, и я просто буду оценивать, насколько быстро происходит синтаксический анализ и насколько занята моя память и процессор во время процесса. В общем, обычно очень большие файлы должны обрабатываться по строкам, и если файл достаточно светлый, его можно загрузить в память, верно? – benams

+1

Обычно я полагаю. Это зависит от того, какой стиль имеет смысл для того, что вы делаете. –

ответ

5

Вот мой тест:

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) 

Тесты проводились на Macbook Pro с 8 Гб памяти. Результаты показывают, что производительность статистически эквивалентна, используя либо CSV # parse, либо CSV # foreach.

опции Заголовки удалены (только небольшой файл тестировался):

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) 

Примечания:

large_csv_file был иной структурой, чем small_csv_file и поэтому сравнение результатов (т.е. строк/сек) между двумя файлами будет быть неточным.

small_csv_file имел 50000 записей

large_csv_file имел 1000000 записей

Заголовки параметр установлен верно снижает производительность значительно за счет построения хэш для каждого поля в строке (смотрите раздел HeadersConverters: http://www.ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html)

+0

Я сомневаюсь, что вопрос касается использования процессора и времени, поскольку это использование памяти. Если вы выполняете действие в каждой строке, то только наличие строки в памяти является консервативным. Если вы получаете массив массивов, то использование памяти должно быть одинаковым. –

Смежные вопросы