枕を欹てて聴く

香炉峰の雪は簾を撥げて看る

XPath

調べてみるとちょっと衝撃を受けたので書いておく。

以下XPathによるFirebug上からの抽出速度。抽出対象はLDR Full Feedで本文として指定しているもの。
速度計測法はid:os0xさんのjottit.comのLDRize用XPath - FFFF - 0xで使っているFirebug組み込み関数である$xによる抽出1000回の所要時間。

調査目的は、前から疑問に思っていた、抽出対象がclassなど特定条件で一発で抽出できる場合(//div[@class="entry_body"]など)の以下3つの疑問点

  • 全体からclassなどで一発で抽出するのと、祖先ノードにidのある場合、それをid関数で抽出した後子要素を検索するのではどちらが速いのか。
  • //div[@id="ほにゃらら"]はマジで遅いのか。
  • //div[@class="ほにゃらら"]と//div[contains(concat(" ", normarize-space(@class), " "), " ほにゃらら ")]ではどれほどの違いがあるのか。

いろいろなサイトを今から調べてみるので、後々追記していく。

以下、動作させたScriptと時間。また、きちんと同じ要素を抽出しているかを見るために、計測前にconsole.info(s)で確認。
(一括でやると途中でScriptとめられてしまったので、分割してやっています。また、順番は何度か入れ替えて、その時間の平均をとりました。)

//Sample1: http://www.kajisoku.org/archives-0/eid1959.html
//site:    ⊂⌒⊃。Д。)⊃カジ速≡≡≡⊂⌒つ゚Д゚)つFull Auto
//about:   //div[@class="entry_body"]は2つあります。
var s;

console.time('a');
for (var i = 0;i<1000;i++){
    s = $x('//div[@id="m_site"]/div[@class="entry"]/div[@class="entry_body"]');
}
console.timeEnd('a');//a: 5533ms

console.time('b');
for (var i = 0;i<1000;i++){
    s = $x('id("m_site")/div[@class="entry"]/div[@class="entry_body"]');
}
console.timeEnd('b');//b: 161ms

console.time('c');
for (var i = 0;i<1000;i++){
    s = $x('//div[@class="entry_body"]');
}
console.timeEnd('c');//c: 5409ms

console.time('d');
for (var i = 0;i<1000;i++){
    s = $x('//div[contains(concat(" ",normalize-space(@class), " ")," entry_body ")]');
}
console.timeEnd('d');//d: 5569ms
//Sample2: http://trendy.nikkeibp.co.jp/article/pickup/20080404/1008883/
//site:    日経トレンディ
//about:   同じid(idのentがliとdivにひとつずつあって、id関数じゃ対応できなかった。これって正常?)があってあせった。
//よって代替としてそのひとつ上のidのmainを基準に捜索。
//これはあんまり参考にならないかも。
var s;
console.time('a');
for (var i = 0;i<1000;i++){
    s = $x('//div[@id="main"]//div[@class="articlebody"]');
}
console.timeEnd('a');//a: 1859ms
console.time('b');
for (var i = 0;i<1000;i++){
    s = $x('id("main")//div[@class="articlebody"]');
}
console.timeEnd('b');//b: 670ms
console.time('c');
for (var i = 0;i<1000;i++){
    s = $x('//div[@class="articlebody"]');
}
console.timeEnd('c');//c: 1351ms
console.time('d');
for (var i = 0;i<1000;i++){
    s = $x('//div[contains(concat(" ",normalize-space(@class), " ")," articlebody ")]');
}
console.timeEnd('d');//d: 1649ms

ちなみに現在SITEINFO_Wikiに登録されているものはいずれもcのもの。

えっと、びっくりした。

個人的な見解とまとめ

  • /div[@id"ほにゃらら"]はうわさにたがわず遅かった。
  • id関数がすごすぎた。

id関数で高速に抽出後、絞られた要素のみを検索しているから速くなってるのかな。
予想をものすごく裏切られたのでびっくりした。
あんまりにも予想と違ったので誰か別の方が調べてくれるとありがたいです。なんか早合点してそうな気がものすごくするので。
もしかしてSITEINFO書き換え次第では大幅な高速化が見込めるかも。

Remove all ads