Carnet Wiki

Compléments CacheLab et todo

Version 13 — Décembre 2018 JLuc

Notes de développements
Voir aussi
-  API : API CacheLab 1. Action sur des caches ciblés
-  En prime : CacheLab étend #CACHE et INCLURE
-  Archives : statistiques cachelab
-  XRay, un explorateur des caches SPIP

todos

FIX : var_mode=cache n’est accessible que pour les visiteurs logés. Il va falloir utiliser var_cache.

Passage en « test »

- DOCUMENTER : la surcharge de suivre_invalideur pour activer des stratégies spécifiques d’invalidation adaptées selon surcharge par un plugin (ex : ’recalcul’ ; ou plugin « favori ») ou selon les indications d’une configuration (Config « Basique » : si on reçoit id='typeobjet/valeuridentifiant' on appelle cachelab_cibler('del',  ['cle_objet'=>typeobjet, 'id_objet'=>identifiant]); ; Config « Z » : appeler cachelab_cibler('del',  ['chemin'=>'liste']); en plus. etc). C’est extensible par les plugins.
- SYNTAXE :#CACHE ne peut pas recevoir plusieurs arguments de type ’filtre’ car il n’y a qu’une entête X-Spip-Filtre-Cache. On ne peut donc pas cumuler un log, un assert et un filtre maison. Soit tant pis faut choisir, soit faut se créer un filtre maison qui fait la combinaison voulue. Soit pas faut améliorer ça. ????
- NOMMAGE : Éviter le mix anglais français à l’intérieur d’un même sous-ensemble de vocabulaire : action, index des conditions et options, noms de fonctions, etc. Si possible en français. Par exemple il reste ’list’ dans les arguments et indexes d’options et conditions.
- CLEAN : pas recueillir l_not_array et l_no_data. nb_not_array et nb_no_data, plus un spip_log pour l_not_array, suffisent.
- CLEAN : toujours compter le temps : c’est pas long à faire (ou pas le faire sur define seulement)
- CLEAN : Vérifier le retour de ->del et ajouter un log dans cachelab_cibler comme dans _appliquer

Chaud

- DEV : Manière facile (formulaire de config ou defines php) de choisir, activer et configurer une stratégie globale ou spécifique d’invalidation adaptée à un squelette ou à un plugin utilisé + permettre d’activer une stratégie (ou quoi d’autre ?) localement dans un squelette via une balise SPIP dans un squelette (nouvelle valeur du 2e argument de #CACHE)
- CLEAN : utiliser spip_timer plutôt que la lib/microtime
- DEV : créer fonction cachelab_menage($pourcent=20) qui détruit les plus vieux caches qui servent le moins (nbhits à 0 ou les plus faibles) afin de libérer de la place. En effet, APCu vide tous ses caches d’un coup en cas de manque mémoire et on peut préférer éviter cela. Il faudra anticiper en suivant le taux de remplissage du cache.
Algorithme : s’il reste moins de 20% d’espace, parcourir les 50% plus vieux caches, et parmi ceux-ci, détruire les 50% moins utilisés.

Sous-listes de caches

Sur nursit, les caches APC de plusieurs sites indépendants sont mutualisés et sont accessibles (cryptés) à chaque site. Du coup, leur nombre peut être beaucoup plus grand et le parcours de tous les caches peut devenir trop long.
-  utiliser fonction de parcours filtrante de l’API APCu ?
-  créer et gérer des sous-listes de caches, elles-même mises en cache. Il y aurait une liste par site et le filtrage ne serait (quasiment) pas plus long que si les caches n’étaient pas mutualisés.

Cette dernière possibilité serait intéressante également à l’intérieur d’un même site. Potentiellement, ça pourrait diviser le parcours du cache. On ne peut pas choisir à quelle liste un cache appartient de la même manière que filecache le fait (sans sémantique pour ranger les caches en 16 ou 256 répertoires, car quand on fait une requête d’invalidation, on cible un contexte et non un cache précis, et les cibles peuvent appartenir à des dossiers différents. C’est donc la sémantique et le contexte qui définissent à quel liste un cache appartient. Ces éléments de contextes sont par exemple : « le public », « le privé », « ce type d’objet », « une zone protégée ». Il faut pouvoir définir et référencer ses propres contextes spécifiques.

Cette gestion de sous-listes pourrait être faite en telle sorte qu’elle puisse être utilisée aussi par les autres systèmes de mémoization mémoire : memcached redis etc, ce qui leur permettrait ensuite d’utiliser ensuite le CacheLab.

Tiède
-  confirmer l’exemple théorique d’emploi sur des objets standards, sans redéfinir les fonctions CVT, mais avec les pipelines pre_edition et post_edition + donner un exemple dans la doc. (Mais qu’est ce que ça donne de plus par rapport à la surcharge de suivre_invalideur ? Peut être ça permet d’accéder à plus d’éléments du contextes, qui manqueraient dans le parm ’condition’ reçu par suivre_invalideur ?)

Notes sur l’implémentation

Caches ’aliens’ et autres non traités
APC Cache gère les caches de SPIP pour ce site, mais aussi, selon la configuration serveur, les caches APC d’autres origines. Ces caches APC peuvent être créés et gérés par :
-  d’autres sites SPIP ou non SPIP sur le même serveur si celui ci communalise le cache APC (n*t)
-  ce même site SPIP mais interrogé sur un autre port (car le _CACHE_NAMESPACE, qui pour Memoization identifie le site, est basé notamment sur le port). Ça se produit par exemple si votre site mélange les accès http et https.

cacheLab compte et renvoie dans nb_alien le nombre de ces caches mais n’y touche pas du tout (il ne les efface pas).

Parmi les caches APC autochtones, un certain nombre de caches APC ne sont pas créés pour des squelettes : il y a notamment les caches des déclarations textwheel. Ces caches ne sont pas comptés et ne sont pas traités par cacheLab.

crons invalideurs

La synchro des listes dynamiques de mailsubscriber se fait automatiquement entre 00h00 et 01h00 et appelle automatiquement l’invalidation SPIP (cf #1464). D’autre crons potentiellement aussi. Si on veut éviter cette invalidation quotidienne, il faut penser à intercepter cette invalidation.

V2 : usage par non programmeurs = action sur squelettes dist, plugins, objets et formulaires standards

Il semble assez facile de déployer une stratégie optimisée dans le code php qui implémente un objet lorsque ce code est conçu « sur mesure » pour un site donné. Ça semble plus difficile pour des objets génériques qui ne préjugent rien du contexte d’utilisation. La stratégie par défaut de SPIP à l’heure actuelle reste peut être bien la meilleure dans ces cas là.

Un entre-deux semble envisageable pour les squelettes généralistes de SPIP : dist, spipr, escale, SC, sarka... Certains se prêtent certainement bien à l’élaboration d’une stratégie optimisée de ciblage.

On pourrait également définir des conventions génériques de nommage des dossiers et fichiers permettant d’implémenter des régles standard de filtrage et invalidation ciblée du cache. Sur la base de ces conventions, on pourrait définir un plugin standardisé auquel auraient recours les squelettes se conformant aux conventions et souhaitant bénéficier de l’invalidation sélective du cache.

Exemple de règles :
-  nom de dossiers contenant ’liste’, ou plus précisément ’liste_monobjet’, pour les noisettes qui présentent des listes de monobjet et qui doivent être invalidées lorsqu’on crée, supprime ou modifie un monobjet
-  noms de squelettes contenant ’monobjet’ lorsqu’il faut filtrer pour les invalider sélectivement lorsqu’on crée, supprime ou modifie un monobjet avec un id_monobjet particulier

De même, il semble intéressant de chercher à fournir des comportements optimisés standard pour certains plugins :
-  mesfavoris
-  gis
-  formidable ?

DEV : Autres explorations

Extension envisageable : listes ciblées préfiltrées

Une possibilité serait de constituer des listes ciblées : sous-ensembles pré-filtrés de caches. Une telle liste de caches serait alimentée au moment de la création d’un cache, lorsque ce dernier satisfait les critères définissant la liste. L’invalidation sélective pourrait alors directement spécifier les caches de quelle liste doivent être invalidés, en paramètre de suivre_invalideur.
-  Il y aurait un surcoût lors de la création d’un cache, pour préfiltrer le cache. Mais ce surcoût semble très réduit.
-  Les temps d’invalidation seraient alors énormément réduits (divisés par un facteur 100 ou 1000 ?), puisqu’il n’y aurait aucun filtrage requis. Tout le parcours serait utile.

Cette possibilité semble peu intéressante lorsqu’un cache mémoire est utilisé, mais serait intéressante pour filecache, lorsque le cache se fait sur le disque. Car le parcours de tous les fichiers de cache sur le disque est trés coûteux, mais on ne perd pas de temps si on garde précisément la trace des caches qu’il faut invalider (parcours 100% utile).

Ces listes sont en fait une extension de ce que propose le plugin microcache. Il serait probablement possible de l’implémenter en étendant microcache (en ajoutant un nouvel argument à la fonction : le nom de la liste de caches ciblés (qui décrit aussi le type de filtrage qui génère cette liste).

Disponibilité pour filecache et autres

Pour filecache et les caches mémoires autres que APC, il faudra probablement implémenter une gestion de la liste des caches, car je crois qu’ils n’en disposent pas en natif.

À faire donc : une nouvelle méthode de memoïzation qui permette de parcourir les caches. La création de la liste est activée sur demande explicite seulement (paramétrable par define).

Ajouter un ou des pipelines

S’ils étaient implémentés dans le core, dans les fonctions de gestion du cache, des pipelines permettraient d’implémenter des stratégies alternatives de fonctionnement du cache, sans surcharger tout le fichier dans un plugin.
-  suivre_invalideur
-  la fonction qui vérifie si un cache existe et est à jour

Cachecool

On pourrait au contraire souhaiter garder les caches invalides et les utiliser à la demande, comme fait cachecool. Cela n’atténue pas la charge sur le serveur, mais ça donne l’impression d’un service plus rapide.

On peut combiner :
-  les caches périmés sont supprimé par cron toutes les X minutes
-  dans l’intervalle, les caches périmés sont quand même servis. L’utilisateur doit être averti qu’il doit parfois attendre un peu pour que les affichages soient mis à jour ou disposer d’un bouton pour forcer la mise à jour de la noisette qui l’intéresse !