del.icio.usの重そうな処理速度を計測した

del.icio.usのclass=postかdesc周辺をGMで何かしたくなったのでやってみたけど遅い。適当な文字列を各ブックマークタイトル前に挿入するGMを書いて、FireFoxで50 entry/page、10回(だけ!)平均で測定してみた。それほど厳密な計測じゃないので計測状態の違いで差はあると思うけど、できる限り近い状態で計測したつもり。

del.icio.us/ui/static/delicious.jsで出てくる$cを普通に使った場合

Start: GM実行可能フェーズ, Loaded: GMで登録したonloadハンドラ先頭, End: GM内処理終了。詳細は後で出てくるソース参照。

[Loaded - Start] [End - Loaded] [End - Start]
1 5719 1172 6891
2 3125 1234 4359
3 2672 1188 3960
4 3328 844 4172
5 2859 844 3703
6 2968 844 3812
7 2813 843 3656
8 2360 1187 3547
9 2375 1234 3609
10 2375 1219 3594
avg. 3059.3 1060.9 4120.3
// ==UserScript==
// @name           test_del.icio.us
// @description    hogehohohohohohohogeeeeee
// @include        http://del.icio.us/*
// ==/UserScript==

(function() {
  alert('test_delicious start')
  var gm_start_time = (new Date()).getTime()
  addEventListener('load', function() {
    var page_loaded_time = (new Date()).getTime()
    var forEach = unsafeWindow.forEach
    var $c = unsafeWindow.$c
    var $DIV = unsafeWindow.$DIV
    var descs = $c('desc')
//    var descs = $c('desc', $c('posts', document, 'ol'), 'h4')
    forEach(descs, function(d) {
      d.parentNode.insertBefore($DIV({}, "[[unko]]"), d);
    })
    var gm_end_time = (new Date()).getTime()
    alert([
      'test_delicious end. \n',
      'start: ' + gm_start_time + '\n',
      'loaded: ' + page_loaded_time + ' diff:' + (page_loaded_time - gm_start_time) + '\n',
      'end: ' + gm_end_time + ' diff:' + (gm_end_time - page_loaded_time) + '\n',
      '[end-start] : '  + (gm_end_time - gm_start_time)
    ].join(''))
  }, true)
})()

初回はブラウザの何かがどうにかなって遅いのだと思う。onload実行されるまで約2800msくらいかかってる。GMでいれた処理(End - Loaded期間)も1000ms近くかかってる。GM内では対したことしてないけど、なんとなく$cが時間かかってそうなので$cを使ってる処理を探したところ、Mp3.go(),Folds.go()で使われていることを確認した。$c関数はgetElementsByClassNameの検索対象のDOM階層、対象タグも指定できるような関数で、del.icio.uslib.jsに入ってる。
Mp3.goではdocument内の全anchorのうちclass='mp3'のものを検索して、動的レンダリングしている。Folds.goではtag-bundleの折りたたみ挙動の書き換えを実施。こちらはdocument内の全ulからclass='bundles'のものを検索している。とりあえず、この二つの$c処理だけ計測してみた。計測にはbookmarkletに以下のコードをキーワードbbfとして登録して実施した。Ctrl + Lだと瞬時にアドレスバーに移ると今回のような計測に便利だとわかった。

javascript:(function(){var before=new Date().getTime();%s;var result = new Date().getTime() - before;alert('process time(ms)='+result)})()

Mp3.go, $c('mp3', document, 'a')処理時間

タグ付けてないyoupyさんのページと比較してみた。

rtk2106 youpy
1 453 47
2 453 31
3 438 31
4 469 47
5 453 47
6 468 31
7 469 63
8 468 47
9 485 47
10 469 63
avg. 462.5 45.4

10倍くらい違う。タグクラウドにmp3クラスないからpostsクラスで絞った結果だけ検索することで高速化できそうな気がする。

Mp3.go, $c('mp3', $c('posts', document, 'ol'), 'a')

rtk2106 youpy
1 62 47
2 78 47
3 63 47
4 93 47
5 62 47
6 62 47
7 62 31
8 78 47
9 62 47
10 94 31
avg. 71.6 43.8

速くなった。

Folds.go, $c('bundles',document,'ul').each(function(f){ $c('label', f)[0] })

Folds.goでは$c('bundles',document,'ul')だけだとほとんど時間かかってなくて、その下のlabel検索で時間がかかっていた。

rtk2106 youpy
1 718 47
2 750 15
3 750 47
4 750 31
5 734 47
6 719 31
7 734 46
8 734 47
9 750 47
10 734 47
avg. 737.3 40.5

対象がタグクラウド部のせいか、18倍くらい違う。class='label'検索対象をh3タグ限定にして計測してみる。

Folds.go, $c('bundles',document,'ul').each(function(f){ $c('label', f, 'h3')[0] })

rtk2106 youpy
1 16 32
2 0 15
3 15 0
4 0 16
5 16 16
6 15 31
7 16 31
8 15 16
9 16 16
10 16 15
avg. 12.5 18.8

速くなった。

Delicious.Shortcut.init内の$('.posts')

これも遅そうだったので計測した。del.icio.usで使ってる$()関数はjQueryのものらしい(とコメントに書いてある)。

rtk2106 youpy
1 969 125
2 859 109
3 875 109
4 891 110
5 829 109
6 875 110
7 844 110
8 844 110
9 875 125
10 969 110
avg. 883 112.7

Delicious.Shortcut.init, $('.posts', $id('main'))

$()関数も検索コンテキストを指定できるのでgetElementByIdした結果から検索するようにしてみた。

rtk2106 youpy
1 125 63
2 140 78
3 156 78
4 125 94
5 125 78
6 140 78
7 187 78
8 156 78
9 141 79
10 172 78
avg. 146.7 78.2

速くなった。

以上を踏まえて、元のGMで要素選択する対象を絞る

descs取得のコードをコメントアウトしてるものと交換して計測した。

[Loaded - Start] [End - Loaded] [End - Start]
1 2672 78 2750
2 3516 62 3578
3 2844 62 2906
4 2953 63 3016
5 2828 47 2875
6 2344 47 2391
7 2344 63 2407
8 2344 62 2406
9 2797 63 2860
10 2953 62 3015
avg. 2759.5 60.9 2820.4

変更対象期間(End - Loaded)を高速化できることを確認した。


本当は遅くなってる問題の箇所をGMで高速化したバージョンに置き換えとかできればいいのだけどhtml中に直接書かれているscriptタグを書き換える方法がわからない。GMが呼ばれた時点ではまだscriptタグが評価されていなく(外部スクリプトでグローバルに置いた変数への参照が不正になる)、GMで登録したonloadのタイミングでは既に実行後であることは確認した。

一般的なまとめとして、なんでもかんでもタグ付ければいいってもんじゃないということがわかった。del.icio.usの人もいっぱいタグ付ける人いないだろう、ってことで放置してるような気がする。tag-cloudのuse minimum=5にしとけば5未満の小さいタグがいっぱいな場合に速くすることはできるはず、だけど自分のユーザページではそれほど体感速度の向上は無かった。