カスタムオブジェクト-> XMLシリアル化ユーティリティを最適化していますが、すべて完了し、機能しています。それは問題ではありません。
ファイルをXmlDocument
オブジェクトにロードし、すべての子ノードを再帰的に通過することで機能しました。
おそらくXmlReader
の代わりにXmlDocument
を使用して全体をロード/解析する方が高速になると考えたので、そのバージョンも実装しました。
アルゴリズムはまったく同じです。ラッパークラスを使用して、XmlNode
とXmlReader
を処理する機能を抽象化します。たとえば、GetChildren
メソッドのyieldは、子XmlNode
またはSubTree XmlReader
を返します。
そこで、両方のバージョンをテストするテストドライバーを作成し、重要なデータセット(約1,350の要素を持つ900kbのXMLファイル)を使用しました。
ただし、JetBrains dotTRACEを使用すると、XmlReader
バージョンは実際にXmlDocument
バージョンよりも遅いことがわかります。子ノードを反復処理しているときに、XmlReader
読み取り呼び出しに関与する重要な処理があるようです。
だから私はこれを尋ねるためにすべてを言う:
XmlDocument
とXmlReader
の長所/短所は何ですか。どのような状況でどちらを使用すべきですか?
私の推測では、XmlReader
のパフォーマンスが経済的になるだけでなく、メモリの使用量が少なくなるファイルサイズのしきい値があります。ただし、そのしきい値は1 MBを超えているようです。
子ノードを処理するたびにReadSubTree
を呼び出しています:
public override IEnumerable<IXmlSourceProvider> GetChildren ()
{
XmlReader xr = myXmlSource.ReadSubtree ();
// skip past the current element
xr.Read ();
while (xr.Read ())
{
if (xr.NodeType != XmlNodeType.Element) continue;
yield return new XmlReaderXmlSourceProvider (xr);
}
}
このテストは、単一のレベル(つまり、幅の広いものと浅いもの)の多くのオブジェクトに適用されますが、XMLが深さと幅があるときにXmlReader
の運賃はどれだけうまくいくのでしょうか?つまり私が扱っているXMLは、データオブジェクトモデル、多くの子オブジェクトに対する1つの親オブジェクトなどによく似ています:1..M..M..M
また、解析しているXMLの構造も事前にわからないため、最適化できません。
私は一般的にそれを最速の観点ではなく、メモリ使用率パースペクティブ。すべての実装は、私がそれらを使用した使用シナリオ(通常のエンタープライズ統合)に十分に高速です。
しかし、私が倒れたとき、そして時には壮大に、私が作業しているXMLの一般的なサイズを考慮していません。あなたがそれについて前もって考えれば、あなた自身にいくらかの悲しみを救うことができます。
少なくともXmlDocument
やXPathDocument
などのDOMリーダーでは、XMLはメモリにロードされると膨張する傾向があります。 10:1のようなものですか?正確な量を定量化することは困難ですが、ディスク上で1MBの場合、たとえばメモリ内で10MB以上になります。
ドキュメント全体をメモリ全体にロードするリーダー(XmlDocument
/XPathDocument
)を使用するプロセスは、大きなオブジェクトヒープの断片化の影響を受け、最終的にOutOfMemoryException
s(使用可能なメモリがある場合でも)、使用できないサービス/プロセスになります。
サイズが85Kを超えるオブジェクトは大きなオブジェクトヒープに置かれ、DOMリーダーで10:1のサイズの爆発が発生するため、XMLドキュメントが割り当てられるまでにそれほど時間がかからないことがわかります。ラージオブジェクトヒープ。
XmlDocument
は非常に使いやすいです。唯一の欠点は、XMLドキュメント全体をメモリにロードして処理することです。魅惑的に簡単に使用できます。
XmlReader
はストリームベースのリーダーであるため、プロセスのメモリ使用率は一般的にフラットに保たれますが、使用するのはより困難です。
XPathDocument
は、より高速で読み取り専用のXmlDocumentのバージョンになる傾向がありますが、それでもメモリの「膨張」に悩まされます。
XmlDocumentは、XMLドキュメント全体のメモリ内表現です。したがって、ドキュメントが大きい場合、XmlReaderを使用して読み取った場合よりも多くのメモリを消費します。
これは、XmlReaderを使用する場合、要素を1つずつ読み取り、処理してから破棄することを前提としています。 XmlReaderを使用し、メモリ内に別の中間構造を構築すると、同じ問題が発生し、その目的に反することになります。
Googleが「 SAX vs DOM 」の場合、XML処理の2つのモデルの違いについて詳しく読むことができます。
もう1つの考慮事項は、XMLReaderが完全に形成されていないXMLを処理するためにより堅牢である可能性があることです。最近、XMLストリームを使用するクライアントを作成しましたが、一部の要素に含まれるURIで特殊文字が正しくエスケープされていないストリームがありました。 XMLDocumentとXPathDocumentはXMLのロードをまったく拒否しましたが、XMLReaderを使用すると、必要な情報をストリームから抽出できました。
エンコードの違いは、2つの異なる測定値が混在しているためです。 UTF-32は文字ごとに4バイトを必要とし、本質的にシングルバイトデータよりも低速です。
大きい(100K)要素のテストを見ると、使用されているロード方法に関係なく、各ケースで時間が約70ms増加することがわかります。
これは、文字ごとのオーバーヘッドが原因で生じる(ほぼ)一定の差です。
XmlDocumentが遅くなり、最終的に使用できなくなるサイズのしきい値があります。ただし、しきい値の実際の値はアプリケーションとXMLコンテンツに依存するため、厳格なルールはありません。
XMLファイルに大きなリスト(数万の要素など)を含めることができる場合は、間違いなくXmlReaderを使用する必要があります。