2013-10-03 16 views
5

Tôi không chắc chắn câu hỏi này có liên quan đến ruby ​​chỉ, có thể bạn sẽ thấy nó có liên quan đến bất kỳ ngôn ngữ nào khác.hiệu suất: ruby ​​CSV.foreach vs CSV.parse

Tôi tự hỏi nếu tôi nên sử dụng phân tích cú pháp hoặc foreach:

  • CSV.parse(filepath) sẽ phân tích toàn bộ hồ sơ và trả về một mảng của mảng, mà sẽ phản ánh file csv và sẽ được lưu trữ trong bộ nhớ. Sau đó, tôi sẽ xử lý các hàng mảng này.

  • CSV.foreach(filepath) sẽ đọc/phân tích tệp theo từng hàng và xử lý hàng từng hàng.

Khi nói đến hiệu suất, có sự khác biệt nào không? có cách tiếp cận nào thích hợp hơn không?

PS: Tôi biết rằng trong ruby ​​tôi có thể cung cấp một khối với phương pháp phân tích cú pháp và sau đó nó sẽ xử lý từng hàng riêng biệt.

+1

Hiệu suất khác biệt? Điều đó có thể phụ thuộc vào độ lớn của tệp CSV và cách bạn đang làm việc với chúng. Bạn có thể tự mình trả lời câu hỏi đó một cách dễ dàng bằng cách đo điểm chuẩn cách bạn sẽ sử dụng mọi thứ trong hoàn cảnh của mình. –

+0

Xin chào @muistooshort, cảm ơn bạn đã trả lời. Tôi đã nhận được câu trả lời của bạn, và tôi sẽ chỉ đơn giản là đo nhanh như thế nào là phân tích cú pháp và bận rộn như thế nào là bộ nhớ của tôi và CPU trong quá trình này. Nói chung, các tệp thường rất lớn nên được xử lý từng hàng và nếu tệp đủ nhẹ, nó có thể được tải vào bộ nhớ, phải không? – benams

+1

Thông thường tôi giả sử. Nó phụ thuộc vào phong cách nào có ý nghĩa đối với những gì bạn đang làm. –

Trả lời

5

Dưới đây là thử nghiệm của tôi:

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) 

Các tiêu chuẩn được chạy trên một Macbook Pro với bộ nhớ 8GB. Kết quả cho thấy hiệu suất là tương đương về mặt thống kê bằng cách sử dụng CSV # parse hoặc CSV # foreach.

tùy chọn Headers gỡ bỏ (chỉ tập tin nhỏ được kiểm tra):

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) 

Ghi chú:

large_csv_file là của một cấu trúc khác với small_csv_file và do đó kết quả so sánh (tức hàng/giây) giữa hai tập tin sẽ không chính xác.

small_csv_file có 50.000 hồ sơ

large_csv_file có 1.000.000 hồ sơ

Headers tùy chọn thiết lập là true giảm hiệu suất đáng kể do việc xây dựng một băm cho từng lĩnh vực ở hàng (xem HeadersConverters phần: http://www.ruby-doc.org/stdlib-2.0.0/libdoc/csv/rdoc/CSV.html)

+0

Tôi nghi ngờ câu hỏi là càng nhiều về việc sử dụng CPU và thời gian vì nó là sử dụng bộ nhớ. Nếu bạn đang thực hiện một hành động trên mỗi hàng, thì chỉ có hàng trong bộ nhớ là bảo thủ. Nếu bạn đang nhận mảng mảng, thì mức sử dụng bộ nhớ sẽ giống nhau. –