我自己有個 wiki 拿來堆一些資料,前陣子覺得 Live 這頁很慢,實際測試發現要跑五秒多,想說到底是什麼鬼...
先從 MediaWiki 的各種 optimization 設定開始看,像是 Manual:Cache 這邊提到的東西,一路看下來看起來都已經設好最佳化了。
只好拿 profiling 工具來翻,在 PHP 上面用的是 Xdebug,裝了以後希望是特殊的情況才跑 profiling,所以參考了「Profiling」這邊的說明,在 php.ini
裡面這樣設定:
xdebug.mode=profile xdebug.start_with_request=trigger xdebug.trigger_value=StartProfileForMe
接著依照說明,你要找個地方把這個值傳進去:
Xdebug's profiler will only start when either the environment variable
XDEBUG_TRIGGER
is set toStartProfileForMe
, the GET or POST variableXDEBUG_TRIGGER
is set toStartProfileForMe
, or when the cookieXDEBUG_TRIGGER
has the valueStartProfileForMe
.
我是在網址列上直接用 ?XDEBUG_TRIGGER=StartProfileForMe
觸發,預設值會把 profiling 結果丟到 /tmp
下面,接下來就是把 callgrind 檔案視覺化了。
首先是把 xdebug 的 callgrind 格式輸出檔案轉成 DOT 格式,這邊參考「Interpreting callgrind data」的說明,先裝 gprof2dot,這個軟體在 PyPI 上有,所以可以用 pipx 裝,接著把 callgrind 轉完後再轉成 PNG 檔案。
我把圖放到最後面 (點開可以看大圖),第一張是 Live 這頁的 profiling,第二張是 Hosting 這頁的。
我注意到在 Live 這頁 php::mysqli
這邊被呼叫了幾千次,這邊就算是本地端的資料庫,幾千次的 latency 累積起來還是很驚人,畢竟是跨 process 之間的溝通,而且已知是 ping-pong 要等待的情況。
接著去翻是什麼造成的,看起來跟 selectRow
有關,但線索到這邊就斷掉了,上面的 User->load
看起來並沒有 loop 導致大量呼叫 selectRow
。
但至少有個方向,從網路上沒什麼討論看起來,應該不會是本體的效能問題,而是 extension 造成的,從這個角度開始追與帳號 & 權限有關的 extension,第一發懷疑是 Extension:AccessControl 造成的,結果果然沒錯... 拔掉後頁面的速度就從 5.1 秒左右降到 1.5 秒左右了。
沒有實際追程式碼,但猜測是 wiki 裡面用的 Template 造成 AccessControl 都會去檢查權限,加上這邊沒有上 cache,造成頁面上 Template 一多效能很差...
最後,這是 Live 頁的 profiling graph:
這是 Hosting 頁的 profiling graph: