La mémoire et PHP

Christophe Villeneuve

nAcademy Le 31 octobre 2013
Sommaire

Mémoire, qu'est ce ?
• Octets, Bytes, Word, Heap...

• Surveiller / Mesurer la consommation de mémoire
• Carte d'analyse d'image

• Comprendre la consommation de mémoire PHP
• Zend memory Manager

• Mesurer la consommation de processus mémoire
nAcademy Le 31 octobre 2013
Indispensable
La mémoire indispensable
Hardware

nAcademy Le 31 octobre 2013

Software
Les étapes pour PHP
✔

Start (allocations)

✔

Compilation
✔

✔

✔

Analyse
Compilation (OP Code Génération)

Execute
✔

✔

✔

Interprétation

Start

Zend_compile_file()

Zend_execute()

Execution Memoire virtuelle

Libérations

nAcademy Le 31 octobre 2013

Out
Temps de chargement d'une page
<?php
$time_start = microtime(true);
for ($i=0 ; $i<1000000; $i++)
{
//le test
}
$time_end = microtime(true);
$time = $time_end - $time_start;
Résultat sans APC ou Memcache
echo 'Durée : '.$time.' secondes<br/>';
?>

nAcademy Le 31 octobre 2013

Duree : 0.2619161605835 secondes
La place de la mémoire... dans un processus
✔

Chaque lancement d'un logiciel ou d'une application
= Mémoire Virtuelle (VM)

✔

La mémoire virtuelle VS mémoire physique (PM)
= RAM

✔

Identification
✔
✔

✔

VM : Adresse position Kernel
PM : Adresse utilisée dans une table

En résumé, chaque processus a l'illusion d'une adresse
mémoire Physique (PM)
nAcademy Le 31 octobre 2013
Monitoring de la mémoire
Surveillance de la mémoire serveur Linux

nAcademy Le 31 octobre 2013
Obtenir le détail de la mémoire détaillé
Cat / proc/{PID}/ statut 

mémoire virtuelle utilisée
mémoire physique utilisée
Taille mémoire data VM
Taille mémoire Text VM
✔
✔

Autres outils :
Autres outils :
✔
✔ Vmstats
Vmstats
✔
✔ Smem
Smem
✔
✔

Valgrind
Valgrind

nAcademy Le 31 octobre 2013
Et...
Mémoire et PHP (1/2)
✔

PHP

comme les autres
✔

nAcademy Le 31 octobre 2013

C'est juste un processus
Codé en C
Mémoire et PHP (2/2)

➢

➢

PHP
Def. consommation

<?php 
passthru(
             sprintf(
              cat /proc/%d/status,
              getmypid()
                      )
            );
?>

nAcademy Le 31 octobre 2013
Utilisation de la mémoire (version de PHP)

http://php.net/manual/fr/features.gc.performance-considerations.php
nAcademy Le 31 octobre 2013
Comportement des alertes
Fatal error:
Allowed memory size of 134217728 bytes
exhausted (tried to allocate 54 bytes)

Fatal error: Out of memory (allocated 786432) (tried to
allocate 24576 bytes) in...

nAcademy Le 31 octobre 2013
Mémoire interne de PHP avec PHPinfo()
✔

Appelé Zend Memory Manager

✔

Actif par défaut

nAcademy Le 31 octobre 2013
Pourquoi Zend Memory Manager
✔
✔

<?php
echo 'hello world' ;
?>

✔

Zend Memory Manager
libc_malloc()

mmap()

Kernel

nAcademy Le 31 octobre 2013

Layer ?

Couche personnalisée
Utile pour ces extensions
Permet
✔ de limiter la taille
✔ Son utilisation
✔ Mise en cache des blocs
✔ Préallocation
✔ Evite la fragmentation
✔ Etc.
Mesurer la quantité de mémoire nécessaire
Mémoire non utilisée
memory_get_usage()
X

memory_get_usage (true)

memory_limit()

memory_get_peak_usage (false)
Mémoire allouée

nAcademy Le 31 octobre 2013
Au niveau du code memory_get_usage ()
✔

✔

Indique combien vos blocs alloués consomment
✔
Pagination possible en Mémoire Physique (PM)
✔
Cela ne compte pas pile
✔
Cela ne compte pas toute extension qui
contourne
Zend Memory Manager est plus de précis
✔
Associé Valgrind pour des gros volumes
✔
Ne compte pas les bibliothèques liées
✔
Mais c'est un très bon indicateur à suivre

nAcademy Le 31 octobre 2013
Mesure allocation dynamique Zend Memory Manager
<?php
ini_set(memory_limit, -1);
function heap()
{
return shell_exec(sprintf(grep "VmRSS:" /proc/%s/status, getmypid()));
}
echo heap();
$a = range(1, 1024*1024);
echo heap();
unset($a);
echo heap();
?>
nAcademy Le 31 octobre 2013
Exemple d'utilisation (en octets)
Objet

Tableau
<?php

<?php

echo memory_get_usage();

echo memory_get_usage();

$a = array( 1024*1024);
echo memory_get_usage();

235088

235552

unset($a);
echo memory_get_usage();

$a = str_repeat("", 1024*1024);
echo memory_get_usage();

unset($a);
echo memory_get_usage();
235088

?>

?>
nAcademy Le 31 octobre 2013

235088

235256

235088
Les variables en PHP
Type de variables PHP
✔

Taille de mémoire pour chaque type
✔
✔

string : sizeof the string + 1 into char *

✔

double : 8 bytes

✔

✔

long : 8 bytes

pointer : 8 bytes

Zval
✔

✔

PHP stocke les variables dans les structures C

PHP faiblement typé
nAcademy Le 31 octobre 2013
Comportement par l'exemple
<?php
$a = 'foo' ;
?>

Zval
(string) 'foo'
$a
is_ref=0 refcount=1

<?php
$a = 'foo' ;
$b = $a ;
?>

nAcademy Le 31 octobre 2013

$a
$b

(string) 'foo'
is_ref=0 refcount=2
Manipuler la variable
<?php
$a = 'foo' ;

(string) 'foo'
$a
is_ref=0 refcount=1

$a

$b = $a ;

$b

$b

$a = 17 ;
?>
nAcademy Le 31 octobre 2013

(string) 'foo'
is_ref=0 refcount=2

(string) 'foo'
is_ref=0 refcount=1
(int) 17

$a

is_ref=0 refcount=1
Plus complexe... quoi que
<?php
$a = 'foo' ;
$b = $a ;
$c = $b ;
$b = 17 ;
unset ($a) ;
?>
$c

$b

$b

(string) 'foo'

$a

(string) 'foo'

$c

is_ref=0 refcount=2

is_ref=0 refcount=1

(int) 17
is_ref=0 refcount=1
nAcademy Le 31 octobre 2013

$a
$a

$a
$b

(string) 'foo'
is_ref=0 refcount=1
(string) 'foo'
is_ref=0 refcount=2

(string) 'foo'
is_ref=0 refcount=3

$c

$b

(int) 17
is_ref=0 refcount=1
Comparaison : echo VS print

= Fonctions presque identiques
nAcademy Le 31 octobre 2013

© http://www.phpbench.com/
Comparaison : isSet() VS empty() VS is_array()

= isSet() and empty() sont identiques

nAcademy Le 31 octobre 2013

© http://www.phpbench.com/
Comparaison : double (") VS single (') quotes

= c'est satisfaisant

nAcademy Le 31 octobre 2013

© http://www.phpbench.com/
Comparaison : For VS While

= While plus rapide

nAcademy Le 31 octobre 2013

© http://www.phpbench.com/
Comparaison : foreach() VS for() VS while(list() = each())

100 elements, 24byte key and 10k data per entry

= Avantage Foreach

nAcademy Le 31 octobre 2013

© http://www.phpbench.com/
Autres indicateurs de consommation de mémoire
•
•
•
•
•
•
•
•

_POST ? 160 B
_GET ? 368 B
_COOKIE ? 232 B
_FILES ? 48 B
indice ? 112 B
indicestart ? 112 B
indicestop ? 112 B
datas ? 25.21 MB

nAcademy Le 31 octobre 2013
Ne pas oublié
✔

✔

Regard plus attentif
✔
Class
✔
Boucle
Eviter si possible
✔
RegEXP
✔
Trop grandes classes

nAcademy Le 31 octobre 2013
Surveiller la consommation de mémoire
✔
✔
✔
✔

✔

Peu d'outils (pour PHP)
memory_get_usage()
OS help (/proc , pmap , etc...)
Pour éviter les risques de fuite mémoire 
✔
Valgrind, mtrace, ccmalloc...
PHP Extensions
✔
Xdebug : xdebug_debug_val
✔
memprof https://github.com/arnaud-lb/php-memory-profiler
✔
memtrack

nAcademy Le 31 octobre 2013
Merci

Sources : 
Slides : Julien PAULI
Site web :  www.developpez.com
nAcademy Le 31 octobre 2013

La mémoire et PHP

  • 1.
    La mémoire etPHP Christophe Villeneuve nAcademy Le 31 octobre 2013
  • 2.
    Sommaire Mémoire, qu'est ce? • Octets, Bytes, Word, Heap... • Surveiller / Mesurer la consommation de mémoire • Carte d'analyse d'image • Comprendre la consommation de mémoire PHP • Zend memory Manager • Mesurer la consommation de processus mémoire nAcademy Le 31 octobre 2013
  • 3.
  • 4.
  • 5.
    Les étapes pourPHP ✔ Start (allocations) ✔ Compilation ✔ ✔ ✔ Analyse Compilation (OP Code Génération) Execute ✔ ✔ ✔ Interprétation Start Zend_compile_file() Zend_execute() Execution Memoire virtuelle Libérations nAcademy Le 31 octobre 2013 Out
  • 6.
    Temps de chargementd'une page <?php $time_start = microtime(true); for ($i=0 ; $i<1000000; $i++) { //le test } $time_end = microtime(true); $time = $time_end - $time_start; Résultat sans APC ou Memcache echo 'Durée : '.$time.' secondes<br/>'; ?> nAcademy Le 31 octobre 2013 Duree : 0.2619161605835 secondes
  • 7.
    La place dela mémoire... dans un processus ✔ Chaque lancement d'un logiciel ou d'une application = Mémoire Virtuelle (VM) ✔ La mémoire virtuelle VS mémoire physique (PM) = RAM ✔ Identification ✔ ✔ ✔ VM : Adresse position Kernel PM : Adresse utilisée dans une table En résumé, chaque processus a l'illusion d'une adresse mémoire Physique (PM) nAcademy Le 31 octobre 2013
  • 8.
  • 9.
    Surveillance de lamémoire serveur Linux nAcademy Le 31 octobre 2013
  • 10.
    Obtenir le détailde la mémoire détaillé Cat / proc/{PID}/ statut  mémoire virtuelle utilisée mémoire physique utilisée Taille mémoire data VM Taille mémoire Text VM ✔ ✔ Autres outils : Autres outils : ✔ ✔ Vmstats Vmstats ✔ ✔ Smem Smem ✔ ✔ Valgrind Valgrind nAcademy Le 31 octobre 2013
  • 11.
  • 12.
    Mémoire et PHP(1/2) ✔ PHP comme les autres ✔ nAcademy Le 31 octobre 2013 C'est juste un processus Codé en C
  • 13.
    Mémoire et PHP(2/2) ➢ ➢ PHP Def. consommation <?php  passthru(              sprintf(               cat /proc/%d/status,               getmypid()                       )             ); ?> nAcademy Le 31 octobre 2013
  • 14.
    Utilisation de lamémoire (version de PHP) http://php.net/manual/fr/features.gc.performance-considerations.php nAcademy Le 31 octobre 2013
  • 15.
    Comportement des alertes Fatalerror: Allowed memory size of 134217728 bytes exhausted (tried to allocate 54 bytes) Fatal error: Out of memory (allocated 786432) (tried to allocate 24576 bytes) in... nAcademy Le 31 octobre 2013
  • 16.
    Mémoire interne dePHP avec PHPinfo() ✔ Appelé Zend Memory Manager ✔ Actif par défaut nAcademy Le 31 octobre 2013
  • 17.
    Pourquoi Zend MemoryManager ✔ ✔ <?php echo 'hello world' ; ?> ✔ Zend Memory Manager libc_malloc() mmap() Kernel nAcademy Le 31 octobre 2013 Layer ? Couche personnalisée Utile pour ces extensions Permet ✔ de limiter la taille ✔ Son utilisation ✔ Mise en cache des blocs ✔ Préallocation ✔ Evite la fragmentation ✔ Etc.
  • 18.
    Mesurer la quantitéde mémoire nécessaire Mémoire non utilisée memory_get_usage() X memory_get_usage (true) memory_limit() memory_get_peak_usage (false) Mémoire allouée nAcademy Le 31 octobre 2013
  • 19.
    Au niveau ducode memory_get_usage () ✔ ✔ Indique combien vos blocs alloués consomment ✔ Pagination possible en Mémoire Physique (PM) ✔ Cela ne compte pas pile ✔ Cela ne compte pas toute extension qui contourne Zend Memory Manager est plus de précis ✔ Associé Valgrind pour des gros volumes ✔ Ne compte pas les bibliothèques liées ✔ Mais c'est un très bon indicateur à suivre nAcademy Le 31 octobre 2013
  • 20.
    Mesure allocation dynamiqueZend Memory Manager <?php ini_set(memory_limit, -1); function heap() { return shell_exec(sprintf(grep "VmRSS:" /proc/%s/status, getmypid())); } echo heap(); $a = range(1, 1024*1024); echo heap(); unset($a); echo heap(); ?> nAcademy Le 31 octobre 2013
  • 21.
    Exemple d'utilisation (enoctets) Objet Tableau <?php <?php echo memory_get_usage(); echo memory_get_usage(); $a = array( 1024*1024); echo memory_get_usage(); 235088 235552 unset($a); echo memory_get_usage(); $a = str_repeat("", 1024*1024); echo memory_get_usage(); unset($a); echo memory_get_usage(); 235088 ?> ?> nAcademy Le 31 octobre 2013 235088 235256 235088
  • 22.
  • 23.
    Type de variablesPHP ✔ Taille de mémoire pour chaque type ✔ ✔ string : sizeof the string + 1 into char * ✔ double : 8 bytes ✔ ✔ long : 8 bytes pointer : 8 bytes Zval ✔ ✔ PHP stocke les variables dans les structures C PHP faiblement typé nAcademy Le 31 octobre 2013
  • 24.
    Comportement par l'exemple <?php $a= 'foo' ; ?> Zval (string) 'foo' $a is_ref=0 refcount=1 <?php $a = 'foo' ; $b = $a ; ?> nAcademy Le 31 octobre 2013 $a $b (string) 'foo' is_ref=0 refcount=2
  • 25.
    Manipuler la variable <?php $a= 'foo' ; (string) 'foo' $a is_ref=0 refcount=1 $a $b = $a ; $b $b $a = 17 ; ?> nAcademy Le 31 octobre 2013 (string) 'foo' is_ref=0 refcount=2 (string) 'foo' is_ref=0 refcount=1 (int) 17 $a is_ref=0 refcount=1
  • 26.
    Plus complexe... quoique <?php $a = 'foo' ; $b = $a ; $c = $b ; $b = 17 ; unset ($a) ; ?> $c $b $b (string) 'foo' $a (string) 'foo' $c is_ref=0 refcount=2 is_ref=0 refcount=1 (int) 17 is_ref=0 refcount=1 nAcademy Le 31 octobre 2013 $a $a $a $b (string) 'foo' is_ref=0 refcount=1 (string) 'foo' is_ref=0 refcount=2 (string) 'foo' is_ref=0 refcount=3 $c $b (int) 17 is_ref=0 refcount=1
  • 27.
    Comparaison : echoVS print = Fonctions presque identiques nAcademy Le 31 octobre 2013 © http://www.phpbench.com/
  • 28.
    Comparaison : isSet()VS empty() VS is_array() = isSet() and empty() sont identiques nAcademy Le 31 octobre 2013 © http://www.phpbench.com/
  • 29.
    Comparaison : double(") VS single (') quotes = c'est satisfaisant nAcademy Le 31 octobre 2013 © http://www.phpbench.com/
  • 30.
    Comparaison : ForVS While = While plus rapide nAcademy Le 31 octobre 2013 © http://www.phpbench.com/
  • 31.
    Comparaison : foreach()VS for() VS while(list() = each()) 100 elements, 24byte key and 10k data per entry = Avantage Foreach nAcademy Le 31 octobre 2013 © http://www.phpbench.com/
  • 32.
    Autres indicateurs deconsommation de mémoire • • • • • • • • _POST ? 160 B _GET ? 368 B _COOKIE ? 232 B _FILES ? 48 B indice ? 112 B indicestart ? 112 B indicestop ? 112 B datas ? 25.21 MB nAcademy Le 31 octobre 2013
  • 33.
    Ne pas oublié ✔ ✔ Regardplus attentif ✔ Class ✔ Boucle Eviter si possible ✔ RegEXP ✔ Trop grandes classes nAcademy Le 31 octobre 2013
  • 34.
    Surveiller la consommationde mémoire ✔ ✔ ✔ ✔ ✔ Peu d'outils (pour PHP) memory_get_usage() OS help (/proc , pmap , etc...) Pour éviter les risques de fuite mémoire  ✔ Valgrind, mtrace, ccmalloc... PHP Extensions ✔ Xdebug : xdebug_debug_val ✔ memprof https://github.com/arnaud-lb/php-memory-profiler ✔ memtrack nAcademy Le 31 octobre 2013
  • 35.