Nokogiri构建器在巨大的XML上表现?
我需要构建一个大约1-50 MB的巨大XML文件。 我认为使用构建器会足够有效,而且有点。 问题是,在程序到达最后一行后它不会立即结束,但Ruby仍在做几秒钟的事情,可能是垃圾收集? 之后程序终于结束了。
举一个真实的例子,我测量了构建XML文件的时间。 在构建XML时,它输出55秒(后面有一个数据库,所以需要很长时间),但是Ruby仍然会处理大约15秒钟,处理器就会变得疯狂。
伪/实际代码如下:
... builder = Nokogiri::XML::Builder.with(doc) do |xml| build_node(xml) end ... def build_node(xml) ... xml["#{namespace}"] if namespace xml.send("#{elem_name}", attrs_hash) do |elem_xml| ... if has_children if type case type when XML::TextContent::PLAIN elem_xml.text text_content when XML::TextContent::COMMENT elem_xml.comment text_content when XML::TextContent::CDATA elem_xml.cdata text_content end else build_node(elem_xml) end end end end
请注意,我使用自己的类结构使用不同的方法,并且构建的速度是相同的,但在最后一行程序通常结束,但现在我被迫使用Nokogiri所以我必须找到一个解决方案。
在构建XML之后,我可以做些什么来避免X秒长的开销? 它甚至可能吗?
更新:
感谢Adiel Mittmann的建议,在创建我的最小工作示例期间,我能够找到问题所在。 我现在有一个小的(好不是那么小)的例子来certificate这个问题。
以下代码导致问题:
xml.send("#{elem_name}_") do |elem_xml| ... elem_xml.text text_content #This line is the problem ... end
因此该行根据Nokogiri的文档执行以下代码:
def create_text_node string, &block Nokogiri::XML::Text.new string.to_s, self, &block end
然后执行文本节点创建代码 。 那么,到底发生了什么?
更新2:
经过其他一些尝试后,问题可以通过以下方式轻松复制:
builder = Nokogiri::XML::Builder.new do |xml| 0.upto(81900) do xml.text "test" end end puts "End"
真的是Nokogiri本身吗? 我有什么选择吗?
您的示例在此处执行也需要很长时间。 而你是对的:垃圾收集器需要很长时间才能执行。 试试这个:
require 'nokogiri' class A def a builder = Nokogiri::XML::Builder.new do |xml| 0.upto(81900) do xml.text "test" end end end end A.new.a puts "End1" GC.start puts "End2"
这里,延迟发生在"End1"
和"End2"
。 打印"End2"
后,程序立即关闭。
请注意,我创建了一个对象来演示它。 否则,构建器生成的数据只能在程序完成时进行垃圾回收。
至于做你想要完成的事情的最佳方式,我建议你问另一个问题,详细说明你正在尝试用XML文件做些什么。
尝试使用Ruby内置(sic)Builder。 我也用它来生成大型XML文件,而且它的占用空间很小。