Profilování PHP skriptů pomocí XHProf

Profilování, tedy sledování doby běhu různých části programu, neodmyslitelně patří k vývoji každé aplikace. Umožní nám zjistit úzká místa a optimalizovat pouze ta. Jak říká známá poučka Donalda Knutha: „Předčasná optimalizace je kořen všeho zla“. Článek nám představí profilovací nástroj pro PHP.

Donedávna byly dva způsoby, jak profilovat aplikace napsané v jazyce PHP: „Ruční“, tedy přímo v kódu funkce na jejím začátku a konci zavolat microtime a délku běhu spočítat jako rozdíl vrácených časů, což není moc efektivní, jednak kvůli psaní zbytečného kódu, ale také kvůli jeho vykonávání v ostrém provozu (podobný způsob používá například MediaWiki – systém pohánějící Wikipedii). Druhý, jednoznačně lepší, způsob byl v použití univerzálního debugovacího rozšíření Xdebug, který jako jednu z mnoha funkcí nabízí i profiler.

Na začátku roku 2009 se objevil třetí způsob, když vývojáři Facebooku zveřejnili rozšíření XHProf pro profilování PHP skriptů pod open-source licencí Apache 2.0. Toto rozšíření, na rozdíl od Xdebugu, přináší několik zajímavých vlastností: vyšší rychlost, zaznamenávání využití paměti a měření přesného procesorového času. Ovšem nelze jej provozovat na operačním systému Windows (podporovány jsou pouze Linux, FreeBSD a Mac OS X a je také omezen na instrukční sadu x86 a x86–64), zatím neexistuje žádná desktopová aplikace pro zpracování výsledků a nezaznamenává dobu vykonávání jednotlivých volání funkce, ale pouze jejich součet.

Instalace a konfigurace

Protože u většiny linuxových distribucí neexistuje balíček s tímto rozšířením, je nutné provést kompilaci. Instalace pomocí pecl repozitáře nefunguje pravděpodobně kvůli špatné struktuře archivu s rozšířením. Samotná kompilace není nijak složitá, stačí stáhnout archiv s rozšířením, rozbalit jej a spustit následující posloupnost příkazů:

cd <cesta ke složce s rozšířením>/extension/
phpize
./configure
make
make install

Po úspěšném dokončení instalace je ještě nutné do php.ini přidat následující řádky zapínající rozšíření a nastavující složku, do které se budou ukládat výsledky profilování (v tomto případě je to složka  /tmp/xhprof).

[xhprof]
extension=xhprof.so
xhprof.output_dir=/tmp/xhprof

Správně nainstalované rozšíření se objeví ve výpisu funkce phpinfo().

Použití

Profilování se zapne jednoduchým zavoláním funkce xhprof_enable() nebo xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY), čímž získáme i údaje o procesorovém čase a využití paměti.

Výsledky poté získáme pomocí funkce xhprof_disable(), která vrací pole všech volaných funkcí spolu s všemi zjištěnými údaji. Jednotlivé položky a jejich význam je popsán v dokumentaci k rozšíření. S tímto polem můžeme dále pracovat, například si jej nechat vypsat a ručně projít, ovšem lepší je využít integrovaného grafického webové rozhraní, které nám analýzu získaných dat velmi usnadní.

Ze složky s rozšířením zkopírujeme složky xhprof_lib a xhprof_html například přímo do kořene webového serveru (v tomto případě /usr/local/apache2/htdocs/) a na konec analyzovaného souboru vložíme následující kód:

// Získání výsledků profilování
$xhprofData = xhprof_disable();
$xhprofLibFolder = "/usr/local/apache2/htdocs/xhprof_lib";
include_once $xhprofLibFolder . "/utils/xhprof_lib.php";
include_once $xhprofLibFolder . "/utils/xhprof_runs.php";
$xhprofRuns = new XHProfRuns_Default();
// Uložení do souboru
$xhprofRunId = $xhprofRuns->save_run($xhprofData, "xhprof_foo");
// Vypsání odkazu pro zobrazení rozhraní profileru
echo "<a href='http://localhost/xhprof_html/index.php?run=$xhprofRunId&source=xhprof_foo'>Výstup profileru</a>";

Funkce save_run ve třídě XHProfRuns_Default se postará o uložení souboru s výsledkem profilování do složky, kterou jsme určili v konfiguračním souboru php.ini, řetězec xhprof_foo určuje jmenný prostor uložených dat.

Tento způsob zobrazení odkazu funguje pouze u HTML souborů, jeho vložení například do XML, JSON nebo dokonce obrázku by způsobil jejich nefunkčnost. V tom případě je potřeba identifikátor $xhprofRunId uložit například do souboru a rozhraní profileru spustit zadáním správné adresy do prohlížeče.

Kliknutí na odkaz se zobrazí jednoduché a trochu nepěkné rozhraní profileru.

Význam jednotlivých sloupců je následující:

  • Calls – počet volání funkce.
  • Inclusive – čas strávený vykonávám funkce a všech funkcí z ní volaných.
  • Exclusive – čas strávený pouze daný funkce.
  • Wall time – doba trvání.
  • CPU time (pouze v případě zapnutého XHPROF_FLAGS_CPU) – je započítán pouze čas vykonávání na procesoru. Výsledky se tedy nebudou příliš lišit na zatíženém a nezatíženém systému, ale nezapočítávají čekání na databázi či diskové operace.
  • Memory Usage (pouze v případě zapnutého XHPROF_FLAGS_MEMORY) – změna využití paměti před a po vykonání funkce. Rozdíl ve špičce využité paměti je zobrazen ve sloupci Peak Memory Usage.

K zobrazení rozdílu mezi dvěma spuštěními skriptu (například zobrazení rozdílu mezi neoptimalizovanou a optimalizovanou verzí) upravíme adresu URL:

http://localhost/xhprof_html/index.php?run1=<prvni_id>&run2=<druhe_id>&source=<jmenný_prostor>

Lze také zobrazovat součet několika různých výsledků profilování a to znovu úpravou adresy:

http://localhost/xhprof_html/index.php?run=<prvni_id>,<druhe_id>,<treti_id>&source=<jmenný_prostor>

Potěší možnost vygenerování grafu, který zobrazuje závislosti mezi jednotlivými funkcemi a dobu jejich vykonávání. Tato funkce vyžaduje nainstalovaný open-source vizualizační software Graphviz, konkrétně aplikaci dots.

Nasazení v ostrém provozu

Toto rozšíření lze, díky jeho nízké režii, použít i na profilování v ostrém provozu, na rozdíl od Xdebugu. Pro snížení náročnosti je vhodné vypnout mód XHPROF_FLAGS_CPU. Další snížení je možné náhodným profilováním například každého stého požadavku.

Samozřejmě nelze zobrazovat odkaz na profiler běžnému uživateli přímo na stránce, identifikátor je nutné ukládat do souboru nebo databáze. Hotové řešení nabízí XHGui, které do databáze ukládá komprimovaně i výsledky profilování a umožňuje jejich snadnou správu (například zobrazit nejnáročnější požadavky či požadavky využívající nejvíc paměti) a zobrazení grafů.

Shrnutí

V článku jsme si představili efektivní nástroj pro profilování skriptů v PHP, který pomůže nalézt slabá místa vaší aplikace a zaměřit tak při optimalizaci pozornost tam, kde opravdu vzniká problém, ne tam, kde si myslíme, že by mohl být. Profiler by měl být v základní výbavě každého, kdo to s aplikacemi v PHP myslí vážně.

Studuje Fakultu elektrotechniky a komunikačních technologií VUT v Brně a na volné noze programuje efektivní aplikace převážně v jazyce PHP.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 5

Přehled komentářů

Michal Wiglasz Re: Profilování PHP skriptů pomocí XHProf
sidik Moc pěkné
Michal Re: Moc pěkné
sidik Re: Moc pěkné
vetesnik Super, bude se hodit
Zdroj: https://www.zdrojak.cz/?p=3411