Dans PHP, Array_Walk_Recursive est une fonction très utile qui vous permet de fonctionner sur chaque élément d'un tableau multidimensionnel. Cependant, cette fonction peut également provoquer des fuites de mémoire, en particulier lorsqu'elles traitent de grandes quantités de données. Les fuites de mémoire peuvent provoquer une croissance de l'utilisation de la mémoire de l'application et peuvent éventuellement provoquer le plantage du système. Par conséquent, il est très important de savoir comment éviter les fuites de mémoire lors de l'utilisation de Array_Walk_Recursive .
La fuite de mémoire fait référence au programme qui demande la mémoire, mais il n'est pas publié lorsqu'il n'est plus utilisé, entraînant une augmentation continue de l'utilisation de la mémoire, ce qui affecte finalement les performances et la stabilité du programme. En PHP, les fuites de mémoire se produisent généralement lorsque des références circulaires, des allocations de ressources illimitées ou des variables non clés occupent la mémoire.
La fonction Array_Walk_Recursive est utilisée pour traverser récursivement le tableau et appliquer une fonction de rappel à chaque élément. Sa syntaxe de base est la suivante:
<span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span>(</span><span><span class="hljs-keyword">array</span></span><span> &</span><span><span class="hljs-variable">$array</span></span><span>, </span><span><span class="hljs-keyword">callable</span></span><span> </span><span><span class="hljs-variable">$callback</span></span><span>);
</span></span>
$ array est le tableau à traiter.
$ rappel est une fonction de rappel à appliquer à chaque élément du tableau.
Par exemple:
<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-number">1</span></span><span>, [</span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>], </span><span><span class="hljs-number">4</span></span><span>];
</span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>, function(&</span><span><span class="hljs-variable">$item</span></span><span>, </span><span><span class="hljs-variable">$key</span></span><span>) {
</span><span><span class="hljs-variable">$item</span></span><span> = </span><span><span class="hljs-variable">$item</span></span><span> * </span><span><span class="hljs-number">2</span></span><span>;
});
</span><span><span class="hljs-title function_ invoke__">print_r</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>);
</span></span>
Résultats de l'exécution:
<span><span>Array
(
[</span><span><span class="hljs-meta">0</span></span><span>] => </span><span><span class="hljs-number">2</span></span><span>
[</span><span><span class="hljs-meta">1</span></span><span>] => Array
(
[</span><span><span class="hljs-meta">0</span></span><span>] => </span><span><span class="hljs-number">4</span></span><span>
[</span><span><span class="hljs-meta">1</span></span><span>] => </span><span><span class="hljs-number">6</span></span><span>
)
[</span><span><span class="hljs-meta">2</span></span><span>] => </span><span><span class="hljs-number">8</span></span><span>
)
</span></span>
Bien que cette fonction soit très puissante, vous pouvez rencontrer des problèmes de fuite de mémoire lorsque vous traitez avec des ensembles de données plus importants, en particulier lorsque les tableaux contiennent un grand nombre de tableaux ou d'objets imbriqués.
array_walk_recursive fonctionne chaque élément par référence. Lorsque itéra les itérations sur le tableau récursivement, il lit et modifie les éléments à plusieurs reprises sans gestion de la mémoire appropriée, en particulier lors de la rencontre de structures très complexes. Surtout si de nouvelles références ou objets sont créés à l'intérieur de la fonction de rappel, ces objets peuvent ne pas être détruits dans le temps, ce qui entraîne une utilisation croissante de la mémoire.
Supposons que vous créiez un nouvel objet dans la fonction de rappel et que vous le stockiez sans détruire explicitement ces objets:
<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-number">1</span></span><span>, [</span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>], </span><span><span class="hljs-number">4</span></span><span>];
</span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>, function(&</span><span><span class="hljs-variable">$item</span></span><span>, </span><span><span class="hljs-variable">$key</span></span><span>) {
</span><span><span class="hljs-variable">$item</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">StdClass</span></span><span>(); </span><span><span class="hljs-comment">// Créer un nouvel objet</span></span><span>
});
</span></span>
Dans cet exemple, un nouvel objet est créé à chaque fois que vous vous réinscrivez et ces objets ne sont pas détruits. Si le tableau est très grand ou si la profondeur récursive est profonde, la fuite de mémoire deviendra très grave.
Voici quelques meilleures pratiques pour éviter les fuites de mémoire de Array_Walk_Recursive :
Lorsque vous créez des variables ou des objets temporaires dans la fonction de rappel, utilisez unset () pour les détruire explicitement. Cela aidera à libérer la mémoire à temps.
<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-number">1</span></span><span>, [</span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>], </span><span><span class="hljs-number">4</span></span><span>];
</span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>, function(&</span><span><span class="hljs-variable">$item</span></span><span>, </span><span><span class="hljs-variable">$key</span></span><span>) {
</span><span><span class="hljs-variable">$item</span></span><span> = </span><span><span class="hljs-keyword">new</span></span><span> </span><span><span class="hljs-title class_">StdClass</span></span><span>();
</span><span><span class="hljs-keyword">unset</span></span><span>(</span><span><span class="hljs-variable">$item</span></span><span>); </span><span><span class="hljs-comment">// Détruire les objets en temps opportun</span></span><span>
});
</span></span>
Les générateurs sont une alternative efficace qui peut traverser les tableaux de manière paresseuse, plutôt que de charger la matrice entière en mémoire à la fois. En utilisant le générateur, les fuites de mémoire peuvent être évitées efficacement.
<span><span><span class="hljs-function"><span class="hljs-keyword">function</span></span></span><span> </span><span><span class="hljs-title">recursive_walk</span></span><span>(</span><span><span class="hljs-params"><span class="hljs-variable">$array</span></span></span><span>) {
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$array</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$key</span></span><span> => </span><span><span class="hljs-variable">$value</span></span><span>) {
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-title function_ invoke__">is_array</span></span><span>(</span><span><span class="hljs-variable">$value</span></span><span>)) {
</span><span><span class="hljs-keyword">yield</span></span><span> </span><span><span class="hljs-keyword">from</span></span><span> </span><span><span class="hljs-title function_ invoke__">recursive_walk</span></span><span>(</span><span><span class="hljs-variable">$value</span></span><span>); </span><span><span class="hljs-comment">// Traversé récursivement des sous-réseaux</span></span><span>
} </span><span><span class="hljs-keyword">else</span></span><span> {
</span><span><span class="hljs-keyword">yield</span></span><span> </span><span><span class="hljs-variable">$key</span></span><span> => </span><span><span class="hljs-variable">$value</span></span><span>;
}
}
}
</span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-number">1</span></span><span>, [</span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>], </span><span><span class="hljs-number">4</span></span><span>];
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-title function_ invoke__">recursive_walk</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>) </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$key</span></span><span> => </span><span><span class="hljs-variable">$value</span></span><span>) {
</span><span><span class="hljs-keyword">echo</span></span><span> </span><span><span class="hljs-string">"<span class="hljs-subst">$key</span></span></span><span> => </span><span><span class="hljs-subst">$value</span></span><span>\n";
}
</span></span>
Le générateur peut réduire efficacement la consommation de mémoire en chargeant des éléments à la demande.
Évitez de créer de nouvelles variables ou objets dans la fonction de rappel et modifier directement la valeur de l'élément de tableau d'origine peut éviter les frais généraux de mémoire inutiles.
<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-number">1</span></span><span>, [</span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>], </span><span><span class="hljs-number">4</span></span><span>];
</span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>, function(&</span><span><span class="hljs-variable">$item</span></span><span>, </span><span><span class="hljs-variable">$key</span></span><span>) {
</span><span><span class="hljs-variable">$item</span></span><span> *= </span><span><span class="hljs-number">2</span></span><span>; </span><span><span class="hljs-comment">// Modifier directement l'élément d'origine</span></span><span>
});
</span></span>
Assurez-vous que l'opération effectuée par la fonction de rappel est aussi simple que possible et n'effectuez pas trop d'allocation de ressources ou de calculs complexes, en particulier lors de l'appel récursivement. S'il existe des ressources dans la fonction de rappel qui doivent être créées à plusieurs reprises, essayez d'éviter la création répétée dans chaque récursivité.
<span><span><span class="hljs-variable">$array</span></span><span> = [</span><span><span class="hljs-number">1</span></span><span>, [</span><span><span class="hljs-number">2</span></span><span>, </span><span><span class="hljs-number">3</span></span><span>], </span><span><span class="hljs-number">4</span></span><span>];
</span><span><span class="hljs-title function_ invoke__">array_walk_recursive</span></span><span>(</span><span><span class="hljs-variable">$array</span></span><span>, function(&</span><span><span class="hljs-variable">$item</span></span><span>, </span><span><span class="hljs-variable">$key</span></span><span>) {
</span><span><span class="hljs-built_in">static</span></span><span> </span><span><span class="hljs-variable">$multiplier</span></span><span> = </span><span><span class="hljs-number">2</span></span><span>; </span><span><span class="hljs-comment">// Utilisez des variables statiques pour stocker des valeurs constantes</span></span><span>
</span><span><span class="hljs-variable">$item</span></span><span> *= </span><span><span class="hljs-variable">$multiplier</span></span><span>;
});
</span></span>
Parfois, la conception du tableau lui-même peut affecter les performances et l'utilisation de la mémoire. Essayez d'éviter d'utiliser des structures imbriquées trop profondes. Si possible, envisagez de simplifier la structure des données à une forme plus plate, en réduisant la complexité de la récursivité.
Bien que Array_Walk_Recursive soit un outil très pratique, son utilisation nécessite également des soins, en particulier lorsqu'il s'agit de quantités complexes ou importantes de données. En contrôlant l'utilisation de la mémoire, en nettoyant les variables et objets inutiles et en adoptant des générateurs et autres stratégies d'optimisation, les problèmes de fuite de mémoire peuvent être effectivement évités. N'oubliez pas que la gestion de la mémoire est l'une des clés de l'optimisation des performances PHP. Une utilisation raisonnable de la mémoire peut considérablement améliorer la stabilité et la vitesse de réponse de l'application.