【问题标题】:performance: ruby CSV.foreach vs CSV.parse性能:红宝石 CSV.foreach 与 CSV.parse
【发布时间】:2013-10-03 00:02:41
【问题描述】:

我不确定这个问题是否仅与 ruby​​ 相关,也许您会发现它与任何其他语言相关。

我想知道我应该使用 parse 还是 foreach:

  • CSV.parse(filepath) 将解析整个文件并返回一个数组数组,该数组将反映 csv 文件并将存储在内存中。稍后,我将处理这个数组行。

  • CSV.foreach(filepath) 将逐行读取/解析文件并逐行处理。

在性能方面,有什么不同吗?有更好的方法吗?

PS:我知道在 ruby​​ 中我可以提供一个带有 parse 方法的块,然后它将分别处理每一行。

【问题讨论】:

  • 性能差异?这可能取决于您的 CSV 文件有多大以及您如何使用它们。您可以通过基准测试在您的情况下如何使用事物,自己很容易地回答这个问题。
  • 您好@muistooshort,感谢您的回复。我得到了你的答案,我将简单地衡量解析的速度以及在此过程中我的内存和 CPU 的繁忙程度。一般来说,通常非常大的文件应该逐行处理,如果文件足够轻,可以加载到内存中,对吧?
  • 通常我想。这取决于哪种风格对您正在做的事情有意义。

标签: ruby performance file csv


【解决方案1】:

这是我的测试:

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)

基准测试在配备 8GB 内存的 Macbook Pro 上运行。结果表明使用 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 有 50,000 条记录

large_csv_file 有 1,000,000 条记录

Headers 选项设置为 true 会显着降低性能,因为会为行中的每个字段构建哈希(请参阅 HeadersConverters 部分:http://www.ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html

【讨论】:

  • 我怀疑这个问题与内存使用一样多的是 CPU 使用率和时间。如果您对每一行执行一个操作,那么只有该行在内存中是保守的。如果你得到一个数组数组,那么内存使用应该是一样的。
猜你喜欢
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
相关资源
最近更新 更多