Optimalizace výkonu PHP aplikací: caching a konfigurace

Proč optimalizovat výkon PHP aplikací

Výkon PHP aplikací výrazně ovlivňuje uživatelskou zkušenost, náklady na infrastrukturu i obchodní výsledky. Moderní PHP ve verzi 8.x přináší JIT kompilaci, vylepšení jádra a rozsáhlý ekosystém nástrojů pro optimalizaci. Cílem je dosáhnout nízké latence, vysoké propustnosti a stabilního chování pod zátěží s ohledem na bezpečnost a udržovatelnost kódu.

Strategie: měřit → analyzovat → optimalizovat

  • Měření: APM nástroje (OpenTelemetry, New Relic, Datadog), metriky z php-fpm status, logy Nginx/Apache (p95/p99), business KPI.
  • Profilace: produkčně bezpečné profilery (Blackfire, Tideways), pro vývoj Xdebug (mimo produkci), sampling vs. tracing.
  • Testování: load/stresové testy (k6, JMeter, Gatling, wrk), performance budgety v CI/CD, regresní testy.

Upgrade na moderní PHP 8.x

  • Výkon jádra: významná zlepšení v OPcache, garbage collection a optimalizaci bytecode.
  • JIT: užitečné pro čistě CPU-bound úlohy; u typické I/O webové zátěže efekt omezený – měřte pro konkrétní workflow.
  • Nové funkce: typové deklarace, readonly vlastnosti, fibers, vylepšená podpora json, optimalizované operace nad array.

OPcache: základní pilíř výkonu

  • Bytecode cache: eliminuje opakovanou kompilaci PHP skriptů, snižuje latenci a zatížení CPU.
  • Doporučené nastavení (pro produkci):
    • opcache.enable=1, opcache.enable_cli=0 (případně 1 pro dlouhodobě běžící CLI služby).
    • opcache.validate_timestamps=0 a řízený opcache reset při vydání nové verze (immutable buildy).
    • opcache.memory_consumption 256–1024 MB podle velikosti kódu, opcache.interned_strings_buffer 16–128 MB.
    • opcache.max_accelerated_files podle počtu skriptů (např. 20 000–100 000).
    • opcache.preload a opcache.preload_user pro preload často využívaných tříd a funkcí.
  • Realpath cache: nastavit realpath_cache_size na 256 kB–4 MB, realpath_cache_ttl na 300 a více sekund pro minimalizaci volání stat().

Composer a autoloading

  • Optimalizace autoloaderu: použití composer dump-autoload -o (classmap authoritative) pro minimalizaci diskových I/O.
  • Redukce závislostí: provést audit balíčků, nahradit těžké knihovny lehčími alternativami, odstranit nepoužívané.
  • PSR-4 mapování přizpůsobit struktuře kódu; vyhnout se příliš hlubokým adresářovým stromům.

PHP-FPM: ladění procesního manažera

  • Model: FPM spouští worker pro každý požadavek; cílem je nastavit optimální počet workerů tak, aby nedocházelo k swapování.
  • Klíčové parametry: pm = dynamic|ondemand, pm.max_children, pm.max_requests, pm.process_idle_timeout.
  • Postup: změřit paměť (RSS) jednoho workera při špičce → spočítat max_children ≈ (RAM - rezerva) / RSS.
  • Slowlog: nastavit request_slowlog_timeout a slowlog pro záznam stacktrace blokujících požadavků.

Webový server a HTTP vrstva

  • Nginx + FPM: používat malé a rychlé fastcgi_buffers, správně nastavit fastcgi_read_timeout, vyvarovat se neodůvodněně velkému client_max_body_size.
  • Komprese: Gzip nebo Brotli pro textové assety; na PHP odpovědích komprimovat na reverzní proxy, ne v PHP.
  • Cache: pracovat s Cache-Control, ETag, Last-Modified; u API volat podle idempotence a frekvence změn.
  • fastcgi_cache pro plně cacheovatelné stránky (anonymní obsah) s invalidací pomocí klíčů.

Databáze: nejčastější úzké hrdlo

  • Indexy: pravidelný audit pomalých dotazů, přidání kompozitních indexů dle přístupových vzorů.
  • N+1 problém: eliminovat eager/fetch joiny, používat batchování dotazů, přenášet data v jedné dávce.
  • ORM: omezit hydrataci, selektivní výběr sloupců, využívat 2nd level cache (Redis/Memcached), vyhnout se nákladným transformacím v PHP.
  • Připojení: používat persistentní spojení v PDO uvážlivě; u FPM může dojít k neefektivnímu držení připojení.
  • Read replicas: oddělit čtení a zápis, zajistit idempotenci a konzistenci (router citlivý na zpoždění replik).

Cache vrstvy a serializace

  • APCu: in-process cache pro výpočty, konfiguraci a malé lookupy (pamatovat na invalidaci při deployích).
  • Redis/Memcached: sdílená cache pro session, výsledky dotazů, fragmenty renderu; používat TTL a namespací.
  • Serializer: využívat igbinary nebo msgpack pro snížení datového objemu i CPU oproti nativní serializaci.
  • HTTP cache: využívat reverzní proxy (Varnish/Nginx) pro celé stránky, ESI pro fragmenty.

Sessions a souběh

  • Locking: defaultní file-based session zablokuje požadavky; po načtení session volat session_write_close().
  • Úložiště: Redis s lockingem a krátkým TTL; vyhnout se sdílení session mezi doménami, pokud to není nezbytné.

Asynchronní zpracování a škálování

  • Fronty: dlouhé operace přes job queue (RabbitMQ, Redis, SQS, Beanstalkd), event-driven architektura.
  • Dlouho běžící runtime: Swoole, AMPHP, ReactPHP, RoadRunner, Laravel Octane – snižují režii FPM, vyžadují pečlivou správu stavů.
  • Offloading: generování PDF, obrázků a exportů mimo webové workery (workers, serverless).

Optimalizace kódu a datových struktur

  • Minimální alokace: preferovat foreach před array_map pro lepší čitelnost a výkon; vyhýbat se zbytečným kopiím polí.
  • Řetězce: používat prořazení řetězců operátorem .= s rezervou bufferu nebo implode; minimalizovat použití regulárních výrazů, preferovat funkce typu strpos.
  • JSON: json_encode používat s volbami JSON_UNESCAPED_UNICODE, JSON_INVALID_UTF8_SUBSTITUTE, vyhnout se přenosu nadbytečných polí.
  • Výpočty: pro velká čísla preferovat rozšíření ext-gmp před funkcemi bc*.
  • Collections: u rozsáhlých datasetů využívat generátory (yield) a iterátory místo načítání celých dat do paměti.

Šablonování a rendering

  • Cache šablon: u Twig, Latte, Blade aktivovat kompilaci a cache, minimalizovat dynamiku v šablonách.
  • Fragment cache: cachovat části stránky s invalidací na základě klíčů (uživatel, jazyk, verze dat).

Bez I/O navíc: souborový systém a sítě

  • Minimalizace stat(): používat absolutní cesty, realpath cache, vypnout nepřiměřené restrikce open_basedir, pokud zpomalují.
  • HTTP klient: opakované využití TCP/TLS spojení (pooling v Guzzle přes Curl handler), nastavit timeouts a circuit breakers.
  • Externí služby: využívat bulk operace, dávkové API požadavky, navrhovat idempotentní interakce.

Bezpečnost vs. výkon

  • Zakázat Xdebug v produkci, nastavit assert.active=0, deaktivovat zend.assertions nad 0.
  • expose_php=0, správné nastavení session.cookie_secure, SameSite a HTTPOnly bez dopadu na výkon.
  • Rate limiting aplikovat na reverse proxy, ne v PHP, tím se sníží zatížení CPU.

Konfigurace runtime a OS

  • Huge pages pro OPcache (pokud je stabilní), pinning CPU nasazovat po pečlivém testování.
  • Disk: používat SSD/NVMe pro logy a dočasná data, implementovat rotaci logů, vyhýbat se synchronním zápisům během požadavku.
  • Kontejnerizace: kompilace závislostí v době buildu, immutable artefakty, warmup OPcache při startu kontejneru.

Monitoring, alerting a observabilita

  • Metriky: latence (p50/p95/p99), propustnost (RPS), chybovost, saturace zdrojů (CPU, paměť, I/O), délka fronty FPM.
  • Tracery: distribuované traceování (OpenTelemetry) pro web → PHP → DB → cache.
  • Logy: strukturované (JSON), korelace s trace-id, sampling při klidových stavech, plné logy při incidentech.

Framework-specifické poznámky

  • Symfony: produkční cache, opcache.preload, composer dump-env prod, vypnout debug bundle, HTTP cache s HttpCache nebo CDN.
  • Laravel: config:cache, route:cache, view:cache, Horizon pro queue, Octane pro dlouho běžící runtime.
  • Nette: produkční režim, cache šablon Latte, dump DI kontejneru a warmup OPcache.
  • Doctrine: cache dotazů a výsledků, omezit režimy hydratace, explicitně vybírat sloupce v SELECT.

Tabulka: rychlá mapovací příručka optimalizací

Symptom Možná příčina Doporučený krok
Vysoké CPU, nízký RPS Chybějící OPcache, náročné šablony Zapnout OPcache, cache šablon, profilace
Pomalé p95/p99 N+1 dotazy, I/O na externí API Batchování, cache, timeouty a retry s backoff
Fronta ve FPM Nízký max_children, vysoké RSS Navýšit RAM/optimalizovat kód, přepočítat max_children
Variabilní latence GC, cold start, reset OPcache Warmup po deployi, stabilní strategie nasazení
Blokující požadavky Session lock, file I/O session_write_close(), přesun session do Redis

Release management a spolehlivost

  • Blue/Green a Canary nasazení s metrikami a automatickým rollbackem.
  • Immutable artefakty: žádné změny na serveru po deployi; warmup cache a OPcache.
  • Feature flagy: řízení zatížení a postupné zapínání náročných funkcí.

Checklist: minimální produkční baseline

  • Zapnutý a správně dimenzovaný OPcache včetně realpath cache.
  • Optimalizovaný Composer autoloader a audit závislostí.
  • Vyladěný PHP-FPM (pm.max_children, slowlog, status page).
  • HTTP cache hlavičky, komprese na reverzní proxy, fastcgi_cache pro anonymní obsah.
  • Databázové indexy, odstranění N+1, cache opakovaných dotazů.
  • APCu/Redis pro runtime cache a session bez locků.
  • Monitoring p95/p99, APM trasování a alerty, load test v CI.

Závěr

Optimalizace výkonu PHP je kontinuální disciplína kombinující změny v architektuře, konfiguraci runtime, databázové vrstvě i kódu. Systematickým měřením, profilací a automatizovaným testováním dosáhnete stabilní latence, lepší škálovatelnosti a nižších nákladů. Moderní PHP 8.x s OPcache, pečlivě vyladěným F