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 ?

19voto

auris Points 211

Cela fait une différence avec les éléments du tableau.

Prenons l'exemple suivant

$a = array('test' => 1);
$a['test'] = NULL;
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";

Ici, la clé "test" existe toujours. Cependant, dans cet exemple

$a = array('test' => 1);
unset($a['test']);
echo "Key test ", array_key_exists('test', $a)? "exists": "does not exist";

la clé n'existe plus.

14voto

OSP Points 166

En ce qui concerne les objets, en particulier dans le scénario de chargement paresseux, il faut tenir compte du fait que le ramasseur d'ordures fonctionne dans les cycles inactifs du processeur. Il faut donc supposer que vous allez avoir des problèmes lorsque beaucoup d'objets sont chargés ; une petite pénalité de temps résoudra la libération de la mémoire.

Utilisez time_nanosleep pour permettre à GC de collecter la mémoire. Mettre la variable à null est souhaitable.

Testé sur un serveur de production, à l'origine le travail a consommé 50MB et a ensuite été arrêté. Après l'utilisation de nanosleep, la consommation de mémoire constante était de 14 Mo.

Il faut dire que cela dépend du comportement du GC qui peut changer d'une version de PHP à l'autre. Mais cela fonctionne bien avec PHP 5.3.

Par exemple, cet exemple (code pris de VirtueMart2 google feed)

for($n=0; $n<count($ids); $n++)
{
    //unset($product); //usefull for arrays
    $product = null
    if( $n % 50 == 0 )
    {
        // let GC do the memory job
        //echo "<mem>" . memory_get_usage() . "</mem>";//$ids[$n];
        time_nanosleep(0, 10000000);
    }

    $product = $productModel->getProductSingle((int)$ids[$n],true, true, true);
    ...

3voto

Anggie Aziz Points 57

J'ai encore des doutes à ce sujet, mais je l'ai essayé à mon script et j'utilise xdebug pour savoir comment cela va affecter l'utilisation de la mémoire de mon application. Le script est défini sur ma fonction comme ceci :

function gen_table_data($serv, $coorp, $type, $showSql = FALSE, $table = 'ireg_idnts') {
    $sql = "SELECT COUNT(`operator`) `operator` FROM $table WHERE $serv = '$coorp'";
    if($showSql === FALSE) {
        $sql = mysql_query($sql) or die(mysql_error());
        $data = mysql_fetch_array($sql);
        return $data[0];
    } else echo $sql;
}

Et j'ajoute unset juste avant le return code et il me donne : 160200 puis j'essaie de le changer avec $sql = NULL et cela me donne : 160224 :)

Mais il y a quelque chose d'unique dans ce comparatif quand je n'utilise pas unset() ou NULL, xdebug me donne 160144 comme utilisation de la mémoire.

Donc, je pense que donner la ligne pour utiliser unset() ou NULL ajoutera du processus à votre application et il sera mieux de rester original avec votre code et de diminuer la variable que vous utilisez aussi efficacement que vous pouvez.

Corrigez-moi si je me trompe, merci.

3voto

magallanes Points 1024

Pour mémoire, et sans compter le temps que cela prend :

<?php
echo "<hr>First:<br>";
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";      
echo memory_get_peak_usage() . "<br>\n"; 
echo "<hr>Unset:<br>";
unset($x);
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";      
echo memory_get_peak_usage() . "<br>\n"; 
echo "<hr>Null:<br>";
$x=null;
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";      
echo memory_get_peak_usage() . "<br>\n";

echo "<hr>function:<br>";
function test() {
    $x = str_repeat('x', 80000);
}
echo memory_get_usage() . "<br>\n";      
echo memory_get_peak_usage() . "<br>\n"; 

echo "<hr>Reasign:<br>";
$x = str_repeat('x', 80000);
echo memory_get_usage() . "<br>\n";      
echo memory_get_peak_usage() . "<br>\n"; 

Il retourne

First:
438296
438352
Unset:
438296
438352
Null:
438296
438352
function:
438296
438352
Reasign:
438296
520216 <-- double usage.

Conclusion, les deux null et unset libèrent de la mémoire comme prévu (pas seulement à la fin de l'exécution). De plus, la réaffectation d'une variable conserve la valeur deux fois à un moment donné (520216 contre 438352).

3voto

Swapnil Points 11

PHP 7 a déjà travaillé sur ces problèmes de gestion de la mémoire et son utilisation a été réduite au minimum.

<?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";

?>

PHP 7.1 Outpu :

a pris 0.16778993606567 secondes a pris 0.16630101203918 secondes

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