CodeBlanks Logo Icon CodeBlanks

Summary - Performance

PHP course · Expert · Lesson 28/54

Build an optimized data service with OPcache, benchmarks and eager loading.

Summary - Performance

This group covered four pillars of PHP performance: OPcache removed the compilation cost with a bytecode cache; profiling tools revealed bottlenecks by call count and time; memory_get_usage and the Spl data structures let you watch memory consumption; microtime-based benchmarks compared two approaches.

You fixed the N+1 problem with eager loading and used lazy initialization to skip unnecessary work. Performance work is measure first, change second — intuition misleads.

A combined performance approach

In a real scenario you combine the four tools: first check OPcache with opcache_get_status; then time the comparison with microtime; watch memory spikes with memory_get_peak_usage; if the database shows N+1, switch to eager loading.

Changing a step without measuring leaves optimization to intuition; deciding after a measurement is the professional move.

Exercise OPcache, benchmark and eager loading combined

Start with $start = microtime(true). Get the OPcache status with $opcache_ok = function_exists('opcache_get_status') && opcache_get_status(false) !== false;. The $posts and $authors arrays below are ready. In a foreach print echo $post['title'] . ':' . $authors[$post['author_id']] . "\n"; for each post. Compute $end = microtime(true) and $elapsed = $end - $start. Print echo ($opcache_ok ? "1\n" : "0\n"); and echo count($posts) . "\n";.

Show example solution
' . $authors[$post['author_id']] . "\n"; } $end = microtime(true); $elapsed = $end - $start; echo ($opcache_ok ? "1\n" : "0\n"); echo count($posts) . "\n";.
Example solution:
<?php
$start = microtime(true);
$opcache_ok = function_exists('opcache_get_status') && opcache_get_status(false) !== false;

$posts = [
    ['id' => 1, 'title' => 'A', 'author_id' => 10],
    ['id' => 2, 'title' => 'B', 'author_id' => 20],
];
$authors = [10 => 'Ayşe', 20 => 'Deniz'];

foreach ($posts as $post) {
    echo $post['title'] . ':' . $authors[$post['author_id']] . "\n";
}

$end = microtime(true);
$elapsed = $end - $start;

echo ($opcache_ok ? "1\n" : "0\n");
echo count($posts) . "\n";

Exercise FileCache with an SplStack

Write a FileCache class with public SplStack $keys;; in __construct assign $this->keys = new SplStack();. The set(string $key): void method calls $this->keys->push($key). Create $cache = new FileCache();. Call set('user_1'), set('user_2'), set('user_3'). Print echo $cache->keys->count() . "\n";, echo $cache->keys->pop() . "\n";, echo $cache->keys->count() . "\n";.

Show example solution
void { $this->keys->push($key); } }. $cache = new FileCache(); $cache->set('user_1'); $cache->set('user_2'); $cache->set('user_3'); echo $cache->keys->count() . "\n"; echo $cache->keys->pop() . "\n"; echo $cache->keys->count() . "\n";.
Example solution:
<?php
class FileCache {
    public SplStack $keys;

    public function __construct() {
        $this->keys = new SplStack();
    }

    public function set(string $key): void {
        $this->keys->push($key);
    }
}

$cache = new FileCache();
$cache->set('user_1');
$cache->set('user_2');
$cache->set('user_3');

echo $cache->keys->count() . "\n";
echo $cache->keys->pop() . "\n";
echo $cache->keys->count() . "\n";

Test yourself

  1. Which approach cuts queries the most?

    • Calling each item separately with lazy loading
    • Calling memory_get_usage
    • Loading all relations in one query with eager loading
    • Using a plain array instead of SplStack
    Show answer

    Loading all relations in one query with eager loading — Correct. Eager loading collapses N+1 into one query and cuts the count the most.

All lessons in Expert