Výkon PHP aplikací

Proč optimalizovat výkon PHP aplikací

Výkon PHP aplikací rozhoduje o uživatelské zkušenosti, infrastrukturních nákladech i obchodních výsledcích. Moderní PHP (8.x) přináší JIT, vylepšení engine a rozsáhlý ekosystém optimalizačních nástrojů. Cílem je dosáhnout nízké latence, vysoké propustnosti a stabilního chování pod zátěží při zachování bezpečnosti a udržovatelnosti kódu.

Strategie: měřit → analyzovat → optimalizovat

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

Upgrade na moderní PHP 8.x

  • Výkon jádra: výrazná zlepšení v opcache, garbage collection a optimalizaci bytecodu.
  • JIT: pro čistě CPU-bound úlohy může pomoci; u typické I/O webové zátěže je efekt omezený. Měřte podle konkrétního workloadu.
  • Nové funkce: typy, readonly, fibers, lepší json, optimalizované array operace.

OPcache: základní kámen výkonu

  • Bytecode cache: eliminuje opakovanou kompilaci skriptů; snižuje latenci a zatížení CPU.
  • Doporučené nastavení (produkce):
    • 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 releasu (immutable buildy).
    • opcache.memory_consumption 256–1024 MB dle rozsahu 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 používaných tříd a funkcí.
  • Realpath cache: realpath_cache_size 256k–4M, realpath_cache_ttl 300+ pro minimalizaci volání stat().

Composer a autoloading

  • Optimalizace autoloaderu: composer dump-autoload -o (classmap authoritative), minimalizuje diskovou I/O.
  • Redukce závislostí: audit balíčků, nahrazení těžkých knihoven lehčími alternativami, odstranění nepoužívaných.
  • PSR-4 mapování přizpůsobit struktuře projektu; vyhnout se hlubokým stromům složek.

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

  • Model: FPM vytváří workera pro každý požadavek; cílem je optimální počet workerů bez nutnosti swapování.
  • Klíčové parametry: pm = dynamic|ondemand, pm.max_children, pm.max_requests, pm.process_idle_timeout.
  • Postup: změřit RSS jednoho workera při špičce → vypočítat max_children ≈ (RAM - rezerva) / RSS.
  • Slowlog: request_slowlog_timeout a slowlog pro získání stacktrace blokujících volání.

Webový server a HTTP vrstva

  • Nginx + FPM: udržujte malé a rychlé fastcgi_buffers, správně nastavte fastcgi_read_timeout, vyhněte se zbytečně vysokým hodnotám client_max_body_size.
  • Komprese: Gzip/Brotli pro textové assety; na PHP odpovědích aplikujte kompresi na reverzní proxy, nikoli v PHP.
  • Cache: Cache-Control, ETag, Last-Modified; u API zvažte podle idempotence a frekvence změn.
  • fastcgi_cache pro plně cacheovatelné stránky (anonymní obsah), invalidace přes odpovídající klíče.

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

  • Indexy: pravidelný audit pomalých dotazů, přidání kompozitních indexů podle přístupových vzorů.
  • N+1 problém: eliminovat pomocí eager/fetch joinů, batchování dotazů a využití datových přenosů v jedné dávce.
  • ORM: omezit hydration, selektivní výběr sloupců, úroveň cache 2nd level (Redis/Memcached), vyhnout se náročným transformacím v PHP.
  • Připojení: opatrně používat persistentní připojení v PDO; u FPM může dojít k držení připojení bez užitku.
  • Read replicas: oddělení čtecích a zápisových operací, zajištění idempotence a konzistence (lag-aware router).

Cache vrstvy a serializace

  • APCu: in-proc cache pro výsledky výpočtů, konfiguraci a malé lookupy (pozor na invalidaci při deployi).
  • Redis/Memcached: sdílená cache pro session, výsledky dotazů, fragmenty renderu; používejte TTL a namespacy.
  • Serializer: igbinary nebo msgpack snižují objem a nároky na CPU ve srovnání s nativní serializací.
  • HTTP cache: reverse proxy (Varnish/Nginx) pro celé stránky, ESI pro fragmenty.

Sessions a souběh

  • Locking: výchozí file-based session uzamyká požadavky; po přečtení volat session_write_close().
  • Úložiště: Redis s locking a krátkým TTL; vyhnout se sdílení session napříč 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 – omezuje overhead FPM, vyžaduje pečlivou správu stavu.
  • Offloading: generování PDF, obrázků a exportů mimo web worker (workers, serverless řešení).

Optimalizace kódu a datových struktur

  • Minimální alokace: preferovat foreach před array_map pro čitelnost i výkon; vyhnout se zbytečným kopiím polí.
  • Řetězce: používat .= s rezervací bufferu nebo implode; minimalizovat regulární výrazy, preferovat strpos apod.
  • JSON: json_encode s vhodnými volbami (JSON_UNESCAPED_UNICODE, JSON_INVALID_UTF8_SUBSTITUTE), nepřenášet nadbytečná pole.
  • Výpočty: u velkých čísel preferovat ext-gmp před bc* funkcemi.
  • Collections: u velkých datasetů využít generátory (yield) a iterátory místo načítání kompletních dat do paměti.

Šablonování a rendering

  • Cache šablon: Twig/Latte/Blade – zapnout 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 nepotřebné open_basedir restrikce, pokud zpomalují.
  • HTTP klient: reuse TCP/TLS (pooling v Guzzle přes Curl handler), nastavovat timeouts a circuit breakers.
  • Externí služby: používat bulk operace, batch API, navrhovat idempotentní požadavky.

Bezpečnost vs. výkon

  • Zakázat Xdebug v produkci, assert.active=0, vypnout zend.assertions > 0.
  • expose_php=0, správné session.cookie_secure, SameSite a HTTPOnly bez negativního dopadu na výkon.
  • Rate limiting na reverse proxy, nikoli v PHP, což snižuje CPU zátěž.

Konfigurace runtime a OS

  • Huge pages pro OPcache (pokud je stabilní), pinning CPU pouze po důkladném testování.
  • Disk: SSD/NVMe pro logy a dočasná data, rotace logů, žádné synchronní zápisy během requestu.
  • Kontejnerizace: build-time kompilace závislostí, immutable artefakty, warmup opcache při startu kontejneru.

Monitoring, alerting a observabilita

  • Metriky: latence (p50/p95/p99), propustnost (RPS), chybovost, zatížení (CPU, paměť, I/O), délka fronty FPM.
  • Traces: distribuované trasování (OpenTelemetry) přes web → PHP → DB → cache.
  • Logy: strukturované (JSON), korelace s trace-id, sampling v normálních časech a plné logy při incidentech.

Framework-specifické poznámky

  • Symfony: prod 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 fronty, Octane pro dlouho běžící runtime.
  • Nette: production mode, cache šablon Latte, dump DI kontejneru a opcache warmup.
  • Doctrine: query cache a result cache, omezit hydratační režimy, explicitní výběr sloupců (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 volání na externí API Batchování dotazů, cache, nastavení timeoutů 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 Garbage collection, cold start, reset opcache Warmup po deployi, stabilní strategie releasu
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.
  • Imutabilní artefakty: žádné změny na serveru po releasu; 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 stránka).
  • HTTP cache hlavičky, komprese na reverzní proxy, fastcgi_cache pro anonymní obsah.
  • DB indexy, odstraněné N+1, cachování opakovaných dotazů.
  • APCu/Redis pro runtime cache a session bez blokování.
  • Monitoring p95/p99, APM trace a alerty, load testy 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 získáte stabilní latenci, lepší škálování a nižší náklady. Moderní PHP 8.x s OPcache, pečlivě vyladěným FPM, využitím cache vrstev a promyšlenou prací s I/O poskytuje excelentní základ pro rychlé a spolehlivé webové aplikace.