253 votes

Qu'est-ce qui est le plus efficace pour libérer de la mémoire avec PHP : unset() ou $var = null ?

Je réalise que la seconde évite la surcharge d'un appel de fonction ( mise à jour est en fait une construction linguistique), mais il serait intéressant de savoir si l'une est meilleure que l'autre. J'ai utilisé unset() pour la plupart de mon codage, mais j'ai récemment regardé quelques cours respectables trouvés sur le net qui utilisent $var = null à la place.

Y a-t-il une préférence, et quel est le raisonnement ?

241voto

VonC Points 414372

Il a été mentionné dans le Page du manuel désactivée en 2009 :

unset() fait ce que son nom indique - annuler une variable. Il ne force pas la libération immédiate de la mémoire. Le ramasseur de déchets de PHP le fera quand il le jugera bon - par intention dès que possible, car ces cycles CPU ne sont pas nécessaires de toute façon, ou aussi tard qu'avant que le script ne manque de mémoire, selon ce qui se produit en premier.

Si vous faites $whatever = null; alors vous réécrivez les données de la variable. La mémoire sera peut-être libérée/réduite plus rapidement, mais vous risquez de voler des cycles CPU au code qui en a vraiment besoin plus tôt, ce qui se traduira par un temps d'exécution global plus long.

(Depuis 2013, ce unset page de manuel n'incluent plus cette section)

Notez que jusqu'à php5.3, si vous avez deux objets en référence circulaire Comme dans le cas d'une relation parent-enfant, l'appel à unset() sur l'objet parent ne libérera pas la mémoire utilisée pour la référence parentale dans l'objet enfant. (La mémoire ne sera pas non plus libérée lorsque l'objet parent sera mis au rebut). bug 33595 )


La question " différence entre unset et = null " détaille quelques différences :


unset($a) supprime également $a de la table des symboles ; par exemple :

$a = str_repeat('hello world ', 100);
unset($a);
var_dump($a);

Sorties :

Notice: Undefined variable: a in xxx
NULL

Mais quand $a = null est utilisé :

$a = str_repeat('hello world ', 100);
$a = null;
var_dump($a);

Sorties :

NULL

Il semble que $a = null est un peu plus rapide que son unset() contrepartie : la mise à jour d'une entrée de la table des symboles semble être plus rapide que sa suppression.


  • lorsque vous essayez d'utiliser un fichier inexistant ( unset ), une erreur sera déclenchée et la valeur de l'expression de la variable sera nulle. (Parce que, qu'est-ce que PHP devrait faire d'autre ? Chaque expression doit donner lieu à une valeur).
  • Une variable à laquelle on a assigné la valeur null reste cependant une variable parfaitement normale.

18 votes

Notez que si $whatever pointe vers un objet, $whatever = null écrase le pointeur, et non l'objet lui-même, donc il agit de la même manière que unset() .

2 votes

@VonC : la citation "unset" sur php.net à laquelle vous faites référence n'existe plus.

0 votes

@JürgenThelen vrai, mais le contenu de cette ancienne réponse semble toujours pertinent, non ?

50voto

Alex Barrett Points 7719

unset n'est pas réellement une fonction, mais un construction du langage . Il ne s'agit pas plus d'un appel de fonction qu'un return ou un include .

En dehors des problèmes de performance, l'utilisation de unset fait de votre code intention beaucoup plus claire.

0 votes

C'est pourquoi je les ai toujours utilisés, personnellement je trouvais qu'ils avaient meilleure allure que $var = null. Au fait, j'ai toujours utilisé NULL en majuscules... mais maintenant je ne sais pas pourquoi ?

1 votes

@VonC : Oui, je m'en doutais, mais pourquoi peut-on utiliser les minuscules true, false et null ?

0 votes

J'ai également supposé que les constructions du langage n'utilisaient pas de parenthèses, comme echo, require, include, etc. ne sont pas echo(), require() ou include().

37voto

William Holroyd Points 1769

En effectuant un unset() sur une variable, vous avez essentiellement marqué la variable pour le 'garbage collection' (PHP n'en a pas vraiment, mais pour l'exemple) de sorte que la mémoire n'est pas immédiatement disponible. La variable ne contient plus les données, mais la pile reste à la taille supérieure. L'utilisation de la méthode null supprime les données et réduit la mémoire de la pile presque immédiatement.

C'est mon expérience personnelle et celle d'autres personnes. Voir les commentaires de la fonction unset() aquí .

Personnellement, j'utilise unset() entre les itérations d'une boucle afin de ne pas avoir à subir le retard de la pile dont la taille fait du yo-yo. Les données ont disparu, mais l'empreinte reste. A l'itération suivante, la mémoire est déjà prise par php et donc, plus rapide pour initialiser la variable suivante.

15 votes

Mettre quelque chose à NULL peut être utile si la mémoire requise pour contenir la valeur NULL est inférieure à celle requise pour contenir la valeur qu'elle contenait auparavant. Par exemple, une longue chaîne de caractères. Si la chaîne n'était pas une constante et que son nombre de références tombe à zéro, alors cette mémoire devrait être libérée. Unset est plus propre - il ne maintient plus de référence. Vous devez attendre le ramassage des ordures, mais il est prudent de considérer qu'il n'occupe pas de mémoire, car une condition de mémoire faible déclenchera le ramassage des ordures.

0 votes

Ne pouvons-nous pas utiliser les deux ? equal to null et ensuite unset ?

2 votes

@NabeelKhan Je vous suggère d'utiliser unset() à l'intérieur des boucles et de l'annuler lorsque vous sortez de la boucle. Sinon, il y a un impact sur les performances à faire les deux à l'intérieur de la boucle. Si vous n'utilisez pas de boucles, il suffit d'annuler la fonction car elle effectue déjà la logique unset() dans les coulisses.

29voto

<?php
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    $a = 'a';
    $a = NULL;
}
$elapsed = microtime(true) - $start;

echo "took $elapsed seconds\r\n";

$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
    $a = 'a';
    unset($a);
}
$elapsed = microtime(true) - $start;

echo "took $elapsed seconds\r\n";
?>

Pour cela, il semble que "= null" soit plus rapide.

Résultats de PHP 5.4 :

  • a pris 0,88389301300049 secondes
  • a pris 2,1757180690765 secondes

Résultats de PHP 5.3 :

  • a pris 1,7235369682312 secondes
  • a pris 2,9490959644318 secondes

Résultats de PHP 5.2 :

  • a pris 3.0069220066071 secondes
  • a pris 4,7002630233765 secondes

Résultats de PHP 5.1 :

  • a pris 2,6272349357605 secondes
  • a pris 5.0403649806976 secondes

Les choses commencent à être différentes avec PHP 5.0 et 4.4.

5.0 :

  • a pris 10.038941144943 secondes
  • a pris 7,0874409675598 secondes

4.4 :

  • a pris 7,5352551937103 secondes
  • a pris 6.6245851516724 secondes

Gardez à l'esprit que microtime(true) ne fonctionne pas en PHP 4.4. J'ai donc dû utiliser l'exemple microtime_float donné dans php.net/microtime / Exemple #1.

20voto

RiaD Points 15744

Cela fonctionne d'une manière différente pour les variables copiées par référence :

$a = 5;
$b = &$a;
unset($b); // just say $b should not point to any variable
print $a; // 5

$a = 5;
$b = &$a;
$b = null; // rewrites value of $b (and $a)
print $a; // nothing, because $a = null

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X