[spip-dev] Compilateur, env et cache

Bonjour,

En réfléchissant autour de Zpip, noiZetier, nous sommes partis du constat suivant :
- Zpip et le noiZetier utilisent massivement {env}
- ce qu'ils incluent n'utilise pas forcément tous les paramètres de l'environnement pour se calculer (parfois aucun)
- les inclusions peuvent elles-mêmes inclure une autre inclusion qui, elle, utilisera un paramètre de plus

A inclus B (utilise rien) inclus C (utilise id_article) inclus D (utilise id_rubrique calculé en C + #ENV{id_rubrique} donné par A)

Du coup, B a autant de caches que de contexte d'env différents, et cela, pour rien puisque tous les cache sont identiques.
Cela dans le cas ou B <INCLUS C>
Si B #INCLUS C, alors, c'est normal que B ait autant de caches que C

De là, quelques idées :
- déclarer dans l'entête des squelettes les paramètres d'environnement effectivement utilisés dans le squelette
- déclarer aussi ceux qui ne sont pas utilisés, mais qui doivent être passés aux inclusions

- ou calculer à la compilation les éléments de l'environnement :
   - utilisés dans le squelette (y compris par héritage dans les #inclusions)
   - passés aux <inclusions>

- ne créer des caches différents que pour les paramètres effectivement utilisés

- peut-être qu'à partir du moment où il n'y aurait un cache différent que pour les paramètre effectivement utilisés, la connaissance des paramètres passés aux inclusion n'aurait plus d'importance et que se contenter de les passer tous suffirait...

Ça inspire quoi ces réflexions ?

-- RealET

  • les inclusions peuvent elles-mêmes inclure une autre inclusion qui, elle, utilisera un paramètre de plus

attention danger : l’inclusion statique fait remonter le « un paramètre de plus ». Or on ne sait ce qu’on inclue qu’à l’exécution, et non à la compilation.

  • déclarer dans l’entête des squelettes les paramètres d’environnement effectivement utilisés dans le squelette

l’« entête des squelettes » est une notion qui n’existe pas, mais on pourrait sans doute les déclarer dans le squelette (tout court)

  • déclarer aussi ceux qui ne sont pas utilisés, mais qui doivent être passés aux inclusions

je dirais non, en tous cas c’est problématique car l’inclusion fait appel à un find_in_path() qui peut permettre de surcharger le squelette inclus. il ne faut donc pas d’info dans le squelette appelant sur ce que fera le squelette inclus.

  • ou calculer à la compilation les éléments de l’environnement :
  • utilisés dans le squelette (y compris par héritage dans les #inclusions)
  • passés aux

bon courage avec la théorie du compilateur :smiley: il est possible que ce soit d’ailleurs impossible.

  • ne créer des caches différents que pour les paramètres effectivement utilisés

+1

  • peut-être qu’à partir du moment où il n’y aurait un cache différent que pour les paramètre effectivement utilisés, la connaissance des paramètres passés aux inclusion n’aurait plus d’importance et que se contenter de les passer tous suffirait…

oui, ou de n’en passer aucun, et d’aller les chercher dans l’env global

Ça inspire quoi ces réflexions ?

il faut épurer le mécanisme théorique, puis le coder. go

en tous cas sans forcément chercher la complication, si un squelette déclare #JENUTILISEQUE{id_article}, on peut envisager déjà de bidouiller le mécanisme de cache pour qu’il gère ça. Ca peut se dev en plugin

– Fil

Ça veut dire que lorsqu’on compile A qui inclue B, il faut d’abord compiler B (et ainsi de suite) pour connaitre les variables d’env utilisées et les expliciter dans l’écriture de l’inclusion de B. Ceci afin qu’a l’execution on puisse trouver le nom de cache commun de B lié aux seules env utilisées.

Cela complique notablement la compilation.
Mais plus encore, cela entraine une interdépendance. Actuellement, chaque squelette peut être compilé indépendamment des autres.
En particulier si B est modifié, cela est détecté au calcul, et il est recompilé à la volée.

Avec une interdépendance en cascade, il faudrait, avant de calculer A, vérifier qu’aucun des squelettes inclus n’a été modifié, et, en conséquence recompiler A si c’est le cas. Tout cela aurait un impact perfo important.

Une solution alternative serait de filtrer le contexte non à la compilation, mais à l’exécution.
Ainsi, au moment ou l’on cherche un cache avec un contexte donné, il faudrait d’abord charger son squelette compilé et en extraire l’information de contexte réellement utile, et l’utiliser pour filtrer le contexte complet avant de chercher le cache correspondant.

Ce mécanisme peut marcher, au prix d’une petite dégradation de perf (double lecture de cache), mais à un seul niveau.
Autrement dit, si A inclue B inclue C, l’inclusion de B se ferait sur la seule foi du contenu de B, sans pouvoir tenir compte de ce que C utilise vraiment aussi.

Toute cette problématique se posant essentiellement pour le calcul et le cache des noisettes d’un noizetier, à traver le pipeline recuperer_fond, je pense que c’est à son niveau que le problème doit se règler : les noisettes qui le peuvent (ce sont en général des briques finales sans inclusion supplémentaire) doivent déclarer le contexte qu’elle necessite et qui sera utilisé pour filtrer le contexte général passé par le squelette.

En l’absence de déclaration, tout le env sera utilisé, ce qui assure le fonctionnement au prix d’un cache multiple.
En cas de déclaration, seul le env necessaire sera utilisé, ce qui est optimal. Mais peut introduire des « bugs » en cas de déclaration erronée ou incomplète.

Cédric

Pour le noiZetier, marcimat a codé cela il y a quelques jours.
Il est donc dorénavant possible de spécifier pour chaque noisettes les variables d'environnement qu'il faut lui transmettre. En l'absence de déclaration spécifique, toutes les variables d'environnement sont transmises.

Joseph

Bonjour,

Et si l'on veut transmettre aucune variable d'environnement?

C'est pas pour ennuyer que je pose cette question.
{env} ça ne sert pas à transmettre toutes les variables?

Sur un Spip svn 2.2, j'avais des problèmes avec {env}{ajax},
finalement j'ai renoncé à Ajax, sinon une partie du contenu n'était
pas toujours affiché (de manière aléatoire, l'INCLUDE ne se faisait
pas).

A bientôt
Grégoire

Je ne répondrai que pour les noisettes du noizetier. Il est possible de spécifier contexte: 'aucun'. Auquel cas, aucune variable du contexte n'est transmise (NB : les paramètres de la noisette sont eux toujours transmis en tant que variables d'environnement).

cordialement

Joseph