Skip to main content

Consum de memòria

El consum de memòria elevat en PHP és un problema crític que es produeix quan un script utilitza més memòria RAM de la disponible o permesa pel sistema. En l'àmbit d'aplicacions web, pot conduir a una inestabilitat greu del servidor i errors fatals.

Causes del Consum de Memòria Elevat en PHP 

L'ús descontrolat de memòria sol ser causat per la gestió inadequada de grans volums de dades:

  • Càrrega Massiva de Dades (Hydration): L'obtenció de milers o milions de registres d'una base de dades utilitzant mètodes que carreguen tot el resultat a la memòria de cop (per exemple, fetchAll sense limitacions) és la causa més comuna.

  • Estructures de Dades Grans i Ineficients: Mantenir grans arrays o objectes complexos a la memòria durant tota l'execució de l'script, especialment si contenen redundància.

  • Problemes amb l'Àmbit (Scope) i les Referències: L'ús de referències circulars o globals mal gestionades que impedeixen que el Recollidor d'Escombraries (Garbage Collector - GC) de PHP alliberi la memòria d'objectes que ja no s'utilitzen.

  • Fugues de Memòria (Memory Leaks): Tot i que PHP gestiona la memòria automàticament, els memory leaks poden aparèixer en closures o en usar extensions de PHP (com extensions de base de dades que no netegen bé els recursos) si no s'utilitzen correctament.

  • Serialització de Dades: Serialitzar (o desserialitzar) objectes molt grans o estats de sessió massius.


Detecció del Consum de Memòria (Mesurament)

Per diagnosticar el consum de memòria, PHP ofereix funcions natives i eines de perfilat avançades.

- Eines de Programació (Instrumentació Manual)

Les funcions natives de PHP permeten obtenir la memòria utilitzada en un moment precís de l'execució:

Funció PHP Descripció Ús Comú
memory_get_usage(true) Retorna la quantitat de memòria actualment assignada al script des del sistema (memòria real). Mesurar el consum incremental de memòria en un bloc de codi.
memory_get_peak_usage(true) Retorna la quantitat màxima de memòria assignada des que va començar l'script (pic màxim). Determinar el moment de màxima càrrega de memòria de tota la petició.

Exemple d'ús per detectar un pic de memòria:

PHP
<?php
// Mesurar l'ús de memòria abans de carregar dades
$mem_inici = memory_get_usage(true);

// 1. Càrrega massiva simulada
$grans_dades = array_fill(0, 100000, str_repeat('X', 100)); // 100k strings de 100 bytes cadascun

// 2. Mesurar el pic de memòria durant l'operació
$mem_pic = memory_get_peak_usage(true);

// 3. Alliberament de memòria (ajuda al GC)
unset($grans_dades);

// 4. Mesurar l'ús després de l'alliberament
$mem_final = memory_get_usage(true);

echo "<h3>Diagnòstic de Memòria:</h3>";
echo "<li>Memòria Abans de Càrrega: " . round($mem_inici / 1024 / 1024, 2) . " MB</li>";
echo "<li>**Pic Màxim de Memòria:** **" . round($mem_pic / 1024 / 1024, 2) . " MB**</li>";
echo "<li>Memòria Després d'Alliberar: " . round($mem_final / 1024 / 1024, 2) . " MB</li>";

- Eines de Profiling (Anàlisi Detallada)

Les eines de profiling proporcionen un mapa visual de quines funcions exactament augmenten el consum de memòria:

  • Xdebug: El seu profiler no només rastreja el temps, sinó també la memòria consumida a cada crida de funció, permetent-ne l'anàlisi amb eines com KCacheGrind.

  • Blackfire: Ofereix gràfics de crides detallats que mostren l'impacte de memòria funció per funció, amb recomanacions específiques sobre com optimitzar les operacions que la consumeixen.


 

Eines de Configuració (PHP.INI i Servidor)

La configuració del sistema és el primer nivell de defensa per prevenir que els scripts ineficients col·lapsin el servidor.

- Directives de PHP.INI

 

Directiva PHP.INI Funció Importància
memory_limit El més important. Defineix la quantitat màxima de memòria RAM que un script PHP pot consumir. Si un script supera aquest límit, PHP llança un Error Fatal (Fatal error: Allowed memory size of X bytes exhausted...) i atura l'execució, protegint el servidor.
max_input_vars Limita el nombre de variables que es poden rebre via $_GET, $_POST i $_COOKIE. Limita el risc d'esgotament de memòria causat per la càrrega de dades massives en formularis.
zend.enable_gc Controla l'habilitació del Recollidor d'Escombraries (GC) de PHP. Normalment està activat per defecte. En casos extrems o scripts molt llargs, desactivar-lo i cridar gc_collect_cycles() manualment pot millorar la gestió de memòria.

 

- Optimització del Codi per Minimitzar l'Ús

La millor "eina" és un codi ben escrit. Les tècniques per mitigar el consum de memòria inclouen:

  1. Iteració de Dades (Iterators i Generators): En lloc de carregar tot un resultat de base de dades a la memòria, utilitzar generadors o iteradors per processar els registres un per un. Això manté l'ús de memòria gairebé constant, independentment de la mida del conjunt de dades.

  2. Alliberament Explícit: Utilitzar unset() en variables grans o objectes complexos tan aviat com ja no siguin necessaris per permetre al GC actuar abans.

  3. Processament Batch: Dividir les operacions amb grans volums de dades en trossos més petits (per exemple, processar 1.000 registres cada vegada en lloc de 100.000), especialment en tasques CLI o workers.