Gau*_*hah 13 ruby xml builder nokogiri
我想将一些数据写入XML文件(XML文件将达到~50 MB).
我找到了nokogiri(1.5.0)宝石 最多高效解析(只读和不写).Nokogiri不是写入XML文件的好选择,因为它在内存中保存完整的XML数据,直到写入最终将其写下来.
我发现builder(3.0.0)是一个不错的选择,但不确定它是否是最好的选择.
我用以下简单的代码尝试了一些基准测试:
(1..500000).each do |k|
xml.products {
xml.widget {
xml.id_ k
xml.name "Awesome widget"
}
}
end
Run Code Online (Sandbox Code Playgroud)
Nokogiri大约需要143秒,内存消耗也逐渐增加,最终达到700 MB左右.
Builder大约需要123秒,内存消耗足够稳定在10 MB.
那么在Ruby中编写大量XML文件(50 MB)有更好的解决方案吗?
Nokogiri文件:
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
Run Code Online (Sandbox Code Playgroud)
生成器文件:
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
Run Code Online (Sandbox Code Playgroud)
sun*_*ity 16
解决方案1
如果速度是你主要考虑的问题,我会直接使用libxml-ruby(http://libxml.rubyforge.org/rdoc/):
$ time ruby test.rb
real 0m7.352s
user 0m5.867s
sys 0m0.921s
Run Code Online (Sandbox Code Playgroud)
api很直接
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)
Run Code Online (Sandbox Code Playgroud)
using:indent => true在这种情况下没有太大区别,但对于更复杂的xml文件,它可能会做.
$ time ruby test.rb#(带缩进)
$ time ruby test.rb #(with indent)
real 0m7.395s
user 0m6.050s
sys 0m0.847s
Run Code Online (Sandbox Code Playgroud)
解决方案2
当然,最快的解决方案,并没有在内存上构建只是手动编写xml,但很容易生成其他错误源,如可能无效的xml.
$ time ruby test.rb
real 0m1.131s
user 0m0.873s
sys 0m0.126s
Run Code Online (Sandbox Code Playgroud)
这是代码:
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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5237 次 |
最近记录: |