パフォーマンスの目(AutoLinkとisset())†
- 元タイトル: パフォーマンスの目(AutoLink)
- ページ: BugTrack2
- 投稿者: kawai
- 優先順位: 低
- 状態: 却下
- カテゴリー: その他
- 投稿日: 2005-02-21 (月) 15:22:54
- バージョン: 1.4.5
状況 2005-02-05†
1. AutoLinkが有効であり、かつ膨大な量のAutoLink対象ページ(数千?)があり、かつページの中に膨大な量のAutoLink対象文字列がある場合、1ページを表示するときのis_page() のコール回数が5000回を越えるようになる。このような時には、is_page()全体の処理をメモリにキャッシュすることで、is_page()の実行時間を極力下げることがやや有効らしい。ただし、メモリオーバーヘッドは状況が悪化するにつれ指数関数的に増大すると思われる。 -- henoheno
2. この状況では、AutoLinkの処理自体がボトルネックになっているようである。そちらをチェックするのはどうか。
3. 実際のページ数よりも多くis_page()がコールされる状況がそもそもよろしくない。AutoLinkの表示上の問題をスマートに解決できないものか。
メッセージ†
キャッシュをどこに持つべきか、持たないべきか。
細かいパフォーマンスチューニングについて。
とりあえず、1.4.5 をベースにします。
is_page() のキャッシュ†
ページを更新する場合に、「ページの更新」ボタン→ redirect → 編集後のページと
遷移しますが、ページ数が多い(といっても 3000 ページほどですが)場合、
redirection を出すまでの時間がとても長くなります。
少し話を絞りたいので、is_page() を調整する場合を考えます。
diff -u pukiwiki-1.4.5/lib/func.php pukiwiki-1.4.5.nw/lib/func.php
--- pukiwiki-1.4.5/lib/func.php 2005-01-27 21:50:43.000000000 +0900
+++ pukiwiki-1.4.5.nw/lib/func.php 2005-02-21 21:49:03.778414400 +0900
@@ -43,8 +43,17 @@
// If the page exists
function is_page($page, $clearcache = FALSE)
{
- if ($clearcache) clearstatcache();
- return file_exists(get_filename($page));
+ static $is_page_cache=array();
+ if ($clearcache){
+ clearstatcache();
+ return $is_page_cache[$page]=file_exists(get_filename($page));
+ }else{
+ if(isset($is_page_cache[$page])){
+ return $is_page_cache[$page];
+ }else{
+ return $is_page_cache[$page]=file_exists(get_filename($page));
+ }
+ }
}
function is_editable($page)
redirection を送り返すまでの時間を計測し、秒で出します。
$autolink=8(デフォルトの設定)
- original
- 15.7280948162
- 15.426306963
- 15.5838799477
- 15.5360071659
- 15.4648089409
- 15.4504718781
- 15.684360981
- 15.7360160351
- 15.596309185
- 16.0735969543
- modified
- 14.764343977
- 14.7630338669
- 14.8030269146
- 15.0483410358
- 14.8650269508
- 14.8224220276
- 14.9437019825
- 15.0613811016
- 14.7906188965
- 15.3033359051
おぉ。よかった。5 % 程度の高速化で済んだ。
$autolink=0
- original
- 1.45402407646
- 1.42836213112
- 1.4352748394
- 1.43410491943
- 1.43086504936
- modified
- 1.55005908012
- 1.45177197456
- 1.46557188034
- 1.48746085167
- 1.49871683121
こちらは若干速度が落ちます。
当然のことですが、ハードウェアの構成などで測定数値の状況は変わります。
上の数字はあくまで私の手元で実験した時の数字です。
問題は autolink が有効になっている場合に、do_search() が呼ばれ、
全ファイル探索に入るためですが、is_page() をキャッシュすると少しだけ
軽減できます。
副作用として通常のページ表示で若干遅くなると推測されます(こちらは未測定)。
- clearstatcache()をやらないから速くなっているとか? -- teanan
- あー。そうですね。もう一回計ってみましょう。 -- kawai
- こんにちは :) PHPfunc:clearstatcache はPHPのファイルシステムキャッシュをリセットする、PHPの関数です。これをコメントアウトするとキャッシュされっぱなしになるので、コメントアウトしてはいけませんです。 -- henoheno
- autolink の値は 1.4.4 まではデフォルトで 0 (無効) でした。ご参考まで。 -- henoheno
- autolink = 8 の時の最初の2回が不要にばらついているのが気になります (^^; 何度でもお試しになって、安定した状態のものを参考値として出されるのはいかがでしょうか -- henoheno
- そうですね。私は1.4.4 は見ていません。 -- kawai
- 測りなおしたものを出しますので、上のものを書き換えます。 -- kawai
- どうもautolink周りを覗いてみた方が良さそうな雰囲気ですね。 -- henoheno
- 了解でーす (書き換え) リリース作業に戻ります。 -- henoheno
- はい。書き換えました。が、あまり変わりませんでした。これはこれで嫌な感じですね。 -- kawai
- お疲れ様です。書き直されたものをふまえて確認させていただきたいのですが、このデータは、毎回別のページを更新して得た秒数ですか? (秒数のぶれが大きい理由がよくわかりません) -- henoheno
- 私もぶれが大きいのが気になってサーバの設定をみなおしてみたところ、少し起こりやすい原因が分かったので、もう一回取り直します。 -- kawai
- もっとも clearcache の起こりにくいパターンなのですが、関数呼び出しの手間とキャッシュと比較してちょっと良くなった程度になりました。MaxRequestsPerChild が少し小さめになっていました。 -- kawai
- if ($clearcache) で unset($is_page_cache) したほうがいいかと。 -- teanan
- ? is_page() の第二引数は $page のキャッシュをクリアしたいという意味ではなく、全てのキャッシュを破棄したい。ということでしょうか? -- kawai
- 今回メモリ内に設けようとしているキャッシュはつまるところ file_exists() のキャッシュ*1ですが、PHPfunc:file_exists はPHPにより既にキャッシュ機構を持っています。clearstatcache() はfile_exists() のキャッシュもクリアしますから、clearstatcache() を呼ぶタイミングでメモリ中のキャッシュもクリアしてあげないと、「実際はファイルが存在しなくなっているファイル」についてメモリの中では存在していることになってしまうような不整合が発生する可能性があると思います。 -- henoheno
- ファイルがあるかどうかは pukiwiki の中では is_page を通して行われるという理解だったのですが、違いますでしょうか? -- kawai
- また、今回のキャッシュは単に file_exists キャッシュをしたいというだけでなく、無駄な計算や関数呼び出しを省きたいというのもあります。ちなみに、今の環境ですと is_page() は 16,347 回呼ばれます。 -- kawai
- どうも今私の使っている Xdebug にバグがあるようで、回数が間違っていました。正しくは 5449 回でした。 -- kawai
- もし clearstatcache を is_page を通さずに行っても良いとすると、もっと速くできそうです。上と同じ条件で 13 秒台にのります。 -- kawai
- 第二引数を指定しているのは、grepする限りではfile.php:file_writeとlink.php:links_updateの2ヶ所だけですね。ここを見る限りだと、指定されたページの有無を更新するだけで良さそうです。 -- teanan
- staticキャッシュを持つのであれば、file.php:file_write ではclearstatcache()は必要なくてファイルの有無($is_page_cache[$page])の更新だけで良さそうです。link.php:links_updateはget_filetimeのキャッシュをクリアする目的を兼ねていそうですのでclearstatcache()は必要ですね。 -- teanan
- まぁ、いずれにせよ、autolink をどうにかすれば済んでしまう話ではあるので、そちらを期待しております。 :) 私も何か良い案が思いついたら出しますので…。 -- kawai
- autolinkの実装の部分にどうにかできる余地があるかどうかすらまだ誰も見ていないのですから、安心してはいけません :) -- henoheno
- is_page()のコール回数の件ですが、1.4.5_1をインストールした直後の「整形ルール」を表示した場合、100回(これでも多いと思うのですけれど)しか呼ばれないようです。5449回というのはすごい量ですね (^^; cache/autolink.datは今何バイトくらいあるんですか? -- henoheno
- 良くみたらteananさんのツッコミが反映されたかどうかがわからないですね (^^; どうしてもclearstatcache()を呼びたくないというのであれば、元のis_page()からもclearstatcache()を取り除いて、それと数値を比較して下さい。(そうでないと条件が揃わないので比較にならない) -- henoheno
- cache/autolink.dat のバイト数>17KB でした。 -- kawai
- 1.4.5_1 もちょっと眺めてみます。 -- kawai
- よっこらしょ。関連する場所の変更点はありませんね。 -- kawai
- こちらの件ですが、現状は比較している両者の条件が揃っておらず、メモリのオーバーヘッドを増やすデメリットを覆すほどの爆発的な効果も見込めなていないことから、ひとまず却下とさせていただきます。何かあればまたコメント下さい。 -- henoheno