2011/09/21

[C#]XPathの処理速度を調べる

このエントリーをはてなブックマークに追加
XPathを処理するのにXmlDocumentクラスのSelectNodes(SingleSlectNode)メソッドを利用する方法はよく使っていて知っていたけれど、XPathNavigatorなるクラスを用いるやりかたがあることを知ったので、それぞれ速度検証しました。
XPathNavigatorはSystem.Xml.XPathにあります。
こいつの使い勝手がよくなると、とても便利なはず。

XPath(XML Path Language) - Wikipedia

XPathの処理方法

検証方法は、それぞれ下の三本立てです。
  1. SelectSingleNodeメソッドを使用する方法
  2. XmlDocuemntクラスからXPathNavigatorクラスを使用する方法
  3. XPathDocumentクラスからXPathNavigatorクラスを使用する方法
結論からいうと、3番目のXPathDocumentクラスからXPathNavigatorクラスを使用する方法が高速でした。

1.SelectSingleNodeメソッドを使用する方法
string fileName = "rss.xml";
string xPath = "//item/title";

XmlDocument xDoc = new XmlDocument();
xDoc.Load(fileName);

XmlNodeList xNodeList = xDoc.SelectNodes(xPath);
foreach(XmlNode xNode in xNodeList){
    // 処理
}

2.XmlDocuemntクラスからXPathNavigatorクラスを使用する方法
string fileName = "rss.xml";
string xPath = "//item/title";

XmlDocument xDoc = new XmlDocument();
xDoc.Load(fileName);
XPathNavigator xNavi = xDoc.CreateNavigator();

object o = xNavi.Evaluate(xPath);
if (o is XPathNodeIterator) { // ノード セットを返す場合
    XPathNodeIterator nodeIterator = (XPathNodeIterator)o;

    foreach (XPathNavigator current in nodeIterator) {
        // 処理
    }
} else {
    // count()など単一の値を返す場合
}

3.XPathDocumentクラスからXPathNavigatorクラスを使用する方法
string fileName = "rss.xml";
string xPath = "//item/title";

XPathDocument xPathDoc = new XPathDocument(fileName); // 読み取り専用
XPathNavigator xNavi = xPathDoc.CreateNavigator();

object o = xNavi.Evaluate(xPath);
if (o is XPathNodeIterator) { // ノード セットを返す場合
    XPathNodeIterator nodeIterator = (XPathNodeIterator)o;

    foreach (XPathNavigator current in nodeIterator) {
        // 処理
    }
} else {
    // count()など単一の値を返す場合
}

検証結果

検証には、某ニュースサイトのrss.xmlを使用させていただきました。
検証は、オーバーヘッドを省いたXPath実行部だけの繰り返しです。この検証結果が安定的なのかどうかは別の問題なので、参考程度にしてください。

10000回実行
1.XmlDocument→SelectSingleNode00:00:06.2230160
2.XmlDocument→XPathNavigator00:00:10.5814837
3.XPathDocument→XPathNavigator00:00:03.6765160

XPathNavigatorが2倍くらい早いようです。もっと圧勝してるのかなあ、という検証結果を期待したのだけど、それほどでもという感じ。まあ間違いなく、早いには早いんだけど。
そもそも10000回で10秒なので気にするレベルではないようです。どれを使っても問題ない。まあ、XPathを処理するところがそんなにバラエティーに富んでるわけないので、そりゃそうかと思わないでもないです。

ただし、XPathNavigatorクラスがXPathDocumentという読み取り専用からでも利用できるという意味では、XMLの読み込みのオーバーヘッドは減らせるのに役立つでしょう。
そして普通にXPathの勉強になりました。
count()などを利用する場合は、XPathNavigatorクラスを用いればいいようです。SelectSingleNodeメソッドは対応してくれない。

おまけ:勉強になったXPathの書き方

対象文字が含まれる内容を抽出したいときのXPathの書き方。

//item/title[contains(.,'Windows')]

→記事タイトルにWindowsの文字があるものを抽出するXPath。

0 件のコメント :

コメントを投稿