**补两个最容易踩的点:报告里 Self 和 Inclusive 别混着看,生产环境千万别开 Xdebug。**
先接着上面的第四步说。Self(自身耗时)降序能帮你找到"自己烧 CPU"的函数,但真正决定接口响应时间的是 Inclusive(含子调用)。典型情况是:报告里排第一的是某个封装的 Db::query(),Self 很小、Inclusive 很大——那它只是"传话的",根因在它下游。所以顺序建议是:先按 Inclusive 找耗时最长的调用链,再切到 Self 确认这条链上谁在真干活。
比耗时更容易定位问题的是 Calls 次数。单次 0.1ms 调用 5 万次就是 5 秒,这类"看起来不慢但被调疯了"的函数,Xdebug 的函数级插桩刚好能抓出来。不想装 GUI 的话,命令行也能排序:
callgrind_annotate --inclusive=yes --threshold=1 /tmp/xdebug/cachegrind.out.1234 | head -50
再说生产。xdebug.mode=profile 的开销是 2–10 倍,只适合本地/预发。生产要么临时开、抓完就关,要么上采样方案的扩展(xhprof 系)。另外 IO 型瓶颈 Xdebug 只能告诉你"卡在这个函数里",到底是慢 SQL 还是外部接口,得配合 MySQL 慢查询日志或 curl 日志才能定性。
最后一句:xdebug.output_dir 必须存在且 PHP-FPM 用户可写,每个请求生成一个文件,压测久了 /tmp 会被塞满,记得挂个定时清理,别把磁盘跑爆。

正式会员
认证极客









