10 PHP Performance Tricks Every Developer Should Know
Introduction
Performance is a critical aspect of any web application. While PHP has evolved significantly—especially with version 8.x—many developers still overlook simple optimizations that can yield substantial speed improvements. This article covers ten practical PHP performance tricks that you can apply today.
1. Use OPcache
OPcache stores compiled PHP scripts in shared memory, eliminating the need to parse and compile files on every request. Enable it in php.ini:
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
For production, set opcache.revalidate_freq to a higher value (e.g., 60) or use opcache.validate_timestamps=0 and manually clear the cache during deployments.
2. Enable JIT Compilation (PHP 8.0+)
Just-In-Time compilation can significantly speed up CPU-intensive workloads. Configure it in php.ini:
opcache.jit=on
opcache.jit_buffer_size=100M
JIT is especially beneficial for mathematical operations, image processing, and machine learning tasks. For typical web applications, the default tracing JIT (tracing) works well.
3. Use Proper Data Structures
Choosing the right data structure can drastically reduce execution time. For example, use array_key_exists() instead of in_array() for large arrays, or prefer isset() for checking keys:
$items = ['a' => 1, 'b' => 2, 'c' => 3];
// Fast: O(1)
if (isset($items['a'])) { /* ... */ }
// Slow: O(n)
if (in_array('a', array_keys($items))) { /* ... */ }
For frequent lookups, consider using SplObjectStorage or Ds\Map (if the Ds extension is available).
4. Avoid Overhead in Loops
Minimize function calls and property accesses inside loops. Cache the count of an array:
// Slow
for ($i = 0; $i < count($items); $i++) { /* ... */ }
// Fast
$len = count($items);
for ($i = 0; $i < $len; $i++) { /* ... */ }
Use foreach when you don't need the index; it's often faster than a for loop with count().
5. Use Generators for Large Datasets
Generators yield values one at a time, reducing memory usage when processing large files or database results:
function readLargeFile(string $file): Generator
{
$handle = fopen($file, 'r');
while (($line = fgets($handle)) !== false) {
yield $line;
}
fclose($handle);
}
foreach (readLargeFile('huge.log') as $line) {
// Process line without loading entire file into memory
}
6. Optimize Database Queries
Use indexes, avoid N+1 queries, and fetch only needed columns. With Laravel's Eloquent, use select() and with() wisely:
// Bad: fetches all columns and causes N+1
$users = User::all();
foreach ($users as $user) {
echo $user->profile->bio;
}
// Good: eager load and select only needed columns
$users = User::select('id', 'name')->with(['profile' => function ($query) {
$query->select('user_id', 'bio');
}])->get();
7. Cache Expensive Operations
Use in-memory caching (APCu, Redis, Memcached) for results of heavy computations or database queries:
function getExpensiveData(): array
{
$cacheKey = 'expensive_data';
if (apcu_exists($cacheKey)) {
return apcu_fetch($cacheKey);
}
$data = // ... heavy computation or DB query
apcu_store($cacheKey, $data, 3600); // cache for 1 hour
return $data;
}
For distributed systems, prefer Redis or Memcached.
8. Use String Interpolation Over Concatenation
Double-quoted strings with interpolation are slightly faster than concatenation:
$name = 'John';
// Slower
$greeting = 'Hello, ' . $name . '!';
// Faster
$greeting = "Hello, $name!";
This is a micro-optimization, but it adds up in high-traffic applications.
9. Avoid Unnecessary Object Instantiation
Reuse objects when possible. For example, use a single instance of a class that has no state:
class StringUtils
{
public static function toCamelCase(string $str): string { /* ... */ }
}
// Instead of new StringUtils() each time, call static method
StringUtils::toCamelCase('hello_world');
Dependency injection containers can help manage singletons.
10. Profile Before Optimizing
Never guess where the bottleneck is. Use profiling tools like Xdebug, Blackfire.io, or Tideways to measure actual performance:
# Install Xdebug and enable profiling
php -d xdebug.mode=profile script.php
Analyze the generated cachegrind file with KCacheGrind or QCacheGrind to identify hotspots.
Conclusion
Performance optimization is an ongoing process. Start with OPcache and JIT, then move to data structures, caching, and profiling. The key is to measure first, then optimize the parts that matter. Implement these tricks wisely, and your PHP applications will run faster and handle more traffic.