Un système de caches actualisants et réentrants, avec son compilateur associé

Archive historique

Ceci est une archive périmée mais qui reste intéressante, parfois autant pour l’article que les commentaires associés.

Suite aux versions successives du compilateur de squelettes,
on propose ici une réécriture d’une vingtaine de fichiers de SPIP pour offrir
un SPIP à caches actualisés automatiquement. Incidemment, cette implémentation
ouvre la voie à une utilisation d’un même source SPIP pour plusieurs sites à la fois,
le répertoire CACHE étant délaissé au profit de tables SQL supplémentaires,
mieux adaptées à l’ajout d’informations concernant les caches.

Description

Rappelons que SPIP repose sur des fichiers nommés squelettes qui sont traduits
en fichiers PHP/MySQL par un compilateur. Ces fichiers sont exécutés lors des
accès au site pour produire les pages HTML envoyées aux navigateurs. Pour réduire la fréquence des calculs, ces pages sont mémorisées dans un cache,
de sorte qu’un nouvel accès au site avec la
même URL retourne immédiatement la page déjà calculée.
Le problème est que la base de données peut changer, le cache ne réflétant plus
le contenu actuel de la base, d’où l’implantation d’une durée de vie (les délais)
pour forcer un nouveau calcul à terme. Cette désynchronisation est cependant
heureusement absente dans le cas d’un forum, qui prend immédiatement en compte la présence d’un nouveau message.

Le présent système reprend la technique utilisée pour les forums, en la généralisant
et en la simplifiant. A l’installation, sont créées plusieurs tables de caches :

-  1. la table des squelettes compilés,
-  2. la table des pages produites par ceux-ci,
-  3-16. autant de tables de caches que de type de boucles.

Pour chaque squelette, le nouveau compilateur produit une fonction principale et ses sous-fonctions, qu’il range dans la table 1. Ces fonctions
reçoivent un argument supplémentaire : le nom de l’entrée dans la table 2 où sera rangé le résultat de la fonction principale. A chaque passage dans une boucle SPIP, ces fonctions mémorisent le numéro de l’objet référencé et le nom du cache où il est utilisé. A la fin de l’exécution, toutes ces valeurs sont rangées dans les tables de caches (3 à 16) correspondant à chaque boucle rencontrée.

A cette modification du compilateur, s’ajoute des modifications des scripts de ecrire/, de sorte que la modification d’un article entraine la destruction
de tous les caches de la table 2 associés à ce numéro d’article dans la table
des caches de type article, ce qui forcera un recalcul lorsqu’on accèdera aux URL
qui les avait créés. De plus, à chaque publication d’un nouvel article ou retrait d’un article précédemment publié, tous les caches référençant des articles seront détruits. ll en est de même pour les brèves.

Discussion

La présente implémentation présente deux défauts :

-  bien que tous les types de boucles aient leur table de caches associée,
seul les articles et les brèves provoqueront une actualisation des caches ; c’est provisoire,
je n’ai pas encore eu le temps de décortiquer les scripts gérant les autres types (— mais je veux bien un coup de main).

-  la destruction d’un cache repose sur une condition nécessaire mais non
suffisante : par exemple, la modification du corps d’un article mais pas de son titre
éliminera les pages qui ne référençaient que le titre. Symétriquement, une page
listant des articles indifférents au dernier article publié sera invalidée inutilement.
Il faudrait analyser les champs SQL consultés pour avoir une condition nécessaire ET suffisante ; ce n’est pas impossible en théorie (d’autant que le compilateur fait déjà cette analyse pour minimiser les échanges avec le serveur SQL) mais c’est beaucoup de travail.

En l’état, le choix d’une condition nécessaire plutot que suffisante est une garantie
que le cache est fiable, mais au prix de calculs plus fréquents qu’aujourd’hui a priori. Dès que le premier point sera achevé, on pourrait éliminer la gestion des
délais, qui est conservée pour l’instant.

Discussion technique

Remplacer des fichiers PHP par des tables implique d’abord de savoir simuler
sur un champ SQL un include de fichier ; cette opération ne figure pas dans
la documentaton officielle de PHP, mais on trouvera la solution dans les notes des utilisateurs de la version française : il faut écrire


eval(’ ?’ . ’ >’ . chaine)


(il fallait oser inventer une horreur pareille, d’autant que crontrairement à ce qui semblerait logique, il ne faut pas remettre ’<’ . ’ ?php’ à la fin !).

Muni de cet outil, il n’est plus nécessaire de créer un cache sur disque pour faire
un include et le détruire aussitot après ($cache_supprime est donc supprimé), comme c’est le cas pour les nouveautés, les squelettes à delai nul,
et les pages avec soulignements dus à une recherche (le soulignement a été réécrit par encapsulation de l’appel au squelette compilé, plutot que de faire une deuxième
passe avec rétention du buffer).

Paradoxalement, la gestion d’un message de forum a été simplifiée pour ne plus se servir du modèle qui a inspiré le présent travail : l’envoi d’un tel message ne met en
jeu que 2 caches (ceux utilisant PARAMETRES_FORUM et FORMULAIRE_FORUM) dont
on sait qu’il devront être détruits lors de la validation finale ; il suffit donc de transmettre leur nom dans la REQUEST_URI pour les détruire à la fin, sans plus encombrer une table SQL à quadruple clé par des références à un forum qui ne sera jamais ouvert.

Le serveur SQL gérant les accès concurrents, les caches temporaires (.NEW etc) et
les protections (.htacces) ne sont plus nécessaires. La présente implémentation repère même lorsqu’un autre
processus est en train de calculer ce que souhaite le processus courant, et l’endort
aussitot au lieu de continuer.

Dans le meme ordre d’idée, le fichier .index qui mémorisait les demandes d’indexation sans se protéger des accès concurrents, a été remplacé par
l’introduction d’entrée nulle dans la table SQL des indexations : il suffit alors
de trouver de telles entrées pour réaliser l’indexation souhaitée.

Enfin, le fichier des langues a été déménagé dans ecrire/data afin de pouvoir dès
à présent éliminer le répertoire CACHE.

Le compilateur lui-même a été un peu amélioré par rapport à la version précédente :

-  il n’y a plus aucune variable globale dans le compilateur ce qui permet sa
réentrance totale, dans le cas des include notamment (la pile des doublons,
en particulier, a été remplacée par de moins couteuses variables locales) ;

-  la production d’appel à php dans les caches a été raréfiée ;

-  les hierarchies sont gérées par un code à 2 boucles à requête simple,
plutot que par une boucle préliminaire avec JOIN et une autre avec IN .

La référence au répertoire CACHE étant disséminée dans plusieurs fichiers de
la version du CVS, beaucoup de fichiers ont dû être retouchés. L’architecture
générale de cette nouvelle version est la suivante :

-  inc-cache est le seul fichier gérant les squelettes (recherche, compilation,
exécution, mises en cache) ;

-  inc-calcul ne contient que des fonctions référencées par le code compilé ;

-  inc-public est le seul fichier renvoyant une page au navigateur (il contient la
première moitié de l’ancien inc-public-global, fusionné avec une partie de la fonction ajout_forum antérieurement dans inc-forum)

-  inc-public-global ne contient que les taches de fond, et n’est inclus par
le précédent que si le temps nécessaire est disponible.

Par ailleurs, voulant autoriser les requêtes multi-valués, j’ai dû installé sur ma machine
MySQL 4.1 qui a la particularité de ne plus accepter ses mots-clés comme nom de
champ. Du coup, tous les fichiers utilisant les tables muni du champ « hash’ »
ont été modifiés pour entourer cette chaine par des accents graves (mais si on
n’utilise pas ces requêtes, les versions antiérieures de MySQL sont suffisantes).

Installation

Bien que cela ne soit pas nécessaire a priori, il est prudent
de sauver d’abord votre installation de Spip et votre base de données. Décompresser la pièce jointe dans le répertoire où se trouve Spip,
puis supprimer le fichier ecrire/inc_connect.php3.
Dans votre navigateur, donner l’URL de votre installation de SPIP suivi de /ecrire
et procéder comme si vous l’installiez en entier.

Tout commentaire est le bienvenu.

Le nouveau tgz (mis en ligne le 5/1/2004 à 0h) est compatible avec la 1.7.

Discussion

Aucune discussion

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom