WordPress ja PHP garbage collection pitkäkestoisissa pyynnöissä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.