Performance Zend_Cache

Comparatif des performances des backends « lents »

Cet article est un comparatif des performances des deux backends lents du framework Zend. Il donne des indications pour savoir quand utiliser tel ou tel backend.

7 commentaires Donner une note à l'article (4.5)

Article lu   fois.

Les deux auteurs

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

1. Présentation de l'auteur

Maxime Varinard est chef de projet chez Vaisonet (http://www.vaisonet.com), société utilisant notamment PHP 5 dans le développement d'applications e-commerce. Vaisonet utilise le framewok Zend dans le cadre de ses développements et notamment Zend_Cache afin d'en optimiser les performances.

2. Généralités

Quand le code à été optimisé, un système de cache peut être nécessaire pour accélérer une application Web. Un système de cache peut ne pas être pertinent, car il oblige à utiliser des données qui ne sont potentiellement plus à jour et consomme également des ressources supplémentaires. Il est donc essentiel de mesurer l'impact et la réelle utilité d'un système de cache.

Plusieurs systèmes de cache existent : le cache au niveau du navigateur Web, les caches type proxy, les caches d'opcodes. Cet article se concentre sur le cache au niveau de l'application Web elle-même et en particulier le cache du Framework php de Zend (http://framework.zend.com/).

Les backends de Zend_Cache sont divisés en deux parties :

  • les caches lents : ils stockent les données dans des fichiers. Ils sont peu rapides, mais peuvent stocker des grandes quantités de données ;
  • les caches rapides : ils stockent les données dans la mémoire vive. Ils sont rapides, mais sont limités par la capacité de la RAM.

Cet article se concentre sur les caches lents disponibles sans serveur spécifique (memcached ou Zend Server par exemple). Il ne s'agit donc absolument pas d'un comparatif exhaustif, mais d'un comparatif des deux grands backends : File et SQLite.

3. Méthodologie

Un script PHP charge le framework Zend en autoload. Les temps suivants sont mesurés pour le backend File et le backend Sqlite :

  • initialisation du cache ;
  • création de 100 entrées distinctes dans le cache ;
  • affichage des 100 entrées créées ;
  • suppression des 100 entrées de cache.

La machine de test est équipée de Windows Vista et de XAMPP. Les mesures ont été loguées dans un fichier CSV et répétées 85 fois à l'aide de l'utilitaire Apache ab, puis les moyennes on été calculées en rejetant les 5 % de valeurs aux extrêmes.

4. Résultats

Les valeurs chiffrées n'ont que peu d'intérêt. Ce qu'il est intéressant de quantifier est le rapport entre SQLite et File. La durée d'exécution en seconde est reportée sur l'axe vertical.

Image non disponible
Image non disponible

Comme on pouvait s'y attendre :

  • l'initialisation du cache SQLite est plus lente (x3,5) ;
  • la création d'une entrée de cache est beaucoup plus lente avec SQLite (x6,8) ;
  • la lecture d'une entrée de cache est extrêmement plus rapide avec SQLite (x54) ;
  • la suppression du cache est plus rapide avec SQLite (x4,2).

Un rapide calcul indique que si on lit plus de 4,5 fois le cache que l'on l'écrit, SQLite est plus intéressant en termes de performance. Bien sûr cette valeur peut évoluer selon le volume de données, mais l'ordre de grandeur est fixé.

Avec une durée de rafraîchissement du cache, il y a fort à parier que l'on atteigne facilement cette valeur limite de 4,5. SQLite apparaît donc comme la solution à mettre en œuvre pour un cache rapide.

5. Différences de fonctionnement File / SQLite

Le cache « File » du framework Zend écrit deux fichiers par donnée mise en cache. Le premier fichier contient les métadonnées du cache et le second les données.

Le cache « SQLite » met toutes les données mises en cache dans un seul fichier, au format spécifique optimisé SQLite. Cependant, la base peut-être verrouillée. En effet, si une donnée est en cours d'écriture, un LOCK est apposé sur le fichier SQLite et tant que l'écriture n'est pas terminée, les données ne seront pas lues et donc les données en cache ne seront pas disponibles.

Imaginons que votre application est très volumineuse, il est possible que des écritures soient fréquentes, même si les lectures sont bien plus nombreuses. Du coup, la base étant souvent verrouillée, même si la lecture est très rapide, l'accès au cache peu globalement être plus lent.

Il est donc difficile de savoir à l'avance lequel du cache File ou du cache SQLite va être le plus rapide. La solution est de suivre la durée d'exécution de vos scripts et de tester les deux backends.

6. Supervision du temps d'exécution

La solution présentée ici utilise une sonde MRTG (http://oss.oetiker.ch/mrtg/) et explique l'esprit général de la solution, mais ne la détaille pas point par point.

6-A. Enregistrer les durées du script

La classe ci-dessous le permet de manière simple. Il suffit d'inclure la classe et de créer l'objet au début du script. Les méthodes magiques PHP 5 lancent le chronomètre au démarrage et sauvent les données à la fin du script.

Les informations sont stockées simplement sur une ligne d'une table MySQL.

 
Sélectionnez
<?php<code langage="php"><![CDATA[<?php
 *  Exemple d'utilisation developpez.com
 */
class loggeur_php
{
    private $temps;
    /**
     * Début de l'analyse     *
     */
    public function __construct()
    {
        $this->temps = microtime(true);
    }
    
    /**
     * Clôture de l'analyse en loggant les informations dans la base de données
     */
    public function __destruct()
    {
        $duree = microtime(true) - $this->temps;
        $linkP = mysqli_connect('localhost', 'supervision', 'pass', 'supervision');    
        $sql = "UPDATE duree SET somme=somme+$duree, nombre=nombre+1 WHERE id=1 LIMIT 1";
        mysqli_query($linkP, $sql);
        mysqli_close($linkP);
    }
}
?>

6-B. La sonde MRTG

Voici un exemple de sonde MRTG, fichier à rendre exécutable.

 
Sélectionnez
#!/usr/bin/php
<?php
/* 
 * Permet de donner les perfs à MRTG puis les réinitialise
 */

$linkP = mysql_connect('localhost', 'supervision', 'pass');
if ($linkP) mysql_select_db('supervision');
$sql = 'select * from performance_moyenne_v41 where id=1 limit 1';
$result = mysql_query($sql, $linkP);
while($stat = mysql_fetch_array($result))
{
    $moyenne = $stat['somme'] / $stat['nombre'];
    echo round($moyenne, 4)*1000 . "\n " . "\n0\n0";
}

$sql2 = 'UPDATE performance_moyenne_v41 SET somme=0, nombre=0 WHERE id=1 LIMIT 1';
mysql_query($sql2, $linkP);

mysql_close($linkP);
?>

6-C. Le fichier de configuration MRTG, à compléter

 
Sélectionnez
Target[***]: `/home/mrtg-sys/perf-log-mrtg.php`
PageTop[***]: <h1>Perfs</h1>
Options[***]: absolute, growright, gauge
MaxBytes[***]: 1500
Title[***]: Perfs
Ylegend[***]: sec * 1000
Legend1[***]: vitesse moyenne
Legend2[***]: ecart type
LegendI[***]: vitesse moyenne
LegendO[***]: ecart type
ShortLegend[***]: sec * 1000

Une fois le fichier de configuration MRTG complété, il faut régénérer le fichier index MRTG.

6-D. Les résultats

Image non disponible

On obtient des graphiques permettant d'évaluer l'application en production avec utilisation des deux systèmes de cache.

7. Conclusion

Selon le cas, l'un ou l'autre des deux backends de cache du Zend Framework peut-être plus performant, mais il est quasiment impossible de le prévoir. Aussi, seul le suivi de son application peut permettre ce choix. Bien sûr, cela peut même servir à évaluer la vitesse de l'application sans système de cache, ou avec des serveurs de cache. Il s'agit d'une bonne pratique à intégrer dans vos projets importants.

Merci pour leurs relectures à jacques_jean et dourouc05

7 commentaires Donner une note à l'article (4.5)

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2010 Maxime Varinard - Vaisonet. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.