No se puede calcular retrospectivamente la huella exacta de una variable, ya que dos variables pueden compartir el mismo espacio asignado en la memoria.
Intentemos compartir memoria entre dos matrices, vemos que asignar la segunda matriz cuesta la mitad de la memoria de la primera. Cuando desarmamos el primero, el segundo todavía usa casi toda la memoria.
echo memory_get_usage()."\n"; // <-- 433200
$c=range(1,100);
echo memory_get_usage()."\n"; // <-- 444348 (+11148)
$d=array_slice($c, 1);
echo memory_get_usage()."\n"; // <-- 451040 (+6692)
unset($c);
echo memory_get_usage()."\n"; // <-- 444232 (-6808)
unset($d);
echo memory_get_usage()."\n"; // <-- 433200 (-11032)
Entonces, no podemos concluir que la segunda matriz usa la mitad de la memoria, ya que se vuelve falsa cuando desarmamos la primera.
Para obtener una vista completa de cómo se asigna la memoria en PHP y para qué uso, le sugiero que lea el siguiente artículo: ¿Qué tan grandes son realmente las matrices (y valores) de PHP? (Pista: ¡GRANDE!)
Los conceptos básicos del recuento de referencias en la documentación de PHP también tienen mucha información sobre el uso de la memoria y el recuento de referencias al segmento de datos compartidos.
Las diferentes soluciones expuestas aquí son buenas para aproximaciones, pero ninguna puede manejar la administración sutil de la memoria PHP.
- calcular el espacio recién asignado
Si desea el espacio recién asignado después de una asignación, entonces debe usarlo memory_get_usage()
antes y después de la asignación, ya que usarlo con una copia le da una visión errónea de la realidad.
// open output buffer
echo "Result: ";
// call every function once
range(1,1); memory_get_usage();
echo memory_get_usage()."\n";
$c=range(1,100);
echo memory_get_usage()."\n";
Recuerda que si quieres almacenar el resultado del primero memory_get_usage()
, la variable ya tiene que existir antes, ymemory_get_usage()
debe ser llamada otra vez antes, y todas las demás funciones también.
Si desea hacer eco como en el ejemplo anterior, su búfer de salida ya debe estar abierto para evitar la memoria de contabilidad necesaria para abrir el búfer de salida.
- calculando el espacio requerido
Si desea confiar en una función para calcular el espacio requerido para almacenar una copia de una variable, el siguiente código se encarga de diferentes optimizaciones:
<?php
function getMemorySize($value) {
// existing variable with integer value so that the next line
// does not add memory consumption when initiating $start variable
$start=1;
$start=memory_get_usage();
// json functions return less bytes consumptions than serialize
$tmp=json_decode(json_encode($value));
return memory_get_usage() - $start;
}
// open the output buffer, and calls the function one first time
echo ".\n";
getMemorySize(NULL);
// test inside a function in order to not care about memory used
// by the addition of the variable name to the $_GLOBAL array
function test() {
// call the function name once
range(1,1);
// we will compare the two values (see comment above about initialization of $start)
$start=1;
$start=memory_get_usage();
$c=range(1,100);
echo memory_get_usage()-$start."\n";
echo getMemorySize($c)."\n";
}
test();
// same result, this works fine.
// 11044
// 11044
Tenga en cuenta que el tamaño del nombre de la variable importa en la memoria asignada.
- ¡Revisa tu código!
Una variable tiene un tamaño básico definido por la estructura interna de C utilizada en el código fuente PHP. Este tamaño no fluctúa en el caso de los números. Para cadenas, agregaría la longitud de la cadena.
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
Si no tenemos en cuenta la inicialización del nombre de la variable, ya sabemos cuánto utiliza una variable (en el caso de números y cadenas):
44 bytes en el caso de números
+ 24 bytes en el caso de cadenas
+ la longitud de la cadena (incluido el carácter NUL final)
(esos números pueden cambiar según la versión de PHP)
Tiene que redondear a un múltiplo de 4 bytes debido a la alineación de la memoria. Si la variable está en el espacio global (no dentro de una función), también asignará 64 bytes más.
Entonces, si desea usar uno de los códigos dentro de esta página, debe verificar que el resultado usando algunos casos de prueba simples (cadenas o números) coincida con esos datos teniendo en cuenta cada una de las indicaciones en esta publicación ($ _GLOBAL array, primera llamada de función, búfer de salida, ...)