Contents
- 1 PHP performance optimization basics
- 1.1 Why bother with performance, anyway?
- 1.2 Step 1: Profile before you touch a thing
- 1.3 Code tweaks that punch above their weight
- 1.4 OPcache: Your first big lever
- 1.5 Database: Where 80% of pain hides
- 1.6 Caching strategies done right
- 1.7 PHP-FPM and server tuning
- 1.8 Frameworks and modern stacks
- 1.9 Quick wins table
- 1.10 Measuring and iterating
PHP performance optimization basics
Hey, fellow PHP devs. Picture this: it's 2 AM, your site's crawling under traffic, and that one endpoint is choking on a sloppy query. Heart sinks a bit, right? We've all been there—staring at the profiler, coffee gone cold, chasing that elusive speedup. But here's the thing: PHP performance isn't some black magic. It's methodical, repeatable, and honestly, kind of satisfying when it clicks.
I've spent years tweaking apps on Find PHP projects, from small shops to high-traffic beasts. Optimization starts simple: measure what's breaking, fix the big wins, then layer on the smart stuff. Today, let's walk through the basics that deliver real results—without drowning in theory. These are the moves that turn "feels slow" into "blazing fast."
Why bother with performance, anyway?
Performance isn't just ego. Users bounce if pages lag over 2 seconds. Google ranks speed. And on platforms like Find PHP, where you're hunting gigs or hiring talent, a snappy app screams competence.
Think about your last deploy. Did it hum, or did it stutter? The basics—OPcache, queries, caching—often give 3-10x gains. No fancy hardware needed. Just smart code and config.
Have you profiled lately? If not, stop reading. Fire up Blackfire or Xdebug. Baseline your p95 latency now.
Step 1: Profile before you touch a thing
Guessing is death. I once spent days "optimizing" a loop that wasn't the bottleneck. Profiling showed 80% time in a DB call. Facepalm.
Tools that work:
- Blackfire or Tideways: Flame graphs show hotspots instantly.
- Xdebug + Cachegrind: Free, but heavier.
- New Relic or similar: For prod monitoring.
Process: baseline → profile → fix top 1-3 → remeasure. Repeat. Set SLOs like "p95 under 150ms for /search."
In realistic conditions—staging or prod-like load. Tools reveal N+1 queries, memory leaks, slow functions.
Quick win: single quotes over doubles for strings. isset() beats array_key_exists(). Avoid loops with DB hits—batch or eager-load.
Code tweaks that punch above their weight
PHP's evolved. PHP 8.4 brings JIT, Property Hooks, array_find*—but measure them. Don't assume.
Avoid common traps:
- No queries in loops. Use JOINs, generators, or async (Swoole/OpenSwoole for 10x gains).
- Stateless apps: ditch sessions if possible.
- Memory: watch circular refs (garbage collection kills perf). Use
memory_get_usage()to spot leaks.
Refactor hotspots. Minify JS/CSS, bundle 'em, async load. Stateless code scales easier.
Example: swap this mess…
foreach ($users as $user) {
$posts = DB::query("SELECT * FROM posts WHERE user_id = ?", $user->id);
// process
}
…for:
$posts = DB::query("SELECT * FROM posts p JOIN users u ON p.user_id = u.id");
OPcache: Your first big lever
Enable it. Now. It's bytecode caching—compiles PHP once, caches in shared memory. Drops TTFP by 50-70%.
In php.ini:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.revalidate_freq=0 ; Prod only
opcache.jit_buffer_size=100M ; PHP 8+
Tune for your load: more memory for big apps. Benchmarks show tweaks squeeze extra 20%.
Pair with JIT (PHP 8+). Not magic—test your workload. Invoking=tracing,blackfire for wins.
Database: Where 80% of pain hides
Bottlenecks love DBs. Profile queries first.
Fixes that stick:
- EXPLAIN ANALYZE. Add indexes on WHERE/JOIN/ORDER columns.
- Kill N+1: eager load in Eloquent/Doctrine.
- Batch inserts. Paginate properly.
- Timeouts on queries.
Cache hot data: APCu for local, Redis/Memcached shared. Reduces hits to zero over time.
Normalize, but denormalize read paths. No SELECT *—grab what you need.
I've seen apps go from 500ms to 50ms just indexing right.
Caching strategies done right
Cache everything stable. Page, data, DB results.
Layers:
- OPcache: Code.
- APCu: Local, fast objects.
- Redis: Distributed, pub/sub bonus.
- Full-page: Varnish or app-level.
Monitor hit/miss. Aim for 90%+ hits. Minimally invasive, huge ROI.
CDNs offload statics—JS/CSS/images. Cuts latency worldwide.
PHP-FPM and server tuning
PHP-FPM rules most stacks. Tune pools:
pm = dynamic
pm.max_children = 100 ; RAM-bound
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_requests = 1000 ; Leak prevention
Benchmark defaults first. Monitor CPU/RAM. Slowlog catches outliers.
Nginx > Apache for high traffic. LiteSpeed if you want easy.
php.ini extras: bump memory_limit wisely, max_execution_time per app.
Frameworks and modern stacks
Pick lean: Laravel 10+, Symfony 6+, Mezzio. Middleware over MVC for speed.
Swoole integration: async, coroutines. Frameworks support it—game-changer for I/O.
Composer: composer install --optimize-autoloader --no-dev --classmap-authoritative. Cuts autoload time.
Quick wins table
| Tweak | Gain | Effort |
|---|---|---|
| OPcache on | 2-3x | Low |
| Index DB | 5-10x queries | Med |
| APCu/Redis | 90% cache hit | Low |
| No loop DB | 3x endpoint | Low |
| JIT tuned | 20-50% CPU | Med |
| CDN statics | Global latency | Low |
Measuring and iterating
Load test: Apache Bench, k6. CI perf budgets—fail PRs on regressions.
Document flamegraphs in repo. Make it routine.
PHP 8.4 niceties shine when measured. Fibers for concurrency, but basics first.
Friends, optimization feels like therapy—uncover the mess, clean it up, watch it fly. That quiet glow when benchmarks drop? Worth every late night. Grab your profiler. Your next project deserves it.