WordPress on suunniteltu klassiseen HTTP-malliin: pyyntö sisään, sivu ulos, prosessi kuolee. Tässä mallissa muistinhallinta on yksinkertaista, koska PHP-prosessi vapauttaa kaiken muistin automaattisesti pyynnön lopussa. Kun siirrytään pitkäkestoisiin pyyntöihin – esimerkiksi import-skripteihin, REST-looppeihin tai CLI-ajoihin – tämä oletus hajoaa. Silloin PHP:n garbage collection (GC) alkaa vaikuttaa konkreettisesti suorituskykyyn ja vakauteen.
Tämä on yksi niistä aiheista, jotka eivät näy pienissä sivustoissa lainkaan, mutta muuttuvat todellisiksi ongelmiksi, kun WordPressiä käytetään data-intensiivisiin tehtäviin.
Mitä PHP:n garbage collection tekee
Garbage collection on mekanismi, joka vapauttaa muistia, kun olioita ei enää käytetä. PHP käyttää pääasiassa:
– viittauslaskentaa (reference counting)
– syklisten viittausten GC:tä
Normaalissa WordPress-pyynnössä GC:n rooli on pieni, koska prosessi päättyy nopeasti. Pitkäkestoisessa skriptissä sama prosessi voi elää:
– minuutteja
– tunteja
– joskus päiviä (worker-prosessit)
Tällöin muistivuodot ja viittausketjut alkavat kasautua.
Missä pitkäkestoisia pyyntöjä esiintyy WordPressissä
WP-CLI-ajot
– massiiviset importit
– käyttäjämigraatiot
– hakemiston läpikäynti
– metadatan korjaukset
REST- ja cron-loopit
– ulkoisen API:n synkronointi
– suurten tietomäärien käsittely
– queue-tyyppiset prosessit
Custom workerit
– jatkuvasti pyörivät PHP-prosessit
– message queue -kuluttajat
– taustaprosessit ilman prosessin restarttia
Näissä ympäristöissä GC:n käyttäytyminen alkaa vaikuttaa suoraan muistinkulutukseen.
Yleisin ongelma: muistinkulutuksen kasvu silmukoissa
Tyypillinen WordPress-skripti:
– hakee 1000 postausta
– käsittelee ne silmukassa
– tekee metamuutoksia
– jatkaa seuraavaan erään
Jos objektit jäävät viittausketjuihin, muistia ei vapauteta. Tämä johtuu usein:
– globaalien muuttujien käytöstä
– hookien sisäisistä viittauksista
– WP_Query-olioiden säilymisestä muistissa
– välimuistikerroksista
Tuloksena muistinkulutus kasvaa tasaisesti, vaikka käsiteltävä data pysyy samana.
WordPressin rakenteelliset syyt muistiongelmiin
WordPress käyttää:
– globaaleja muuttujia
– hook-järjestelmää
– staattisia välimuisteja
– singleton-tyyppisiä luokkia
Nämä ovat käteviä lyhyissä pyynnöissä, mutta pitkäkestoisissa prosesseissa ne:
– keräävät objekteja muistipinoon
– estävät GC:tä vapauttamasta dataa
– aiheuttavat hitaasti kasvavan muistivuodon
Tämä ei ole bugi yksittäisessä funktiossa, vaan seurausta arkkitehtuurista, joka olettaa lyhyen elinkaaren.
Object cache ja GC
Kun käytössä on:
– Redis
– Memcached
– persistent object cache
tilanne monimutkaistuu.
Vaikka data siirtyy ulkoiseen cacheen, PHP-prosessi:
– pitää viittauksia cache-objekteihin
– säilyttää välimuistit muistissa
– kasvattaa muistijalanjälkeä silmukoissa
Ilman cache-flushia tai objektien purkua GC ei vapauta muistia tehokkaasti.
Oireet käytännössä
Pitkäkestoisessa WordPress-skriptissä näkyy usein:
– tasaisesti nouseva memory usage
– GC:n aiheuttamat CPU-piikit
– skriptin hidastuminen ajan myötä
– lopulta memory limit -virhe
Tämä voi tapahtua, vaikka käsiteltävä datamäärä ei kasva lainkaan.
Mitä GC tekee suorituskyvylle
Kun GC aktivoituu:
– se skannaa viittausketjuja
– etsii syklisiä viittauksia
– vapauttaa muistia
Tämä ei ole ilmaista. GC-sykli voi:
– aiheuttaa CPU-piikkejä
– hidastaa silmukoita
– tehdä suoritusajasta epätasaisen
Pitkässä skriptissä GC voi aktivoitua satoja kertoja.
Paremmat käytännöt pitkäkestoisissa WordPress-prosesseissa
Käsittele data erissä
– hae rajattu määrä rivejä
– käsittele ne
– vapauta objektit
– jatka seuraavaan erään
Vapauta viittaukset manuaalisesti
Silmun lopussa:
– tyhjennä muuttujat
– pura WP_Query-oliot
– vapauta suuret taulukot
Tämä auttaa GC:tä toimimaan tehokkaammin.
Tyhjennä object cache säännöllisesti
Pitkissä ajoissa:
– cache täyttyy
– muistinkulutus kasvaa
Säännöllinen cache-reset pitää muistinkulutuksen vakaana.
Restarttaa prosessi tarvittaessa
Monissa tapauksissa yksinkertaisin ratkaisu on:
– aja skripti erissä
– anna prosessin kuolla
– käynnistä uusi prosessi
Tämä on käytännössä “brutaali mutta toimiva” GC-strategia.
Ylläpidon näkökulma
Pitkäkestoiset WordPress-prosessit eivät ole WordPressin luonnollinen elinympäristö. Se on kuin akvaariokala, joka yritetään opettaa kiipeämään puita. Se voi onnistua hetken, mutta jossain vaiheessa fysiikka muistuttaa olemassaolostaan.
Kun GC-ongelmat otetaan huomioon:
– importit pysyvät vakaina
– workerit eivät kaadu
– muistinkulutus pysyy ennustettavana
Yhteenveto
PHP:n garbage collection on lähes näkymätön tekijä normaalissa WordPress-pyynnössä, mutta pitkäkestoisissa prosesseissa siitä tulee keskeinen suorituskyky- ja vakaustekijä.
WordPressin arkkitehtuuri:
– olettaa lyhyen pyynnön elinkaaren
– käyttää globaaleja rakenteita
– ei vapauta muistia aktiivisesti
Tämän seurauksena pitkäkestoiset skriptit:
– keräävät muistia
– aktivoivat GC-syklejä
– hidastuvat ajan myötä
Kun data käsitellään erissä, viittaukset vapautetaan ja prosessit restartataan tarvittaessa, WordPress toimii myös pitkäkestoisissa ajoissa ennustettavasti.
