前回は一般的なXMLの読み込み方法をまとめましたが、通常はXMLソースの全データを使う必要はないので、タイトルの頭文字でフィルタリングするなど、一部のデータを読み込んでみる実験をしてみました。そして発生位置。
3つのランダム読み取り方法では、クエリ条件を変更するだけです
XmlDocument: var nodeList = doc.DocumentElement.SelectNodes("item[substring(title,1,1)='M'][position() mod 10 = 0]"); XPathNavigator: var nodeList = nav.Select("/channel/item[substring(title,1,1)='M'][position() mod 10 = 0]"); Xml Linq: var nodelist = from node in xd.XPathSelectElements("/channel/item[substring(title,1,1)='M'][position() mod 10 = 0]")
XPathを使用すると、コードを1行変更するだけで済みます。 XPath は習得するのがかなり簡単で、SQL よりもはるかに単純です。 XPath ユーザー向けに W3C Shcool の構文紹介と MSDN の LINQ To XML を参照すれば、15 分でその秘密をマスターできるでしょう。
しかし、XmlReaderメソッドの場合は、Mで始まるタイトルを読み取ったり、10項目ごとに1項目を取得したりするので、長い間考えましたが、エレガントな実装方法が思いつきませんでした。 , そこで私はこれを行う必要がありました:
Code
static List<Channel> testXmlReader2() { var lstChannel = new List<Channel>(); var reader = XmlReader.Create(xmlStream); int n = 0;Channel channel = null; Search: while (reader.Read()) { if (reader.Name == "item" && reader.NodeType == XmlNodeType.Element) { while (reader.Read()) { if (reader.Name == "item") break; if (reader.NodeType != XmlNodeType.Element) continue; switch (reader.Name) { case "title": var title = reader.ReadString(); if (title[0] != 'M') goto Search; n++; if (n % 10 != 0) goto Search; channel = new Channel(); channel.Title = title; break; case "link": channel.Link = reader.ReadString(); break; case "description": channel.Description = reader.ReadString(); break; case "content": channel.Content = reader.ReadString(); break; case "pubDate": channel.PubDate = reader.ReadString(); break; case "author": channel.Author = reader.ReadString(); break; case "category": channel.Category = reader.ReadString(); break; default: break; } lstChannel.Add(channel); } } } return lstChannel; }
コード構造が大幅に変更されていることがわかります。条件付きスクリーニングを実行するには、ローカル変数 n を追加し、エンティティ クラスの初期化を調整し、コレクション ステートメントの場所を追加する必要があり、長年忘れていた goto ステートメントを使用してジャンプする必要もありました。 (VB の方が優れています)。 Lao Zhao 氏の言葉を借りれば、ビジネス ロジックはコードの実装にまで浸透しており、文法上のノイズが顔に突き当たります。
XmlTextReaderの実装プロキシクラスであるXmlTextReaderImp(内部、直接使用不可)は、数万行のコードを持つスーパークラスで、Xml文字レベルで直接実行される多数の操作をカプセル化しています。この操作は最下層に非常に近いため、マクロ レベルで適切なコード最適化方法を見つけるのは困難です。フィルタリング条件、つまりビジネスロジックが複雑になれば、コードも全く異なり、わかりやすさと保守性は鏡のように変わります。
次に、時間のパフォーマンスを比較してみましょう:
XmlDocment 26ms XPathNavigator 26ms XmlTextReader 20ms Xml Linq 28ms
Document メソッドと Navigator メソッドの消費時間は大幅に短縮されましたが、Reader メソッドはまだ最初から読み取る必要があるため、大幅に短縮されていません。 3 ミリ秒の削減は、エンティティ オブジェクト作成のオーバーヘッドと考えることができます。さらに奇妙なのは、Linq メソッドが変更されずに最後に落ちたことです。
さまざまなクエリ条件をテストできます。これらの 4 つのメソッドにはそれぞれ、Xml ソースのサイズに関連する独自のパフォーマンス制限があることがわかります。たとえば、最初の 2 つのメソッドでは、XmlDocument.Load メソッドの実行時間に依存します。私のマシンでは、Xml のロードに 23 ミリ秒かかります。 Linq メソッドは壊れないわけではありません。処理する結果が少ない場合、実行時間は 1 ~ 2 ミリ秒短縮されます。
ドキュメントメソッドとナビゲーターメソッドは、データ量が増えるとパフォーマンスが大幅に低下します。無駄なオブジェクトを大量に作成するためであることは容易に推測できます。各メソッドのメモリ使用量を見ると、すべてのデータをフィルタリングせずにロードした場合、Document メソッドは約 23.3M のメモリを使用するのに対し、Navigator メソッドは約 22.9M しか使用しないことがわかります。これは、パフォーマンスが低下する理由も説明します。 Document メソッドの減少はより顕著です。リーダー モードではデータが完全に読み込まれ、プログラムの起動自体のオーバーヘッドを除くと、必要なメモリは約 20.1M だけであり、前の 2 つの方法と比較して使用するメモリの量は半分未満です。 Linq 方式は、メモリの点でも驚くべきパフォーマンスを備えており、Reader 方式よりも 500k 未満多くなっています。
さらなる分析により、特別な必要がない限り、XmlTextReader は注意して使用する必要があるという結論が得られました。XmlTextReader は変更に対する準備が不十分であり、エラーが発生しやすいです。 Linq 方式を使用することを強くお勧めします。場合によっては、Navigator 方式よりも時間パフォーマンスが若干劣りますが、メモリ使用量のパフォーマンスが優れているため、第一の選択肢として確立されています。そして、Linq To XML は将来さらに強力になると信じています。
上記は XML データ読み取り方法のパフォーマンス比較 (2) です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。