Un cache PHP comme xcache
permet de stocker en RAM n’importe quelle donnée, pour la retrouver par la suite. Voici un script permettant d’exploiter ce système pour mémoriser et récupérer le résultat d’une fonction dont le calcul, lourd, serait fait de manière répétée.
//
// Cache function W()
// (c) Fil 2009 - Double-licensed under the GNU/LGPL and MIT licenses
// http://zzz.rezo.net/-SPIP-
// $ttl = time to live
// $vars = other variables that could change the result
// (the function's variables are automatically taken into account)
//
# xcache ?
if (function_exists('xcache_set')) {
function W($vars=null, $ttl=3600) {
$trace = debug_backtrace();
$trace = $trace[1];
$key = __FILE__ . md5(
$trace['function']
.serialize($trace['args'])
.serialize($vars)
);
if (!xcache_isset($key)) {
xcache_set($key, null, $ttl);
$r = call_user_func_array($trace['function'], $trace['args']);
xcache_set($key, $r, $ttl);
return $r;
}
return xcache_get($key);
}
}
# elementary compatibility
else {
function W(){return null;}
}
Pour exploiter ce script dans n’importe quelle fonction PHP, il suffit d’ajouter au début de la fonction une très courte ligne de code :
if (null!==$W=W())return$W;
Par exemple, la fonction suivante, qui prend 3 secondes à calculer :
function calcul_lourd($x, $y) {
sleep(3);
return sqrt($x*$y);
}
peut être mise en cache très simplement :
function calcul_lourd($x, $y) {
if(null!==$W=W())return$W;
sleep(3);
return sqrt($x*$y);
}
Le calcul ne prendra 3 secondes que la première fois, les hits suivants ne prenant qu’environ 0,00001 seconde.
Quand ne pas l’utiliser
Bien entendu toutes les fonctions ne doivent pas être optimisées de cette manière. Exemples de fonctions à ne pas traiter : une fonction peut faire des choses (écrire une donnée dans une base de données...), produire du contenu à l’écran (
print ...
), ou encore donner un résultat changeant (selon l’heure, ou le hasard). Dans ce cas, on ne peut pas utiliser cette méthode sur la fonction en question ; une fonction peut être suffisamment rapide pour que le gain apporté ne compense pas le surcoût engendré par le script, qui est d’environ 10 microsecondes ;
si une fonction est appelée avec des paramètres qui changent à chaque fois, il est inutile de stocker son résultat !
Bref, il s’agit de repérer les fonctions qui méritent d’être optimisées : celles prennent un peu de temps à calculer (plus de 10 microsecondes), qui voient passer les mêmes arguments de façon répétée, et qui ne produisent pas d’action ni d’affichage. Enfin, faire attention à ne pas sur-optimiser : si une fonction A appelle une fonction B, il n’est pas nécessaire d’optimiser A si le gros du calcul se fait à l’intérieur de B.
Paramètres supplémentaires
Dans le cas où le résultat de la fonction à optimiser dépend de paramètres qui ne figurent pas dans ses arguments (par exemple de variables globales), il faut l’indiquer au script :
if(null!==$W=W($parametres))return$W;
Par exemple pour optimiser la fonction suivante :
function bonjour_vous() {
if (isset($_SESSION['auteur'])) {
mysql_query();
.../...
return 'Bonjour '.$nom;
}
return 'Bonjour anonyme';
}
on appellera :
function bonjour_vous() {
if(null!==$W=W($_SESSION['auteur']))return$W;
if (isset($_SESSION['auteur'])) {
mysql_query();
.../...
return 'Bonjour '.$nom;
}
return 'Bonjour anonyme';
}
Dans cette écriture $parametres
peut être n’importe quel type de variable : nombre, chaîne de caractères, tableau...
Durée de vie du cache
Par défaut la durée de vie du cache ($ttl
) est de 3600 secondes. On peut préciser une valeur différente en second argument de la fonction W()
. Par exemple pour indiquer un TTL de 30 secondes :
if(null!==$W=W(null,30))return$W;
Crédits
Ce script écrit par mézigue est distribué sous la double licence GNU/LPGL et MIT. Vous pouvez donc l’utiliser, grosso modo, comme bon vous semble, à condition de conserver ma signature. Les suggestions d’améliorations sont les bienvenues !
Distribution
Le script peut être utilisé tel quel dans vos projets PHP.
Il est aussi distribué en plugin pour SPIP, à télécharger : SVN :
svn://zone.spip.org/spip-zone/_plugins_/xcache/
ZIP :
http://files.spip.org/spip-zone/xcache.zip
7 Messages de forum