Enthusiastic developer: Redis cache on all config, homepage latency down thirty percent. Checkout still four seconds. Nobody profiled checkout — time lives in forty-seven SQL queries from a misnamed Laravel accessor. Redis sped what was already fast.
PHP profiling is not a "when we have time" step. It is anti-debate between intuition and measurement. Without a flame graph, you rewrite code; with it, you attack five percent of the call graph costing eighty percent of time.
Tools by context
| Tool | Environment | Overhead |
|---|---|---|
| Blackfire / Tideways | Staging + prod sampling | Low |
| SPX | Dev/staging, prod possible | Very low |
| Xdebug trace | Dev/staging only | High |
| PHP-FPM slowlog | Production | Minimal |
| APM (Datadog, Sentry) | Production | Variable |
Recommended workflow:
- Monitoring identifies slow route at p95.
- Blackfire/SPX profile that URL under simulated load.
- Fix (SQL, cache, algorithm).
- Re-profile — numeric proof of gain.
Do not profile the homepage if the ticket says "admin CSV export timeout."
Read results without drowning
Common signals:
| Dominant function | Action |
|---|---|
PDOStatement->execute | EXPLAIN, index, ORM eager load |
curl_exec | Timeout, cache, async |
file_get_contents | Local I/O, stream, object storage |
Large unserialize / json_decode | Payload format, cache |
Mass preg_match | Regex or parsing refactor |
CI and staging integration
- Blackfire build comparisons on PRs if budget allows.
- Regression threshold: +10% wall time blocks merge (critical routes).
- Anonymized prod-like dataset mandatory — profiling on three DB rows lies.
The profiler sometimes reveals infra limits: session file disk I/O → Redis sessions; slow DNS → fixed resolver; OPcache off → enable immediately. VPS upgrade before profiling remains frequent waste.
The peak: optimizing without profiler is refactoring for fun
Here is what Friday evening "I optimized a line" forgets to show.
Team rule: perf ticket closed with before/after capture — Blackfire or SPX export link.
Decide and move forward without blind spots
In half a day you can establish a measurement discipline:
- Identify target route via APM or slowlog.
- Profile on staging under realistic load.
- Fix only the flame graph peak.
- Re-measure p95 in production.
- Document the lesson — classic N+1 queries?
Start with the route users actually wait on — not the one you look at most in development. Cross-read PHP-FPM saturation, Missing MySQL index and PostgreSQL EXPLAIN depending on your database engine.
Frequently asked questions
Which profiler in production?
SPX or light Blackfire/Tideways sampling. Never Xdebug step debug in production. PHP-FPM slowlog suffices to spot long I/O without full profiler overhead.
Is Xdebug profiler on staging enough?
Yes if data and traffic are near production. Profile slow routes from monitoring — not just the homepage that hides real bottlenecks.
How to read a flame graph?
Width represents cumulative time. Find unexpectedly wide bars — PDO, curl, unserialize. Optimize the widest first, per Pareto's law.
Profiler says PDO slow — what next?
Run EXPLAIN on the SQL query, check indexes and ORM N+1 queries. The profiler shows where time went; EXPLAIN explains why the database responds slowly.
Measuring a PHP line costs less than rewriting it twice — profile first, ego second.