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。

2011/09/17

Googleの印刷プレビュー機能を無効にする

このエントリーをはてなブックマークに追加


搭載された待望のGoogleChromeの印刷プレビューですが、処理が重くて評判はあまりよくないようです。

うちの環境では、ページによっては固まって動かなくなるレベルでした。
評判云々というか、シンプルに困りました。

  • 印刷はプレビュー表示後に実行できるようになる。プレビューが表示されるまで印刷実行できないので、ページによっては処理が重くて、永遠に印刷実行が選べません。
  • 印刷設定を変更するとプレビューは作り直しになる。プレビューが表示されるまで待って、最後のページが空白だったり、最初の1ページだけいいので、その指定をすると、改めてプレビューを表示しなおそうとする。また数分待つはめに。
  • ページによっては重くてそのまま固まってしまい、印刷をキャンセルしても、同一タブのページが一通り固まってしまう地雷機能と化してしまいました。

印刷プレビューが搭載されたことによって、Chromeブラウザの印刷機能がほぼまるごと使えなくなってしまったわけです。
これではいかん、ということで無効にする方法を調べました。

さくっと使えている環境もあるようで、1秒ほどでプレビュー表示されるのであれば重宝する便利機能であることは想像できるのでうらやましいかぎりです。

●Googleの印刷プレビュー機能を無効にする



buzzword update - Chromeで印刷プレビューを無効にする方法
http://buzzwordjp.blogspot.com/2011/08/chrome.html

Chrome起動時のショートカットに、「 --disable-print-preview」(前に半角スペース2つ)を指定しておけば、印刷プレビュー表示機能を無効にして、プリンタ選択ダイアログから印刷できるようになります。

よかったー。一安心。
ずっとこうしておくことにしよう。

※追記20110928
どのタイミングか不明ですが、プレビュー待たずして印刷ができるようになっていました。
なので、待たされることなく強行はできます。