not - php reduce memory usage
Lo que es mejor para liberar memoria con PHP: unset() o $ var=null (12)
Me doy cuenta de que la segunda evita la sobrecarga de una llamada de función ( actualizar , en realidad es una construcción de lenguaje), pero sería interesante saber si una es mejor que la otra. He estado usando unset()
para la mayor parte de mi codificación, pero recientemente he revisado algunas clases respetables encontradas fuera de la red que usan $var = null
lugar.
¿Hay uno preferido, y cuál es el razonamiento?
Al hacer un unset () en una variable, esencialmente ha marcado la variable para ''recolección de basura'' (PHP no tiene realmente una, pero por ejemplo) por lo que la memoria no está disponible de inmediato. La variable ya no alberga los datos, pero la pila permanece en el tamaño más grande. Al hacer el método nulo, se eliminan los datos y se reduce la memoria de la pila casi de inmediato.
Esto ha sido de la experiencia personal y otros también. Vea los comentarios de la función unset () here .
Personalmente uso unset () entre iteraciones en un bucle para no tener que retrasar el tamaño de la pila. Los datos se han ido, pero la huella se mantiene. En la siguiente iteración, la memoria ya está siendo tomada por php y, por lo tanto, más rápido para inicializar la siguiente variable.
Con respecto a los objetos, especialmente en el escenario de carga lenta, uno debe considerar que el recolector de basura se está ejecutando en ciclos de CPU inactivos, por lo que suponer que se está metiendo en problemas cuando muchos objetos se están cargando, la penalización de tiempo solucionará la liberación de memoria.
Use time_nanosleep para habilitar GC para recolectar memoria. Establecer la variable en nulo es deseable.
Probado en el servidor de producción, originalmente el trabajo consumía 50 MB y luego se detuvo. Después de que se usó nanosleep 14MB fue un consumo constante de memoria.
Se debe decir que esto depende del comportamiento del GC que puede cambiar de una versión de PHP a otra. Pero funciona en PHP 5.3 bien.
p.ej. este ejemplo (código tomado 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);
...
Creé una nueva prueba de rendimiento para unset
y =null
, porque como se menciona en los comentarios, aquí escrito tiene un error (la recreación de los elementos). Usé matrices, como ves, no importaba ahora.
<?php
$arr1 = array();
$arr2 = array();
for ($i = 0; $i < 10000000; $i++) {
$arr1[$i] = ''a'';
$arr2[$i] = ''a'';
}
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
$arr1[$i] = null;
}
$elapsed = microtime(true) - $start;
echo ''took ''. $elapsed .''seconds<br>'';
$start = microtime(true);
for ($i = 0; $i < 10000000; $i++) {
unset($arr2[$i]);
}
$elapsed = microtime(true) - $start;
echo ''took ''. $elapsed .''seconds<br>'';
Pero solo puedo probarlo en un servidor PHP 5.5.9, aquí están los resultados: - tomó 4.4571571350098 segundos - tomó 4.4425978660583 segundos
Prefiero unset
por razones de legibilidad.
Funciona de una manera diferente para las variables copiadas por referencia:
$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
Hace una diferencia con los elementos de la matriz.
Considera este ejemplo
$a = array(''test'' => 1);
$a[''test''] = NULL;
echo "Key test ", array_key_exists(''test'', $a)? "exists": "does not exist";
Aquí, la clave ''prueba'' todavía existe. Sin embargo, en este ejemplo
$a = array(''test'' => 1);
unset($a[''test'']);
echo "Key test ", array_key_exists(''test'', $a)? "exists": "does not exist";
la llave ya no existe
PHP 7 ya está trabajando en dichos problemas de administración de memoria y su uso reducido hasta mínimo.
<?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:
tomó 0.16778993606567 segundos tomó 0.16630101203918 segundos
Para el registro, y excluyendo el tiempo que lleva:
<?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";
Vuelve
First:
438296
438352
Unset:
438296
438352
Null:
438296
438352
function:
438296
438352
Reasign:
438296
520216 <-- double usage.
Conclusión, memoria libre nula y no configurada como se esperaba (no solo al final de la ejecución). Además, la reasignación de una variable mantiene el valor dos veces en algún punto (520216 frente a 438352)
Se mencionó en la página del manual de desarmado en 2009 :
unset()
hace exactamente lo que su nombre dice - anula una variable. No fuerza la liberación inmediata de la memoria. El recolector de basura de PHP lo hará cuando lo considere oportuno, por intención tan pronto, ya que de todos modos no se necesitan esos ciclos de CPU, o tan tarde como antes de que el script se quede sin memoria, lo que ocurra primero.Si estás haciendo
$whatever = null;
entonces estás reescribiendo los datos de la variable. Es posible que la memoria se libere / contraiga más rápido, pero puede robar ciclos de CPU del código que realmente los necesita antes, lo que resulta en un tiempo de ejecución general más prolongado.
(Desde 2013, esa página de manual no unset
ya no incluye esa sección)
Tenga en cuenta que hasta php5.3, si tiene dos objetos en referencia circular , como en una relación padre-hijo, llamar a unset () en el objeto padre no liberará la memoria utilizada para la referencia padre en el objeto hijo. (Tampoco se liberará la memoria cuando el objeto principal sea recolectado como basura). ( Error 33595 )
La pregunta " diferencia entre unset y = null " detalla algunas diferencias:
unset($a)
también elimina $a
de la tabla de símbolos; por ejemplo:
$a = str_repeat(''hello world '', 100);
unset($a);
var_dump($a);
Salidas:
Notice: Undefined variable: a in xxx
NULL
Pero cuando se usa
$a = null
:
$a = str_repeat(''hello world '', 100);
$a = null;
var_dump($a);
Outputs:
NULL
Parece que
$a = null
es un poco más rápido que su contraparteunset()
: la actualización de una entrada de la tabla de símbolos parece ser más rápida que eliminarla.
- cuando intenta utilizar una variable no existente (no establecida), se activará un error y el valor de la expresión de la variable será nulo. (Porque, ¿qué otra cosa debería hacer PHP? Cada expresión debe resultar en algún valor.)
- Sin embargo, una variable con nulo asignada sigue siendo una variable perfectamente normal.
Todavía dudo de esto, pero lo probé en mi script y estoy usando xdebug para saber cómo afectará el uso de la memoria de mi aplicación. El script está configurado en mi función de esta manera:
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;
}
Y agrego unset justo antes del código de return
y me da: 160200, luego trato de cambiarlo con $sql = NULL
y me da: 160224 :)
Pero hay algo único en esta comparativa cuando no estoy usando unset () o NULL, xdebug me da 160144 como uso de memoria
Por lo tanto, creo que dar línea para usar unset () o NULL agregará un proceso a su aplicación y será mejor mantener el origen con su código y disminuir la variable que está usando tan eficaz como sea posible.
Corrigeme si me equivoco, gracias
unset
código si no liberar la memoria inmediata sigue siendo muy útil y sería una buena práctica hacerlo cada vez que pasamos los pasos de código antes de salir de un método. Toma nota de que no se trata de liberar la memoria inmediata. la memoria inmediata es para la CPU, ¿qué pasa con la memoria secundaria que es la memoria RAM.
y esto también aborda sobre la prevención de fugas de memoria.
Por favor, consulte este enlace http://www.hackingwithphp.com/18/1/11/be-wary-of-garbage-collection-part-2
He estado usando unset desde hace mucho tiempo ahora.
mejores prácticas como esta en el código para desmarcar instantáneamente todas las variables que ya se han utilizado como matriz.
$data[''tesst'']='''';
$data[''test2'']=''asdadsa'';
....
nth.
y just unset($data);
para liberar todo el uso variable.
Por favor vea el tema relacionado para desarmar.
¿Qué tan importante es eliminar variables en PHP?
[insecto]
unset
no es en realidad una función, sino una construcción de lenguaje . No es más una llamada de función que una return
o una include
.
Aparte de los problemas de rendimiento, el uso de unset
hace que la intención de su código sea mucho más clara.
<?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";
?>
Porque parece que "= null" es más rápido.
Resultados de PHP 5.4:
- tomó 0.88389301300049 segundos
- tomó 2.1757180690765 segundos
Resultados de PHP 5.3:
- tomó 1.7235369682312 segundos
- tomó 2.9490959644318 segundos
Resultados de PHP 5.2:
- tomó 3.0069220066071 segundos
- tomó 4.7002630233765 segundos
Resultados de PHP 5.1:
- tomó 2.6272349357605 segundos
- tomó 5.0403649806976 segundos
Las cosas comienzan a verse diferentes con PHP 5.0 y 4.4.
5.0:
- tomó 10.038941144943 segundos
- tomó 7.0874409675598 segundos
4.4:
- tomó 7.5352551937103 segundos
- tomó 6,6245851516724 segundos
Tenga en cuenta que microtime (verdadero) no funciona en PHP 4.4, así que tuve que usar el ejemplo de microtime_float dado en php.net/microtime / Example # 1.