Vous ne pouvez pas calculer rétrospectivement l'empreinte exacte d'une variable car deux variables peuvent partager le même espace alloué dans la mémoire
Essayons de partager la mémoire entre deux tableaux, nous voyons que l'allocation du deuxième tableau coûte la moitié de la mémoire du premier. Lorsque nous désactivons le premier, presque toute la mémoire est encore utilisée par le second.
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)
Nous ne pouvons donc pas conclure que le deuxième tableau utilise la moitié de la mémoire, car il devient faux lorsque nous annulons le premier.
Pour une vue complète de la façon dont la mémoire est allouée en PHP et pour quelle utilisation, je vous suggère de lire l'article suivant: Quelle est la taille réelle des tableaux (et des valeurs) PHP? (Indice: GRAND!)
Les principes de base du comptage de références dans la documentation PHP contiennent également de nombreuses informations sur l'utilisation de la mémoire et les références comptent pour un segment de données partagé.
Les différentes solutions exposées ici sont bonnes pour les approximations mais aucune ne peut gérer la gestion subtile de la mémoire PHP.
- calcul de l'espace nouvellement alloué
Si vous voulez l'espace nouvellement alloué après une affectation, vous devez l'utiliser memory_get_usage()
avant et après l'allocation, car l'utiliser avec une copie vous donne une vision erronée de la réalité.
// 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";
N'oubliez pas que si vous voulez stocker le résultat de la première memory_get_usage()
, la variable doit déjà exister avant, et memory_get_usage()
doit être appelée une autre fois auparavant, et toutes les autres fonctions également.
Si vous voulez faire un écho comme dans l'exemple ci-dessus, votre tampon de sortie doit déjà être ouvert pour éviter que la mémoire comptable ne soit nécessaire pour ouvrir le tampon de sortie.
- calcul de l'espace requis
Si vous souhaitez vous fier à une fonction pour calculer l'espace requis pour stocker une copie d'une variable, le code suivant prend en charge différentes optimisations:
<?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
Notez que la taille du nom de la variable compte dans la mémoire allouée.
- Vérifiez votre code !!
Une variable a une taille de base définie par la structure C interne utilisée dans le code source PHP. Cette taille ne fluctue pas dans le cas des nombres. Pour les chaînes, cela ajouterait la longueur de la chaîne.
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 on ne prend pas en compte l'initialisation du nom de la variable, on sait déjà combien une variable utilise (en cas de nombres et de chaînes):
44 octets dans le cas de nombres
+ 24 octets dans le cas des chaînes
+ la longueur de la chaîne (y compris le caractère NUL final)
(ces chiffres peuvent changer en fonction de la version PHP)
Vous devez arrondir à un multiple de 4 octets en raison de l'alignement de la mémoire. Si la variable est dans l'espace global (pas à l'intérieur d'une fonction), elle allouera également 64 octets supplémentaires.
Donc, si vous souhaitez utiliser l'un des codes de cette page, vous devez vérifier que le résultat à l'aide de quelques cas de test simples (chaînes ou nombres) correspond à ces données en tenant compte de chacune des indications de ce post (tableau $ _GLOBAL, premier appel de fonction, tampon de sortie, ...)