10 octobre 2008

Les performances des systèmes de cache en PHP en question.

Les sites WEB se doivent d'être rapide. Dans le cas contraire, le développeur va chercher à optimiser son application et il peut être tenté par des systèmes de cache. Mais quel système de cache choisir ? Sont-il vraiment efficaces ?

Lieu de stockage

Le principal critère de sélection d'un mécanisme de cache est son type de stockage. En voici 3 :

  • Système de fichiers
  • Mémoire partagée
  • Base de données

Pour chaque type, il existe plusieurs logiciels ou
techniques permettant de réaliser le stockage. Pour le système de fichiers, on trouve différents formats de fichier. Pour la mémoire partagée, on trouve : APC, Xdebug, Memcached. Et pour les bases de données, on trouve : Sqlite, Mysql, etc ...

Implémentation en PHP

Pour chaque méthode de stockage et pour obtenir un mécanisme de cache, il est nécessaire d'encapsuler les primitives PHP. On trouve de nombreuses API réalisant ce travail.

A l'heure actuelle, Le Zend Framework fournit une couche d'abstraction pour la majorité des méthodes de stockage citées ci-avant. C'est donc un bon moyen de tester la pertinence et la rapidité des différents types de stockage.

Il est difficile d'évaluer l'impact des différentes implémentations en PHP d'un moteur de cache. Il n'est donc pas question ici de les comparer.

Code à tester

Pour évaluer les performances des différentes méthodes de stockage, on va utiliser 2 séries.

Série 1 : 1 * 100000

La première série stocke en cache une seule information d'une taille importante. Par exemple avec le Zend_Framework, on aura le code suivant
:


$cache = Zend_Cache::factory('Core', $backend, $frontendOptions,
$backendOptions);

if (!($data = $cache->load($id))) {

   $data = '';
   for ($i = 0; $i < 100000; $i++) {
       $data .= '. ';
   }

   $cache->save($data);
   echo '<h1>SAVED</h1>';
}
else echo '<h1>CACHED</h1>';

echo '<div>'.$data.'</div>';

Série 2 : 1000 * 100

La deuxième série stocke en cache plusieurs informations de petite taille mais pour un volume total identique à la première série. Par exemple avec le Zend_Framework, on aura le code suivant :


$cache = Zend_Cache::factory('Core', 'APC', $frontendOptions,
$backendOptions);

$c = false;
$datas = '';
for ($j = 0; $j < 1000; $j++) {
   $id = 'ID'.$j;
   if (!($data = $cache->load($id))) {

       $data = '';
       for ($i = 0; $i < 100; $i++) {
           $data .= '. ';
       }

       $cache->save($data, $id);
       $c = true;
   }
   $datas .= $data;
}
if ($c)
   echo '<h1>SAVED</h1>';
else
   echo '<h1>CACHED</h1>';

echo '<div>'.$datas.'</div>';

Banc d'essais

Pour évaluer les performances, on utilisera en parallèle : ab, httperf
et siege. Ces 3 logiciels permettent de simuler une charge importante sur un serveur WEB tout en mesurant les temps de réponses.

Chacun de ces logiciels est lancé séquentiellement 4 fois, à chaque fois on calcul le nombre moyen de requêtes par seconde.

La comparaison portera sur :

  • Zend_Cache, backend : FILE
  • Zend_Cache, backend : APC
  • Zend_Cache, backend : SQLITE
  • Pxxo 5.4
  • Pxxo 5.4.1

Résultats

Les chiffres sont obtenus en faisant la médiane des 4 moyennes du nombre de requête par seconde. Le tout étant arrondi par défaut.

Série 1 : 1 * 10000 (sans APC)

ab httperf siege
php (sans cache) 20 11 22
pxxo (5.4.1) 208 111 216
pxxo (5.4) 265 136 127
zend_cache (apc) - - -
zend_cache (file) 153 84 156
zend_cache (sqlite) 129 69 134

Série 1 : 1 * 100000 (avec APC)

ab httperf siege
php (sans cache) 22 11 21
pxxo (5.4.1) 464 210 424
pxxo (5.4) 436 202 402
zend_cache (apc) 361 178 344
zend_cache (file) 295 144 278
zend_cache (sqlite) 136 109 208

Série 2 : 1000 * 100 (sans APC)

ab httperf siege
php (sans cache) 21 10 21
pxxo (5.4.1) 8 5 9
pxxo (5.4) 6 3 6
zend_cache (apc) - - -
zend_cache (file) 3 1 3
zend_cache (sqlite) 6 3 6

Série 2 : 1000 * 100 (avec APC)

ab httperf siege
php (sans cache) 22 11 21
pxxo (5.4.1) 45 22 44
pxxo (5.4) 8 4 8
zend_cache (apc) 29 15 29
zend_cache (file) 3 1 3
zend_cache (sqlite) 6 3 6

Conclusion

Comme d'habitude, tout va dépendre de votre contexte. Cependant, on
peut tirer quelques enseignements de ce ban d'essai.

  • Tout d'abord, il est efficace d'utiliser un système de mise en cache pour éviter un traitement long. Mais, plus on va utiliser le système de mise en cache, moins il devient intéressant de l'utiliser.
  • Ensuite, ce test confirme que c'est toujours mieux d'utiliser APC ou du moins de l'activer. Cependant, APC n'est pas toujours disponible et il convient de trouver une solution de rechange.
  • Si le besoin de mise en cache se limite à une seule information, vous pouvez utiliser Zend_Cache avec un stockage sous forme de fichiers (FILE). L'utilisation du backend APC vous apporte un peu plus mais ce n'est même pas obligatoire.
  • Plus vous souhaitez utiliser le stockage en cache, moins vous devez

utiliser le stockage par fichier et plus l'utilisation d'APC devient
obligatoire. Sans APC, SQLITE est une bonne solution de repli.

Le cas Pxxo

Pxxo utilise intensément la mise en cache. Depuis l'origine, le but était de pouvoir limiter le nombre de traitement d'un appel sur
l'autre et le tout de manière presque transparente pour le développeur.

Pxxo, jusqu'à la version 5.4, a toujours utilisé des mécanismes de cache tierces (Cache_Lite de PEAR au début puis Zend_Cache ensuite).
Maintenant, Pxxo utilise son propre mécanisme. Le but était d'améliorer les performances en mode non APC. Cette petite étude permet de confirmer que le but est atteint.

Code source du test

http://www.touv.fr/IMG/zip/cachesystem-2.zip

Aucun commentaire:

Publier un commentaire