2012-03-16 11 views
2

巨大なXMLファイルを構築する必要があります。約1〜50MBです。私はビルダーを使うことが十分に効果的だと思っていましたが、それは多少です。問題は、プログラムが最後の行に到達した後すぐに終了するのではなく、Rubyはまだ数秒間何かをやっていますか?おそらくガベージコレクションですか?その後、プログラムは最終的に終了します。巨大なXMLのNokogiriビルダーのパフォーマンス?

実際の例を挙げると、私は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秒間のオーバーヘッドが発生するのを避けるためにできることはありますか?それも可能ですか?

UPDATE:私の最小限の実施例の作成中にAdiel Mittmannからの提案へ

おかげで、私は問題を見つけることができました。私は今問題を実証している小さな(うまくはない)例を持っています。

次のコードは、問題を引き起こしている:

xml.send("#{elem_name}_") do |elem_xml| 
    ... 
    elem_xml.text text_content #This line is the problem 
    ... 
end 

だからラインは鋸山のマニュアルに基づいて、次のコードを実行:

def create_text_node string, &block 
    Nokogiri::XML::Text.new string.to_s, self, &block 
end 

Text node creation codeは、その後、実行されます。では、ここで何が起こっているのですか?

UPDATE 2:他のいくつかの試行後

、問題を簡単に再生することができる。

builder = Nokogiri::XML::Builder.new do |xml| 
    0.upto(81900) do 
    xml.text "test" 
    end 
end 
puts "End" 

だから、本当に鋸山そのものですか?私のためのオプションはありますか?

+0

ちょうど参考:多くのSOユーザーは、一般的なユーザー名を持つ新しいアカウントによって投稿された質問には注意が必要です。それに関連して高い放棄率があります。 –

+0

情報をありがとう、正直言って、私は気付かなかった、私は生成されたユーザー名を使用していた=>今変更されました。私はこのウェブサイトを初めて利用していますが、私がそのウェブサイトの積極的な役割を果たすことができることを願っています。 – Giron

+0

1つのXMLファイルを読み込んで別のXMLファイルに変換していますか? –

答えて

3

あなたの例もここで実行するのに時間がかかります。そしてあなたは正しいのです。それは実行に時間がかかりすぎるガベージコレクタです。これを試してみてください:

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ファイルを使って何をしようとしているのかを詳細に質問することをお勧めします。

+0

あなたの答えをありがとう、私は十分な評判を持っているなら、私は喜んでその答えを投票します。私は問題が何であるかを正確に突き止めることを目指していたので、これは受け入れられた答えです。あなたの時間をもう一度ありがとう。 – Giron

+0

喜んで助けてください。ところで、質問や回答を投票することがわかっている限り、あなたの評判ポイントに悪影響はありません。実際には、それは時々あなたにバッジを得るでしょう:) –

+0

唯一のdownvotesは評判を犠牲にします。アップホールドは無料で、実際にはコミュニティ全体が素晴らしい投稿を検出するのに役立ちます。 –

0

Ruby組み込みビルダーを使用してみてください。私はそれを使って大きなXMLファイルも生成しますが、そのような小さなフットプリントはありません。

+0

こんにちは、あなたの反応をありがとう、ビルダーは、大規模なXMLで使用されると非常に速いようですが、それは良い提案ですが、私はノコギリが必要だと書いて以来、質問の半分に答えます。とにかくありがとう、スピードはノコギリよりも何倍も速く、多分私は最後にそれを使わなければならないでしょう。 – Giron

関連する問題