Cachez ce PHP que je ne saurais voir (mais montrez toutes mes tables)

Archive historique

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

Nouveaux systèmes de cache et de traduction des squelettes éliminant une passe de PHP.

Présentation

Les versions standards de SPIP envoient aux navigateurs des pages HTML après une traduction en trois temps :

Squelettes SPIP —> Script PHP/MySQL —> Script PHP —> HTML+JavaScript

Une réécriture complète du traducteur de squelettes et du système de cache
(entrepris depuis 8 mois et décrit sur ce site)
permet aujourd’hui d’éliminer la deuxième passe de PHP dans de nombreux cas,
notamment le cas des squelettes de la distribution standard. Cette amélioration due au compilateur est prise en compte par le système de cache qui fonctionne alors comme un véritable cache de pages HTML, envoyées efficacement par le serveur Web comme s’il s’agissait de pages statiques, et non plus de scripts PHP nécessitant
une nouvelle analyse syntaxique pour y trouver puis pour y évaluer les séquences "<?php ... ?>" insérées par le compilateur et/ou le squelette d’origine.

Méthode de compilation

La deuxième passe de PHP dans les versions actuelles de SPIP a trois origines différentes :

-  1. la page HTML à produire varie selon le demandeur ;

-  2. le squelette utilisé inclut d’autres squelettes ;

-  3. le squelette utilisé contient du PHP.

Le point 1 concerne essentiellement les intervenants
(administrateur, rédacteur, souscripteur de forum)
authentifiés par un cookie. Le principe est de remplacer les séquences
"<?php ... ?>"
insérées par le compilateur standard, par l’appel d’une fonction JavaScript.
Du coup, le code produit par le compilateur ne contient plus que du HTML
et du JavaScript que l’on peut mettre en cache comme tel, et il suffit au script
PHP principal (inc-public) de définir cette fonction à chaque connexion en
l’insérant en début de page. En définitive, SPIP délègue
au navigateur une insertion de HTML beaucoup plus immédiate pour son
interprète JavaScript que pour l’interprète PHP du serveur, trop sollicité de surcroît.

En ce qui concerne le point 2, rien en théorie ne motive de différer l’inclusion
d’un squelette après l’exécution complète du squelette incluant, autrement dit
d’appeler immédiatement une fonction d’inclusion au lieu de produire l’actuel
"<?php include() ?>". En pratique, c’est délicat car le code PHP
produit par le traducteur de squelettes doit être parfaitement réentrant, c’est-à-dire
n’affecter aucune variable globale. Ce n’est doublement pas le cas du compilateur standard de SPIP qui manipule une pile à l’aide de variables globales,
et affecte à chaque entrée de fonction compilée les variables globales homonymes
des index de la pile. Le compilateur proposé ici produit du code réentrant, compatible avec des inclusions à un niveau d’imbrication quelconque.

Le compilateur étant lui-même réentrant, on a expérimenté avec succès l’inclusion
pendant la phase de compilation, lorsque la balise INCLUDE est sans paramètre
(donc indépendante du contexte) et le squelette inclus sans PHP. Toutefois cette option n’a pas été retenue car elle grossit l’espace du cache pour un gain de temps
imperceptible.

Un autre cas relevant de cette technique est le surlignement. La version actuelle
diffère le surlignement après la mise en cache sans nécessité théorique, ce qui n’est pas le cas du compilateur ici proposé.

En ce qui concerne le point 3, le compilateur est alors obligé de revenir à la stratégie actuelle, la sémantique de SPIP imposant l’exécution différée du PHP
inséré dans un squelette. Toutefois, certains ajouts au compilateur
devraient raréfier leur utilisation.
Il s’agit notamment (certains points sont nouvaux,
d’autres figurenet
dans les articles et les forums consacrés aux versions successives du compilateur) :

-  autorisation d’une balise SPIP dans les critères de boucle. Par exemple, le critère titre=#TITRE sert à trouver dans la base un autre objet ayant même titre que l’objet de la boucle englobante. Cette absence avait provoqué l’existence du critère « exclus » qui, avec cette innovation, peut s’exprimer tout simplement par « id_article !=#ID_ARTICLE ».

-  autorisation d’effectuer plusieurs comparaisons sur un même critère,
par exemple {id_mot=16}{id_mot=2} (bug 168 jamais corrigé, voir la discussion ; ceci nécessite cependant MySQL 4.1).

-  autorisation de paramètres comme 1,n-1 où n désigne le nombre d’éléments issus de la requête (voir les spécifications).

-  tout champ des tables SQL est accessible par une balise SPIP homonyme en majuscule :
cette référence est automatique suite à une réécriture de l’initialiseur de la BD
qui permet au compilateur d’en connaître le contenu : les grosses variables rows_* du compilateur standard qui en étaient une copie partielle sont évacuées (c’est pourquoi le compilateur proposé n’est pas plus gros que l’actuel, bien qu’il offre plus de fonctionnalités). En revanche, existent deux tableaux permettant
de débrayer cet automatisme :
$exceptions_des_tables (si les noms des champs et/ou des tables SQL ne sont pas les homonymes SPIP) et $exceptions_des_champs (si l’on veut implanter un traitement ultra-spécifique dans l’aiguillage de inc-index-squel malgré l’homonymie).

Ce dernier point concerne non seulement les tables standards de SPIP,
mais aussi les tables accessibles par la connexion SQL, du moment que
ces tables sont décrites par un tableau PHP dans le fichier ecrire/inc_auxbase.php3, et en déclarant global ce tableau dans le fichier
ecrire/inc_globalbase.php3 : ces deux fichiers jouent un rôle équivalent à un
include de .h en C. De la sorte, s’il existe une table nommée matable1
ayant des champs nom et adresse, on peut écrire dans un squelette :

<BOUCLE_1(matable1)><BR>#NOM #ADRESSE</BOUCLE_1>

et obtenir ce que les habitués de SPIP devineront sans peine.

Méthode de cache

Pour profiter au maximum de cette amélioration du compilateur
il est intéressant d’examiner avant la mise en cache si aucune interpolation
de PHP ne figure dans la page produite, afin de l’envoyer tout de suite lors des
prochaines consultations. Dans le cas d’un cache utilisant des fichiers,
cela revient à sauver le résultat avec une extension .html ou .php selon le cas.
Toutefois, la présente implémentation utilise un système de cache reposant sur
le serveur SQL (voir ici pour une présentation et
une discussion) qui a l’avantage d’invalider automatiquement les caches rendus
caducs par l’apparition d’un nouvel article. Il est néanmoins envisageable d’écrire
une autre version du fichier inc-cache (8 fonctions totalisant 6Ko seulement)
qui utiliserait plutôt le système de fichiers (mais je rappelle que la version actuelle
n’est pas totalement fiable faute de poser un verrou lors de la création de tels
fichiers dans le répertoire CACHE).

Etats présent et futur

De toutes les balises SPIP nécessitant une authentification,
seul FORMULAIRE_ADMIN a été réécrite sous forme d’un appel à une fonction
JavaScript : cette stratégie est délicate à implémenter et on s’est donc limité pour
cette première version à la balise la plus fréquente.

Les outils de mesures de performance sont d’une fiabilité médiocre, on y a donc renoncé. A l’usage (tant en local que sur un serveur distant ayant 350 visiteurs et 10 rédacteurs) ça semble effectivement plus rapide. Rappelons que ce nouveau compilateur a aussi
la supériorité de restreindre les appels au serveur SQL aux seuls champs effectivement utilisés et de fournir un code PHP plus de 2 fois plus petit que
les squelettes originaux.

Il est à noter qu’en cas de page 100% HTML, SPIP peut à présent calculer le header
Content-Length et générer un Connexion : close pour prévenir plus rapidement le client de la fin de l’envoi, quand bien même le processus SPIP continue sa vie (pour indexation etc). Les expérimentations donnent toutefois
des résultats contrastés selon les serveurs et proxies utilisés : la question doit donc
être approfondie.

La présente modification d’une vingtaine de fichiers SPIP est compatible avec
la version 1.7 de SPIP. Désolé pour ceux qui sont déjà passés à la 1.7.1 mais
ce travail est loin d’avoir été immédiat. Si les développeurs de SPIP veulent
l’intégrer à la CVS, je veux bien faire la mise à jour nécessaire.

Pour l’installation, il faut détruire le fichier ecrire/inc_connect.php3 et procéder
comme si on installait une nouvelle version de SPIP : ceci aura pour effet de laisser
intactes les tables déjà présentes, et de déclarer les tables de caches spécifiques.
Signalons également que s’il existe dans $dossier_squelettes un fichier nommé
mon-chercher.php3, celui sera lu à la place de inc-chercher.php3
afin d’y
trouver la définition de la fonction chercher_squelette retournant le squelette
associé au document demandé.

Bien que cette version tourne apparemment sans problème sur le site public
mentionné, des bugs ne sont évidemment pas à exclure. Toute remarque et expérimentation sont donc les bienvenues. Une petite cerise sur le gateau :
le formulaire de gestion des forums comporte un bouton supplémentaire
permettant de répondre à un message en meme temps qu’on le valide ;

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