metronome frequence lru

Implémenter un buffer LRU

Une variante du buffer FIFO qui utilise le principe du LRU

Date de publication : 2009-11-19 11:37:36

Cet article présente une évolution de la technique présentée dans mon article utilisation d'un buffer fifo.

Le principe du buffer reste le même, c'est à dire cacher en mémoire des résultats de requêtes SQL pour limiter le nombre de requêtes effectuées par l'applicatif php.

Dans la méthode précédente la taille du tampon mémoire était gérée avec le principe de la file FIFO (First In First Out). Quand le tampon était considéré comme plein, et qu'un nouvel élément devait être ajouté, on effaçait le plus vieil élément du tableau pour faire de la place pour le nouveau.

Aujourd'hui je vais vous montrer comment remplacer le FIFO par un LRU (Last Recently Used) pour améliorer les performances.

Principe du LRU

Dans notre cas d'utilisation, le LRU est utilisé pour déterminer quels éléments garder dans le buffer lorsque celui ci est plein.

Inversement, lorsque le tampon est plein et que l'on doit ajouter un nouvel élément, on supprime donc l'élément le moins récemment utilisé pour faire de la place.

Exemple d'implémentation du LRU

Le code suivant provient de mon précédent article sur le buffer fifo, les seules lignes de code ajoutées servent à déplacer l'élément appelé en fin de tableau.

Les éléments sont ordonnés dans le buffer du moins récemment utilisé au dernier élément utilisé.

Lorsque l'on a besoin de faire de la place dans le tampon on supprime le premier élément pour garder en mémoire les derniers éléments utilisés.


<?php
/**
* Retourne le pseudonyme d'un utilisateur en fonction de son identifiant
*
* @param integer $usrId
* @return string
*/
function getUserPseudo($usrId)
{
/*Tableau qui nous sert de tampon mémoire*/
static $buffer = array();
/*Entier qui contient le nombre d'elements du tampon*/
static $countBuffer = 0;

/*On crée un pointeur sur l'index du tableau*/
$pseudo = &$buffer[$usrId];

/*Si on a déjà le pseudo dans le tampon on le retourne sans refaire de requete en base de données*/
if(isset($pseudo) === true)
{
/*On déplace l'élement en fin de buffer car c'est le dernier utilisé*/
unset($buffer[$usrId]);
$buffer[$usrId] = $pseudo;
return $pseudo;
}
/*Si le tampon est plein on efface le premier élément qui correspond à l'élément le moins récemment utilisé*/
if($countBuffer > 999)
{
list($firstIndex, ) = each($buffer);
unset($buffer[$firstIndex]);
}
/*Dans l'autre cas on incrémente le compteur*/
else
{
$countBuffer++;
}
/*On récupére l'objet base de données*/
$db = Database::getInstance();
/*On fait la requete pour récupérer le pseudo*/
$pseudo = $db->select('SELECT PSEUDO FROM USERS WHERE USR_ID='.(int)$usrId.' LIMIT 1');
if(isset($pseudo[0]) === false)
{
$pseudo = '';
}
else
{
$pseudo = $pseudo[0]['PSEUDO'];
}
/*On retourne le pseudo*/
return $pseudo;
}
?>

Enjoy ;)

Image : Nigel Appleton

 
 

b1n@sp1n