Tabulka slouží jako první orientace, nikoliv jako definitivní diagnostika. Například dlouhá odezva při vysokém provozu může vznikat ve PHP-FPM, databázi i externích službách. Bez měření jednotlivých částí požadavku není možné příčinu spolehlivě určit.
Jak změřit výkon PHP aplikace a najít skutečné úzké místo?
Než začnete upravovat kód, potřebujete vědět, které operace jsou pomalé, jak často se spouštějí a co způsobuje jejich zpoždění. Profilování umožňuje rozdělit zpracování požadavku na jednotlivé části a ukázat, kolik času zabírají databázové dotazy, samotná logika aplikace nebo komunikace s dalšími službami. Pro detailnější analýzu lze využít například Blackfire, Xdebug profiler nebo APM nástroje, které sledují výkon aplikace při běžném provozu. Důležité je rozlišovat profilování kódu od zátěžového testování. Profiler pomáhá zjistit, kde se čas spotřebovává, zatímco zátěžový test ukazuje, jak se systém chová při rostoucím počtu požadavků.
Praktický postup diagnostiky
Vyberte důležité uživatelské scénáře - U e-shopu to může být načtení produktu, filtrování, košík a dokončení objednávky. U interní aplikace například vyhledávání zákazníků, uložení formuláře nebo generování reportu.
Změřte výchozí stav - Zaznamenejte dobu odezvy, počet SQL dotazů, spotřebu paměti, počet chyb a chování při běžném i zvýšeném provozu.
Rozdělte požadavek podle zdrojů zpoždění - Porovnejte čas strávený v databázi, aplikační logice, externích voláních a čekáním na dostupný proces.
Ověřte chování při souběhu požadavků - Některé problémy nejsou při testování jedním uživatelem viditelné a projeví se až při větším zatížení.
Určete prioritu zásahů - Přednost mají problémy, které se opakují často, zasahují více uživatelů nebo ovlivňují obchodně důležité operace.
Při vyhodnocování sledujte zejména medián doby odezvy (p50) a 95. percentil (p95). Medián představuje typickou hodnotu, zatímco p95 označuje hranici, pod kterou spadá 95 % naměřených požadavků. Pomáhá tak zachytit pomalejší část provozu, kterou samotný průměr nebo medián nemusí dostatečně vystihovat. Měřte srovnatelné scénáře a nezapomínejte rozlišit první načtení od opakovaného požadavku s již připravenou cache. U databází pracujte s realistickým objemem dat. Aplikace s několika stovkami testovacích záznamů se může chovat výrazně jinak než stejný systém po několika letech provozu.
1. Používejte podporovanou verzi PHP
Novější verze PHP přinášejí opravy chyb, bezpečnostní aktualizace a průběžná vylepšení běhového prostředí. U starších aplikací proto dává smysl prověřit, zda jejich výkon a stabilitu neomezuje zastaralá verze jazyka. K říjnu 2026 jsou podporované větve PHP 8.2 až 8.5. Verze 8.2 a 8.3 již dostávají pouze bezpečnostní opravy, přičemž podpora PHP 8.2 končí 31. prosince 2026.
Aktuální stav je možné ověřit v oficiálním přehledu podporovaných verzí PHP. Aktualizace ale není jen změna čísla v konfiguraci serveru. Je potřeba prověřit kompatibilitu frameworku, knihoven a rozšíření, spustit automatizované testy a porovnat výkon před změnou a po ní. Novější PHP může přinést zrychlení, ale samo o sobě neodstraní pomalé databázové dotazy ani nevhodně navrženou aplikační logiku.
2. Aktivujte a správně nastavte OPcache
PHP při vykonávání skriptů pracuje s jejich zkompilovanou podobou, takzvaným bytecodem. Rozšíření OPcache ukládá předkompilovaný bytecode do sdílené paměti, takže jej není nutné při každém požadavku znovu připravovat. Tím omezuje opakovanou práci serveru. Při kontrole se zaměřte především na aktivaci OPcache, velikost přidělené paměti, kapacitu pro uložené skripty a chování cache při nasazení nové verze aplikace. Důležité parametry zahrnují opcache.enable, opcache.memory_consumption, opcache.max_accelerated_files a opcache.validate_timestamps.
Stav lze ověřovat například pomocí funkce opcache_get_status() v odpovídajícím běhovém prostředí. Kontrolujte využití paměti, úspěšnost zásahů do cache a případné restarty. Při nasazování změn musí být zároveň zajištěna aktualizace uloženého bytecodu, aby aplikace nepoužívala zastaralé soubory. OPcache však není náhradou databázové ani aplikační cache. Její úlohou je omezit režii vykonávání PHP skriptů, nikoliv ukládat výsledky SQL dotazů. Podrobnosti najdete v dokumentaci PHP OPcache.
3. Optimalizujte konfiguraci PHP-FPM
PHP-FPM spravuje procesy, které obsluhují PHP požadavky. Pokud se dostupné procesy vyčerpají, další požadavky musí čekat. To může výrazně prodloužit odezvu aplikace, přestože jednotlivé operace samy o sobě nejsou příliš náročné. Jedním z důležitých parametrů je pm.max_children, který určuje maximální počet procesů v příslušném poolu. Příliš nízká hodnota může vytvářet frontu požadavků, příliš vysoká naopak způsobit nedostatek paměti. Správné nastavení proto závisí na skutečné spotřebě procesů, dostupné RAM a zatížení dalších služeb.
Při diagnostice sledujte počet aktivních procesů, frontu čekajících požadavků a vytížení serveru. Užitečné mohou být také stavové informace PHP-FPM a záznamy pomalých požadavků prostřednictvím request_slowlog_timeout. Stavové a diagnostické endpointy přitom nesmějí být volně přístupné veřejnosti. Univerzální doporučení typu „nastavte 50 procesů“ není správné. Optimální konfiguraci stanovíte podle naměřené spotřeby zdrojů a následného zátěžového testu. Jednotlivé parametry popisuje oficiální dokumentace PHP-FPM.
4. Zrychlete databázové dotazy a správně používejte indexy
Databáze se často stává hlavním omezením aplikace ve chvíli, kdy naroste počet objednávek, zákazníků, položek nebo historických záznamů. Dotaz, který fungoval rychle při malém objemu dat, může později procházet podstatně větší tabulky a zdržovat načítání celé stránky. Základem je identifikovat nejpomalejší a nejčastěji spouštěné dotazy. U MySQL můžete využít slow query log a příkaz EXPLAIN, který ukazuje plán provedení SQL dotazu. Pomáhá například odhalit zbytečné procházení tabulek, neefektivní spojování dat nebo indexy, které databáze nevyužívá podle očekávání.
Praktický příklad: Administrace e-shopu filtruje objednávky podle zákazníka a řadí je od nejnovějších. Pokud databáze musí při každém požadavku procházet velké množství záznamů, může vhodně navržený složený index výrazně pomoci. Jeho podobu je však nutné určit podle skutečného SQL dotazu, dat a plánu vykonávání.
Důležité je také vědět, že větší počet indexů automaticky neznamená rychlejší databázi. Indexy spotřebovávají místo a mohou zpomalovat operace zápisu. Proto každou změnu ověřte měřením. Podrobnosti o analýze dotazů uvádí dokumentace MySQL EXPLAIN.
5. Odstraňte N+1 dotazy a nadbytečné načítání dat
N+1 problém vzniká například při načtení seznamu záznamů, kdy aplikace pro každou položku samostatně dotazuje další související informace. Na malé databázi si problému nemusíte všimnout, ale při větším počtu položek může počet SQL dotazů rychle růst.
Modelový příklad: Administrace načte 50 objednávek jedním hlavním dotazem. Pro každou objednávku pak samostatně dohledává zákazníka, platbu, dopravu a počet položek. Výsledkem je 1 + (50 × 4), tedy 201 databázových dotazů. Vhodnější načítání relací může jejich počet snížit například na několik dotazů.
Možným řešením je eager loading, vhodně navržené JOIN operace nebo hromadné načítání souvisejících dat. Konkrétní postup závisí na použitém ORM a charakteru dat. Současně je vhodné omezit přenos sloupců, které daná stránka vůbec nepotřebuje, a u rozsáhlejších seznamů zavést stránkování. U aplikací vytvořených v Laravelu bývá podobná diagnostika důležitá zejména při práci s Eloquent ORM. Frameworkové nástroje a další postupy podrobně rozebírá samostatný článek o optimalizaci Laravel aplikace.

6. Využívejte caching podle typu dat a jejich platnosti
Cache dokáže omezit opakované databázové dotazy, výpočty a generování výstupů. Největší smysl má tam, kde aplikace opakovaně používá stejná data, například u kategorií produktů, konfigurací, veřejných profilů nebo přehledových statistik. Pro aplikační cache se běžně využívají Redis nebo Memcached. APCu může posloužit pro lokální ukládání dat na úrovni konkrétního serverového prostředí. Redis bývá vhodný také pro aplikace s více instancemi, které potřebují sdílet uložené hodnoty. Výběr technologie závisí na architektuře a požadavcích na dostupnost dat.
Klíčové není jen uložení výsledku, ale také jeho správná aktualizace. Při návrhu cache je proto nutné řešit:
TTL (Time to Live) - jak dlouho může uložená hodnota zůstat platná.
Invalidaci - kdy se cache odstraní nebo obnoví po změně podkladových dat.
Oddělení dat - jak zabránit tomu, aby uživatel získal výsledek určený jinému účtu nebo firmě.
Současné požadavky - jak omezit situaci, kdy mnoho požadavků současně znovu počítá stejná data po vypršení cache.
Například katalog kategorií, který se upravuje jen příležitostně, může využívat cache s delší platností nebo obnovováním při změně dat. U skladových zásob je potřeba větší opatrnost. Zobrazenou dostupnost lze vhodně cachovat, ale před potvrzením objednávky musí systém ověřit skutečný stav zásob. Přínosná může být také precomputace, tedy předvýpočet náročných statistik mimo hlavní požadavek. Manažerský dashboard pak nemusí při každém otevření přepočítávat celou historii objednávek. Stačí načíst předem připravené agregace, pokud je pro daný účel přijatelné určité zpoždění jejich aktualizace.
7. Optimalizujte aplikační logiku a práci s pamětí
Ne všechny problémy vznikají v databázi. Náročné algoritmy, opakované transformace dat nebo zpracování příliš velkých kolekcí mohou významně zatěžovat procesor i paměť serveru. Typickým příkladem je export objednávek, při kterém aplikace nejprve načte celou databázovou kolekci do paměti a teprve potom začne vytvářet výsledný soubor. U většího množství dat může takový postup zbytečně navyšovat spotřebu RAM. Vhodnější může být dávkové načítání, postupné zpracování záznamů nebo využití generátorů.
Podobně se vyplatí ověřit, zda aplikace opakovaně neprovádí stejné výpočty, nepoužívá zbytečně složité datové struktury nebo nespojuje rozsáhlé kolekce v PHP tam, kde by databáze dokázala pracovat efektivněji. Zvyšování memory_limit však není samo o sobě optimalizací výkonu. Tento parametr pouze mění limit povolené alokace paměti. Ani časté používání unset() nepředstavuje univerzální řešení, protože PHP má vlastní mechanismy správy paměti. Smysluplnější je nejprve zjistit, které operace paměť spotřebovávají a proč.
8. Přesuňte náročné operace do front a omezte čekání na externí API
Některé úlohy uživatel nemusí dokončit během jediného HTTP požadavku. Patří mezi ně například generování rozsáhlých exportů, zpracování obrázků, vytváření reportů nebo odesílání většího množství e-mailů. Pokud tyto operace běží synchronně, uživatel čeká na jejich dokončení a požadavek po celou dobu spotřebovává serverové prostředky. Vhodným řešením mohou být fronty úloh a samostatné procesy pro jejich zpracování. Aplikace například přijme požadavek na export, zařadí úlohu do fronty a uživatele informuje, že výsledný soubor bude dostupný po dokončení.
Při návrhu je důležité ošetřit opakování neúspěšných úloh, zabránit nechtěnému duplicitnímu zpracování a sledovat délku fronty. Samotný přesun do fronty celkovou práci serveru nesníží, ale umožní lépe řídit její načasování a oddělit ji od okamžité odezvy. Samostatnou pozornost si zaslouží externí API. Pokud aplikace při otevření stránky postupně volá několik dalších systémů, může čekání na jejich odpovědi dominovat celé době požadavku. Pomoci může správné nastavení timeoutů, omezení nadbytečných volání, bezpečné ukládání opakovaně využitelných odpovědí nebo přesun operací, které není nutné dokončit okamžitě.
9. Optimalizujte HTTP odpovědi a načítání frontendu
Rychlé zpracování PHP požadavku ještě neznamená, že uživatel uvidí rychle načtenou stránku. Výslednou zkušenost ovlivňuje také velikost přenášených dat, JavaScript, CSS, obrázky a způsob vykreslování obsahu v prohlížeči. Je proto potřeba rozlišovat výkon backendu od výkonu klientské části. Metrika TTFB (Time to First Byte) zachycuje dobu do přijetí prvního bajtu odpovědi, ale může ji ovlivňovat také síť a další vrstvy infrastruktury. LCP (Largest Contentful Paint) naopak sleduje vykreslení největšího obsahového prvku ve viditelné části stránky.
Praktické optimalizace mohou zahrnovat zmenšení JSON odpovědí, vhodnou kompresi přenosu pomocí gzip nebo Brotli, ukládání statických souborů do cache prohlížeče a omezení zbytečného JavaScriptu. U obrázků pomáhají vhodné formáty, rozměry a správné načítání podle důležitosti obsahu. Pokud server vrací odpověď rychle, ale prohlížeč stále dlouho zpracovává rozsáhlé skripty, další optimalizace PHP nemusí přinést viditelné zlepšení. Rozhodující je správně identifikovat, která část procesu uživatele skutečně omezuje.
10. Nastavte průběžný monitoring výkonu
Výkon aplikace se mění s počtem uživatelů, objemem dat a novými funkcemi. Proto nestačí úspěšně dokončit jednu optimalizaci a předpokládat, že se podobné problémy už neobjeví. U provozně důležitých aplikací se vyplatí sledovat dobu odezvy hlavních endpointů, p95, chybovost, zatížení PHP-FPM, výkon databáze a stav front úloh. Monitoring by měl pomáhat rozpoznat odchylku od běžného provozu, nikoliv pouze zobrazovat velké množství technických grafů.
Praktickým řešením je nastavit upozornění na významné zhoršení výkonu a porovnávat stav po každém větším nasazení nové verze. Pokud začne zpomalovat konkrétní API endpoint nebo administrativní operace, lze problém zachytit dříve, než začne výrazně ovlivňovat provoz. U rozsáhlejších systémů je vhodné řešit tyto požadavky dlouhodobě jako součást vývoje webových aplikací, nikoliv pouze jako jednorázovou reakci na stížnosti uživatelů.
Jak ověřit, že optimalizace skutečně zrychlila aplikaci?
Úspěšná optimalizace musí být doložitelná výsledkem. Nestačí, že upravený kód vypadá přehledněji nebo že se stránka při jednom ručním testu načetla rychleji. Důležité je srovnání stejných operací při odpovídajícím objemu dat a podobné zátěži. Při vyhodnocení sledujte nejen rychlost běžného požadavku, ale také pomalejší část provozu, počet databázových dotazů a spotřebu zdrojů. Všímejte si i vedlejších efektů. Aplikace může například získat rychlejší odezvu, ale současně začít využívat více paměti nebo vracet neaktuální data.
Modelový příklad: Představme si administraci objednávek, jejíž výkon se zlepší po odstranění nadbytečných databázových dotazů a úpravě jejich načítání.