XPathNavigatorを使用してノードを反復処理しているアプリケーションがあります。正常に動作しています。
しかし、LINQtoXmlを使用する場合は...
どのようなメリット(パフォーマンス、保守性)が得られますか?
XPath、LINQ to Xmlを使用すると、パフォーマンスにどのような影響がありますか?
私はC#.net、VS 2010を使用していますが、.xmlは中規模です。
XPathNavigatorを使用してノードを反復処理しているアプリケーションがあります。正常に動作しています。
しかし、LINQtoXmlを使用する場合は...
どのようなメリット(パフォーマンス、保守性)が得られますか?
XPath、LINQ to Xmlを使用すると、パフォーマンスにどのような影響がありますか?
私はC#.net、VS 2010を使用していますが、.xmlは中規模です。
ここですでに述べたことに加えて、全体的なパフォーマンスは、問題のドキュメントで実際に何をしているかに依存するようです。これは、XElement と XPathNavigator の間の解析パフォーマンスを比較する簡単な実験の実行に基づいて、私が結論付けたものです。
ノードを選択している場合、これらのノードをトラバースし、いくつかの属性値を読み取ります。
一方、各ノードの子の値も読み取っている場合は、少し興味深いものになります。
これらの結論は、次のコードに基づいています。
[Test]
public void CompareXPathNavigatorToXPathSelectElement()
{
var max = 100000;
Stopwatch watch = new Stopwatch();
watch.Start();
bool parseChildNodeValues = true;
ParseUsingXPathNavigatorSelect(max, watch, parseChildNodeValues);
ParseUsingXElementElements(watch, max, parseChildNodeValues);
ParseUsingXElementXPathSelect(watch, max, parseChildNodeValues);
ParseUsingXPathNavigatorFromXElement(watch, max, parseChildNodeValues);
}
private static void ParseUsingXPathNavigatorSelect(int max, Stopwatch watch, bool parseChildNodeValues)
{
var document = new XPathDocument(@"data\books.xml");
var navigator = document.CreateNavigator();
for (var i = 0; i < max; i++)
{
var books = navigator.Select("/catalog/book");
while (books.MoveNext())
{
var location = books.Current;
var book = new Book();
book.Id = location.GetAttribute("id", "");
if (!parseChildNodeValues) continue;
book.Title = location.SelectSingleNode("title").Value;
book.Genre = location.SelectSingleNode("genre").Value;
book.Price = location.SelectSingleNode("price").Value;
book.PublishDate = location.SelectSingleNode("publish_date").Value;
book.Author = location.SelectSingleNode("author").Value;
}
}
watch.Stop();
Console.WriteLine("Time using XPathNavigator.Select = " + watch.ElapsedMilliseconds);
}
private static void ParseUsingXElementElements(Stopwatch watch, int max, bool parseChildNodeValues)
{
watch.Restart();
var element = XElement.Load(@"data\books.xml");
for (var i = 0; i < max; i++)
{
var books = element.Elements("book");
foreach (var xElement in books)
{
var book = new Book();
book.Id = xElement.Attribute("id").Value;
if (!parseChildNodeValues) continue;
book.Title = xElement.Element("title").Value;
book.Genre = xElement.Element("genre").Value;
book.Price = xElement.Element("price").Value;
book.PublishDate = xElement.Element("publish_date").Value;
book.Author = xElement.Element("author").Value;
}
}
watch.Stop();
Console.WriteLine("Time using XElement.Elements = " + watch.ElapsedMilliseconds);
}
private static void ParseUsingXElementXPathSelect(Stopwatch watch, int max, bool parseChildNodeValues)
{
XElement element;
watch.Restart();
element = XElement.Load(@"data\books.xml");
for (var i = 0; i < max; i++)
{
var books = element.XPathSelectElements("book");
foreach (var xElement in books)
{
var book = new Book();
book.Id = xElement.Attribute("id").Value;
if (!parseChildNodeValues) continue;
book.Title = xElement.Element("title").Value;
book.Genre = xElement.Element("genre").Value;
book.Price = xElement.Element("price").Value;
book.PublishDate = xElement.Element("publish_date").Value;
book.Author = xElement.Element("author").Value;
}
}
watch.Stop();
Console.WriteLine("Time using XElement.XpathSelectElement = " + watch.ElapsedMilliseconds);
}
private static void ParseUsingXPathNavigatorFromXElement(Stopwatch watch, int max, bool parseChildNodeValues)
{
XElement element;
watch.Restart();
element = XElement.Load(@"data\books.xml");
for (var i = 0; i < max; i++)
{
// now we can use an XPath expression
var books = element.CreateNavigator().Select("book");
while (books.MoveNext())
{
var location = books.Current;
var book = new Book();
book.Id = location.GetAttribute("id", "");
if (!parseChildNodeValues) continue;
book.Title = location.SelectSingleNode("title").Value;
book.Genre = location.SelectSingleNode("genre").Value;
book.Price = location.SelectSingleNode("price").Value;
book.PublishDate = location.SelectSingleNode("publish_date").Value;
book.Author = location.SelectSingleNode("author").Value;
}
}
watch.Stop();
Console.WriteLine("Time using XElement.Createnavigator.Select = " + watch.ElapsedMilliseconds);
}
ここからbooks.xmlをダウンロードして
全体として、XPath 拡張機能を除く XElement 解析 API が最高のパフォーマンスを提供するように見えますが、ドキュメントがある程度フラットな場合は使いやすくなります。次のようなことをしなければならない深いネスト構造がある場合
XElement.Element("book").Element("author").Element("firstname").SomethingElse()
XElement.XPathSelectElement は、パフォーマンスとコードの保守性との間で最良の妥協点を提供する可能性があります。
まあ、XPathNavigator
一般的にLinq to XML
クエリよりも高速です。しかし、常に「しかし」があります。
Linq to XML
間違いなくコードをより読みやすく、保守しやすくします。(少なくとも私にとっては) linq クエリを読んでから XPath を分析する方が簡単です。また、コードを正しくするのに役立つクエリを作成するときにインテリセンスを取得します。Linq to XML
必要に応じて、データを簡単に変更することもできます。XPathNavigator
読み取り専用アクセスを提供します。
一方、本当に最高のパフォーマンスが必要な場合XPathNavigator
は、おそらく最適な方法です。それは単に、現在のシナリオと達成しようとしていることに依存します。パフォーマンスが問題にならない場合 (XML ファイルがかなり小さい、このファイルに対して多くの要求を行うことはないなど)、簡単に を使用できますLinq to XML
。それ以外の場合は、 の近くに固執しXPathNavigator
ます。