2011-09-19 24 views
12

Tôi muốn ghi một số dữ liệu vào tệp XML (tệp XML sẽ đến ~ 50 MB).tạo xml tệp lớn trong ruby ​​

Tôi đã tìm thấy nokogiri (1.5.0) đá quý là nhất hiệu quả để phân tích cú pháp (Chỉ đọc và không viết). Nokogiri không phải là một lựa chọn tốt để ghi vào tập tin XML vì nó chứa dữ liệu XML hoàn chỉnh trong bộ nhớ cho đến khi nó ghi cuối cùng ghi lại nó.

Tôi đã tìm thấy người xây dựng (3.0.0) là một lựa chọn tốt nhưng không chắc chắn nếu đó là tùy chọn tốt nhất.

Tôi đã thử một số benchmark với mã đơn giản sau đây:

(1..500000).each do |k| 
    xml.products { 
     xml.widget { 
     xml.id_ k 
     xml.name "Awesome widget" 
     } 
    } 
    end 

Nokogiri mất khoảng 143 giây và cũng tiêu thụ bộ nhớ tăng dần và kết thúc cuối cùng vào khoảng 700 MB.

Trình tạo mất khoảng 123 giây và mức tiêu thụ bộ nhớ đủ ổn định ở mức 10 MB.

Vì vậy, có giải pháp nào tốt hơn để viết các tệp XML khổng lồ (50 MB) trong Ruby không?

Nokogiri file:

require 'rubygems' 
require 'nokogiri' 
a = Time.now 
builder = Nokogiri::XML::Builder.new do |xml| 
    xml.root { 
    (1..500000).each do |k| 
    xml.products { 
     xml.widget { 
     xml.id_ k 
     xml.name "Awesome widget" 
     } 
    } 
    end 
    } 
end 
o = File.new("test_noko.xml", "w") 
o.write(builder.to_xml) 
o.close 
puts (Time.now-a).to_s 

Builder file:

require 'rubygems' 
require 'builder' 
a = Time.now 
File.open("test.xml", 'w') {|f| 
xml = Builder::XmlMarkup.new(:target => f, :indent => 1) 

    (1..500000).each do |k| 
    xml.products { 
     xml.widget { 
     xml.id_ k 
     xml.name "Awesome widget" 
     } 
    } 
    end 

} 
puts (Time.now-a).to_s 
+0

Re Parsing: Nokogiri là khá thân thiện với người, nhưng khi tốc độ là chìa khóa, tôi đi với giá chỉ viết một phân tích cú pháp SAX (có sẵn trong nogokiri cũng) . Tôi có một lớp tiện ích tiện dụng mà tôi sử dụng để nhanh chóng xây dựng một mảng các công cụ mà tôi cần từ một xml (miễn là xml là khá đơn giản) https://gist.github.com/854726 nếu khác tôi có thể phải viết một saxparser tùy chỉnh. – sunkencity

+0

Bạn đã lấy nó theo cách khác .. Tôi muốn xây dựng xml từ mảng (bản ghi hoạt động). –

+0

Đó là một nhận xét về "Tôi tìm thấy nokogiri (1.5.0) đá quý là hiệu quả nhất để phân tích cú pháp", quan điểm của tôi là cách hiệu quả nhất để phân tích cú pháp là sử dụng trực tiếp saxparser api. – sunkencity

Trả lời

15

Giải pháp 1

Nếu tốc độ là mối quan tâm chính của bạn, tôi muốn chỉ cần sử dụng libxml-ruby (http://libxml.rubyforge.org/rdoc/) trực tiếp:

$ time ruby test.rb 

real 0m7.352s 
user 0m5.867s 
sys  0m0.921s 

Các api là khá thẳng về phía trước

require 'rubygems' 
require 'xml' 
doc = XML::Document.new() 
doc.root = XML::Node.new('root_node') 
root = doc.root 

500000.times do |k| 
    root << elem1 = XML::Node.new('products') 
    elem1 << elem2 = XML::Node.new('widget') 
    elem2['id'] = k.to_s 
    elem2['name'] = 'Awesome widget' 
end 

doc.save('foo.xml', :indent => false, :encoding => XML::Encoding::UTF_8) 

sử dụng: indent => đúng không làm được gì nhiều khác biệt trong trường hợp này, nhưng đối với file xml phức tạp hơn nó có thể làm.

$ thời gian ruby ​​test.rb # (với thụt lề)

real 0m7.395s 
user 0m6.050s 
sys  0m0.847s 

Giải pháp 2

Tất nhiên là giải pháp nhanh nhất, và điều đó không xây dựng trên bộ nhớ là chỉ để viết xml theo cách thủ công nhưng điều đó sẽ dễ dàng tạo ra các nguồn lỗi khác như xml không hợp lệ.

$ time ruby test.rb 

real 0m1.131s 
user 0m0.873s 
sys  0m0.126s 

đây là mã cho rằng:

f = File.open("foo.xml", "w") 
f.puts('<doc>') 
500000.times do |k| 
    f.puts "<product><widget id=\"#{k}\" name=\"Awesome widget\" /></product>" 
end 
f.puts('</doc>') 
f.close 
+0

nhưng với bộ nhớ này lên đến 600 mb .. đó là cách quá sai phải không? –

+0

Tôi thêm một cách để làm điều đó mà không cần ăn bộ nhớ, nó nhanh hơn, nhưng bạn không nhận được bất kỳ lợi ích của việc sử dụng một máy phát điện xml như thụt đầu dòng tự động, và kiểm tra tính hợp lệ, vv – sunkencity

+0

trong trường hợp giải pháp 2, tại sao không sử dụng builder? , nó sẽ cung cấp xác nhận và cũng an toàn hơn, phải không? –

Các vấn đề liên quan