XDebug – koodarin paras ystävä PHP-nopeusoptimoinnissa

WP-palvelu.fi:n WordPressille optimoidussa ympäristössä PHP-koodi toimii hyvin sukkelaan, ilman että asiakkaan tarvitsee tehdä mitään. Jos kuitenkin haluaa tehdä lisää optimointia, joko itse tai asiantuntijoidemme toimesta, niin PHP-koodi kannattaa profiloida XDebug-työkalulla.

Xdebug kertoo tarkasti mitä PHP-koodi tekee ja kauanko minkäkin asian suorittaminen kestää. Profiloinnin avulla löytyvät pullonkaulat, jotka voi koodata uudelleen toimimaan nopeammin ja fiksummin.

Huom! Tämä artikkeli on hyvin tekninen ja tarkoitettu WordPress-kehittäjille.

14333210103_5b123ce8fc_z
Kuva: Nicola Sapiens De Mitri

XDebugin ja Webcachegrinderin asentaminen

Ensimmäinen vaihe on asentaa XDebug. Sen voi tehdä yksinkertaisesti komennolla apt-get install php5-xdebug. Jos käyttää kehitykseen WP-palvelun Vagrant-ympäristöä, on XDebug jo valmiiksi asennettuna. Tuotantosivustolle sitä ei kannata asentaa, koska XDebugin mukanaolo PHP-muistissa hidastaa sivuston toimintaa, ja aktiivinen profilointi hidastaa sivustoa jopa kymmenkertaisesti.
Asennuksen jälkeen tarkista, että tiedostosta /etc/php5/fpm/conf.d/20-xdebug.ini löytyy alla olevat rivit määriteltynä:

; Enable xdebug
zend_extension=xdebug.so
; Enable php profiling with get param XDEBUG_PROFILE=1
xdebug.profiler_output_dir=/tmp
xdebug.profiler_output_name=cachegrind.out.%t.%p
xdebug.profiler_enable_trigger=1
; Enable PHP tracing with get param XDEBUG_TRACE=1
xdebug.trace_enable_trigger=1
xdebug.trace_format=1
xdebug.show_mem_delta=1
; Enable dumping detailed info in the frontend when php fatals
xdebug.collect_vars=on
xdebug.collect_params=4
xdebug.dump_globals=on
xdebug.show_local_vars=on
xdebug.dump.SERVER=HTTP_HOST
xdebug.dump.COOKIE=*
xdebug.dump.POST=*
; Enable php debugging
xdebug.default_enable = 1
xdebug.idekey = "vagrant"
xdebug.remote_enable = 1
xdebug.remote_autostart = 0
xdebug.remote_port = 9000
xdebug.remote_handler = dbgp
xdebug.remote_log = "/data/log/xdebug.log"

Asetusten voimaansaattamiseksi käynnistä PHP uudestaan. WP-palvelu.fi:ssä se on helppoa komennolla wp-restart-php5-fpm.
Profilointimittausten visualisoimiseksi tarvitaan oma ohjelma. Palvelinympäristössä kätevä on Webgrind, jonka voi asentaa sivuston alahakemistoon näin:

cd /data/wordpress/htdocs
git clone https://github.com/alpha0010/webgrind

Webgrind löytyy tämän jälkeen osoitteesta http://esimerkki.fi/webgrind/. Jotta Webgrindin Call Graph -toiminto onnistuu, pitää järjestelmässä olla saatavilla dot-ohjelma, jonka Debian-pohjaisissa Linuxeissa saa asentamalla paketin graphviz. Huomaa, että Webgrindistä on useita versioita (engl. forks), josita alpha0010-tekijän versio on kehittynein.

Profilointi

Profilointi tapahtuu, kun verkkosivusto ladataan siten, että URL-osoitteen lopussa on profilointiparametri ?XDEBUG_PROFILE=1. Tämän voi tehdä joko nettiselaimella tai suoraan palvelimelta komentoriviltä ajamalla curl -iL -s "http://localhost/?XDEBUG_PROFILE=1". Samalla näkee, minkälaiset http-otsakkeet ja minkälaisen html-sivun palvelin palauttaa, millä voi varmistaa että curl tosiaankin latasi ja sai halutun sivun.
Joskus sivun tuottava PHP-koodi saattaa toimia eri tavalla suorituskerrasta toiseen, esimerkiksi satunnaisesti ajettavan erillisen ajastetun tehtävän takia. Tällaisen vaihtelun havaitsemiseksi on kätevää ajaa profilointia for-silmukalla useita kertoja peräkkäin siten, että curl tulostaa suoritusajan. Alla olevassa esimerkissä etusivun profilointisuoritus kestää normaalisti noin 11 sekuntia, mutta yksi 13 sekunnin poikkeama löytyy:

$ for i in {1..5}; do curl -IL -w "%{time_total}\n" -o /dev/null -s "http://localhost/?XDEBUG_PROFILE=1"; done
11,631
13,346
11,723
11,350
11,813

Profilointi on raskasta ja siksi sivu latautuu noin 10x hitaammin kuin normaalisti. Profilointitallenteet ovat yleensä 50-100 megatavun kokoisia tiedostoja, eli hyvin isoja. Mitä isompi profilointitallenne, sitä enemmän funktioita koodi on kutsunut. Tulokset ilmestyvät palvelimelle hakemistoon /tmp:

/tmp$ ll -trh
50M tammi 25 11:42 cachegrind.out.1453714919.4838
72M tammi 25 11:42 cachegrind.out.1453714923.4816
49M tammi 25 11:42 cachegrind.out.1453714932.4838
Webgrind
Webgrind ja suodatus
Webgrind call graph

Tiedostot voi ladata omalle koneelle esimerkiksi Kcachegrind-ohjelmalla analysoitavaksi. Niitä voi myös tarkastella suoraan palvelimelta Webgrindin avulla, joka näyttää pudotusvalikossa listana löydetyt profilointitallenteet. Asetuksia säätämällä voi valita, näkyvätkö kaikki funktiot (potentiaalisesti tuhansia) vai vain esimerkiksi 90% eniten aikaa käyttävistä funktioista.

Funktioluettelon voi lajitella kolmen mittarin mukaan: funktioiden kutsumäärä, funktioiden suoritusaika itsessään tai funktioiden kokonaissuoritusaika. Funktion nimi on klikattava linkki, josta aukeaa edelleen taulukko kaikista funktioista, joita funktio itse kutsuu suorituksensa aikana, sekä lista funktioista, jotka kutsuvat kyseistä funktiota. Nimiä klikkaamalla voi helposti porautua funktioiden ketjuun ja etsiä missä mahdollinen isoin syyllinen hitauteen on. Yksi sarakkeista on linkki suoraan kooditiedoston ja riviin jossa funktio on, jotta sitä on helppoa tarkastella kontekstissaan.
Suodattimen avulla listasta on helppo etsiä tyypillisiä epäiltyjä, kuten tietokantakyselyjä (hakusana ”query”) tai ulkoisilta palvelimilta hakuja (hakusanat esim. ”curl” ja ”load”).

Yllä olevassa esimerkissä näkyy syyllisenä hitauteen WordPressin käännöslisäosa WPML. Suosittelemmekin käyttämään sen sijasta mieluummin Polylang-lisäosaa.
Painikkeesta ’Show call graph’ avautuu erillinen ikkuna, jossa on graafi funktioista. Se visualisoi hienosti mitkä funktiot kutsuvat mitäkin funktioita ja paljonko ohjelman kokonaissuoritusajasta menee missäkin. Joskus graafin generointi on hidasta ja selaimeen tulee virheilmoitus ylittyneestä aikaviiveestä. Webgrind kuitenkin tallentaa kaikki graafit /tmp-hakemistoon svg-tiedostoina, joten jos selaimessa lataa saman kuvan uudestaan tulee se seuraavalla kerralla heti ilman mitään viivettä.

Optimointi koodaamalla

Xdebug ei itsessään nopeuta mitään, vaan se paljastaa pullonkaulat koodista. Varsinainen korjaus pitää tehdä muokkaamalla koodia: poistamalla turha osa, yksinkertaistamalla tai harventamalla silmukkaa, korvaamalla tietokantahakuja transienteillä ynnä muuta. Koodimuutosten jälkeen tulee mittauksilla luonnollisesti varmistaa, että muutos oli oikeaan suuntaan.
Profilointisession jälkeen tulee myös muistaa poistaa Xdebug käytöstä, jotta se ei ole hidastamassa turhaan. Tietoturvasyistä myös koko webgrind-hakemisto kannattaa poistaa, kun sitä ei tarvita enää.

Kaipaako sivustosi nopeusoptimointia?

Kysy lisää WP-palvelun asiantuntijoilta! Ota yhteyttä: wp-palvelu.fi/ota-yhteytta/

Comments

2 vastausta artikkeliin “XDebug – koodarin paras ystävä PHP-nopeusoptimoinnissa”

  1. […] PHP:n nopeuden varmistamiseksi asiakkaille on myös tarjolla Seravon kehitysympäristössä XDebug-profilointityökalu ja tuotantosivustoille Tideways-palveluun valmis […]

  2. […] Syksyn toinen iso panostus on lahden takana Tukholmassa järjestettävä WordCamp Stockholm, jossa on mahtava mahdollisuus päästä pyörimään Ruotsin kovimpien WordPress-tekijöiden piiriin. Pohjoismaisen hosting- ja ylläpitoratkaisun vastaanotto on ollut länsinaapurissa sangen positiivinen, sillä WP-palvelun kaltaista paikallista toimijaa ei ole toistaiseksi ollut tarjolla. Sponsoripisteen lisäksi Seravo on taas tyrkyllä myös puhujanpöntössä, kun Otto avaa testattujen päivitysten toimintaa. Toisena tapahtumapäivänä on workshopissamme tarjolla vinkkejä sivuston suorituskyvyn parantamiseen XDebugin ja PHP-profiloinnin avulla. Samaisia vinkkejähän olemme jakaneet aiemmin myös blogin puolella. […]