Přejít k navigační liště

Zdroják » PHP » Profilování PHP skriptů pomocí XHProf

Profilování PHP skriptů pomocí XHProf

Články PHP, Různé

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ě.

Komentáře

Subscribe
Upozornit na
guest
5 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Michal Wiglasz

Jakožto příznivce Windows bych se rád zeptal – neplánujete zařadit i nějaký článek o profilování pomocí xdebug?

sidik

Díky za článek. Hned jsem to vyzkoušel a zjistil, že nejhůř na tom je PDO :D

Michal

To je u vetsiny klasickych PHP aplikaci uplne normalni (na PDO bych to vylozene nesvadel, pujde spis o pristup k databazi obecne).

Kdyby to tak nebylo, zrejme by to znamenalo, ze mate lejky ve svem kodu :-)

sidik

PDO constructor sám zabírá 14% času. A to se volá jen jednou. Ale pořád je to strašně krátká doba. Potěšilo mě, že to mám takové rychlé :)

Oldřich Vetešník

Díky! Hodíme to na server a budeme všichni šťastnější. :)

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.