Aide:Limites de taille d’inclusion de modèles

Le logiciel MediaWiki qui fait fonctionner Wikisource et les autres projets Wikimédia est paramétré de manière à limiter la complexité d’une page et la quantité de données qui peuvent être incluses. Ces limites concernent principalement les données transcluses ou substituées lors de l’expansion d’une page, par opposition aux données directement dans la source de la page elle-même. Cette page explique comment et pourquoi ces limites sont appliquées, et comment les utilisateurs peuvent travailler à l’intérieur de ces limites.

Contexte modifier

Quand faut-il s’en préoccuper ? modifier

Si, sur une page donnée, vous voyez des lignes incompréhensibles comme dans l’exemple ci-dessous, par exemple si le nom d’une page apparaît au lieu de son contenu, ou encore si vous voyez le terme « MediaWiki:Proofreadpage header template », alors cette page fait probablement un usage excessif des modèles. La suite de cette page explique ce phénomène et propose des techniques pour résoudre le problème.

 
Symptômes classiques du dépassement de la limite de taille d’inclusion de modèles sur une page de Wikisource

De quoi s’agit-il ? modifier

Le logiciel MediaWiki, qui génère le code HTML d’une page à partir de sa source wiki, utilise un analyseur (parser) pour traiter les données incluses. Cela se fait à l’aide d’un « préprocesseur » qui convertit le wikitexte en une structure de données connue sous le nom d’arbre XML, puis utilise cet arbre pour produire un wikitexte « étendu », dans lequel les structures à double et triple accolades sont remplacées par leur résultat.

Exemple : le wikitexte {{table|titre=[[Le Songe (Lucien)|Le Songe]]|page={{pli|1|36}}}}, une fois développé, produit le code HTML suivant[1] :

<div class="tableItem" style="position:relative;margin:.125em auto;background:#FFF;line-height:normal"><div style="margin-right:0px"><div style="float:left;width:100%"><div style="position:relative;z-index:2;"><span style="background:#FFF">[[Le Songe (Lucien)|Le Songe]]&nbsp;</span></div><div class="ws-noexport" style="position:relative;margin-left:1em"><div style="position:absolute;z-index:1;bottom:.3em;width:100%;border-bottom:0.135em dotted"></div></div></div><div class="ws-noexport" style="float:right"><div style="position:absolute; z-index:2; bottom:0; right:0; text-indent:0; text-align:right; white-space:nowrap"><span style="background:#FFF">&nbsp;<span style="text-align:right">1</span></span></div></div><div style="clear:both"></div></div></div>

Pendant le processus de conversion, le logiciel utilise plusieurs compteurs pour suivre la complexité de la page en cours de génération. Lorsque l’analyse d’une page commence, ces compteurs sont mis à zéro, puis ils sont incrémentés pendant le processus d’analyse, comme décrit ci-dessous. Il existe des limites supérieures sur ces compteurs et l’analyseur ne permet pas de dépasser ces limites.

Pourquoi y a-t-il des limites ? modifier

Les pages très longues ou compliquées sont lentes à analyser. Non seulement c’est un inconvénient pour les utilisateurs, mais cela peut également être utilisé pour monter une attaque par déni de service (DoS) sur les serveurs, dans laquelle une demande de page force le logiciel MediaWiki à analyser une quantité déraisonnablement importante de données. Les limites aident à prévenir ce type d’attaque et garantissent que les pages sont rendues dans un délai raisonnable. (Néanmoins, parfois, une page complexe peut produire une erreur de délai dépassé (time out) alors qu’elle reste à l’intérieur des limites ; cela dépend de la charge des serveurs.)

Travailler à l’intérieur des limites modifier

Lorsqu’une page atteint les limites du modèle, la solution la plus courante consiste à raccourcir les modèles, en utilisant les méthodes décrites ci-dessous. Si cela n’est pas possible, il peut être nécessaire d’inclure plus de données directement dans la source de la page, plutôt que de les transclure à partir de modèles (par exemple, formater les références à la main ou utiliser <references /> au lieu de {{Références}}). D’un autre côté, un modèle peut aider le serveur à éviter de faire du travail en double, voir ci-dessous.

Quand les problèmes surviennent-ils ? modifier

Les limites d’inclusion sont le plus souvent atteintes sur les pages qui utilisent le même modèle de nombreuses fois, par exemple en utilisant une transclusion par ligne d’un long tableau. Sur Wikisource, un cas courant est celui d’une table des matières très détaillée, produite par de multiples appels au modèle {{table}}. Même si la quantité de données que chaque appel au modèle ajoute à la page finale peut être limitée, elle est comptée chaque fois que le modèle est utilisé, et la limite peut donc être atteinte plus tôt que prévu. Il est peu probable que les pages qui ne contiennent que quelques dizaines d’appels de modèles dépassent les limites d’inclusion, à moins que ces modèles ne contiennent eux-mêmes beaucoup de données.

Comment peut-on le savoir ? modifier

Une fois le corps de la page traité, un commentaire HTML est ajouté vers la fin du code HTML de la page avec les valeurs finales des différents compteurs. Par exemple, la page Les Misérables contient, à l’heure où cette page est rédigée, le commentaire ci-dessous dans le code HTML généré. Les mêmes informations sont accessibles (en français) lorsqu’on clique sur « Prévisualiser », puis tout en bas de la page sur « Données d’optimisation de l’analyseur ».

Code HTML Mode prévisualisation
<!-- 
NewPP limit report
Parsed by mw1414
Cached time: 20220808074756
Cache expiry: 1814400
Reduced expiry: false
Complications: []
CPU time usage: 1.744 seconds
Real time usage: 1.955 seconds
Preprocessor visited node count: 11888/1000000
Post‐expand include size: 2007565/2097152 bytes
Template argument size: 805/2097152 bytes
Highest expansion depth: 11/100
Expensive parser function count: 4/500
Unstrip recursion depth: 1/20
Unstrip post‐expand size: 374928/5000000 bytes
Lua time usage: 0.314/10.000 seconds
Lua memory usage: 2727447/52428800 bytes
Number of Wikibase entities loaded: 0/400
-->
Temps d’utilisation du processeur 1,841 seconde
Temps réel d’utilisation 2,072 secondes
Nombre de nœuds de préprocesseur visités 11 888 / 1 000 000
Taille d’inclusion après expansion 2 007 565 / 2 097 152 octets
Taille des arguments de modèles 805 / 2 097 152 octets
Profondeur d’expansion maximale 11 / 100
Nombre de fonctions d’analyse coûteuses 4 / 500
Profondeur de récursion de développement 1 / 20
Taille de développement après expansion 374 928 / 5 000 000 octets
Temps d’utilisation de Lua 0,315/10,000 secondes
Utilisation mémoire de Lua 2 727 087/52 428 800 octets
Nombre d’entités Wikibase chargées 0 / 400

Si l’une de ces tailles est proche de la limite, il est probable que certains modèles n’ont pas été développés. Chaque occurrence d’un modèle non développé est identifiée dans le corps de la page par un commentaire HTML contenant un message d’erreur.

Les principales limites modifier

Nombre de nœuds de préprocesseur visités modifier

Le nombre de nœuds du préprocesseur (preprocessor visited node count) mesure la complexité de la page (et non le volume de données). Lorsque l’analyseur développe une page, il crée une structure de données connue sous le nom d’arborescence qui correspond à la structure HTML de la page. Chaque nœud de l’arbre qui est visité pendant l’expansion est compté dans le nombre de nœuds du préprocesseur. Si ce nombre est dépassé, l’analyseur interrompra l’analyse avec l’erreur Node-count limit exceeded ( « limite de nombre de nœuds dépassée » ) visible dans le code HTML généré.

Le décompte commence à 1 pour le texte brut. Une paire de balises nowiki compte pour 3, un en-tête pour 2, etc. Un lien ne contribue pas au comptage. Pour l’extension d’un commutateur #switch, chaque condition vérifiée ajoute 2 au décompte. Dans le cas d’expansions multiples du même modèle, le contenu d’un modèle sans argument compte une seule fois, mais celui d’un modèle avec arguments (même s’il est constant) compte plusieurs fois. En revanche, le résultat d’une expansion peut être utilisé plusieurs fois tout en comptant une seule fois s’il est affecté à un paramètre de modèle, et ce modèle a plusieurs utilisations de ce paramètre.

Les pages dépassant cette limite sont automatiquement classées, sur Wikipédia, dans Catégorie:Pages où le nombre de nœuds est dépassé.

Taille d’inclusion après expansion modifier

La taille d’inclusion après expansion (post-expand include size) est la somme des longueurs des wikitextes développés générés par les modèles, les fonctions d’analyseur (parser functions) et les variables. Chaque fois que l’analyseur est chargé par le code source d’une page de développer un modèle, etc. (c’est-à-dire de le remplacer par une transclusion ou une substitution), l’analyseur additionne la longueur du wikitexte développé généré par le modèle, etc. et la valeur courante du compteur pour la page. Si cette somme est supérieure à la limite après expansion (identique à la taille maximale de l’article, à savoir 2 097 152 octets), le modèle initial, etc., n’est pas remplacé et un message d’erreur est ajouté sous forme de commentaire dans le code HTML généré. Sinon, le compteur après expansion est incrémenté à la nouvelle valeur et l’analyse se poursuit. Un modèle développé plusieurs fois dans la page contribue plusieurs fois à sa taille d’inclusion après expansion.

Les appels de modèles sans argument ont un cache de texte étendu. Donc, si {{foo}} inclut le méta-modèle de deuxième niveau {{bar}}, alors plusieurs invocations de {{foo}} n’augmenteront que la taille d’inclusion après expansion pour le {{foo}} entièrement développé ; l’inclusion secondaire {{bar}} n’est comptée qu’une seule fois. Mais si vous avez inclus le même modèle plusieurs fois avec {{foo|arg}}, alors les modèles secondaires sont comptés à chaque fois, même si l’argument est le même.

Les pages dépassant la limite de taille d’inclusion après expansion sont automatiquement ajoutées à Catégorie:Pages contenant trop d’inclusions de modèles (ajouts récents).

Utilisation des commentaires, noinclude et onlyinclude modifier

Seules les données qui survivent à l’étape d’expansion du préprocesseur sont comptées dans le compteur après expansion. La longueur des commentaires HTML dans le wikitexte (qui ne sont pas reproduits dans la source HTML produite) n’est pas incluse dans le compteur. Le code qui se trouve soit à l’intérieur d’une section <noinclude> soit à l’extérieur d’une section <onlyinclude> n’est pas développé, donc ces sections ne contribuent pas à la taille après expansion. Cela signifie également que les balises de catégorie ne contribuent que si elles sont incluses (pour catégoriser les pages appelant le modèle).

Transclusions imbriquées modifier

Notez que les tailles des wikitextes de tous les modèles développés et des fonctions d’analyseur (parser functions) sont ajoutées, même dans le cas de l’imbrication (voir phab:T15260), donc des niveaux supplémentaires augmentent le nombre. Si la page A transclut B et B ne fait que transclure C, alors la taille de C sera comptée deux fois dans la taille d’inclusion après expansion sur la page A, et de même si un modèle consiste en un appel de fonction d’analyseur, ou si une fonction d’analyseur fait un appel de modèle en paramètre, etc. Cela peut parfois être atténué en laissant la fonction d’analyseur produire un nom de modèle au lieu d’un résultat de modèle, par exemple en remplaçant

{{#if:{{{test|}}}|{{template1}}|{{template2}} }}

par :

{{ {{#if:{{{test|}}}|template1|template2}} }}.

Transclusions non rendues modifier

Les tranclusions non rendues comptent toujours pour la limite. Par exemple, une page qui ne contient que {{#if:{{:Main Page}}}} aurait toujours une taille d’inclusion après expansion même si elle ne produisait aucune sortie.

Il en va de même pour les modules Scribunto. Par exemple, {{#invoke:Test|main}} augmenterait toujours la taille d’inclusion après expansion même si Module:Test était simplement :

mw.getCurrentFrame():preprocess'{{msgnw::Main Page}}' -- supprimez cette ligne et la taille d’inclusion après expansion devient zéro
return {main = function()end} -- p.main() n’a pas de valeur de retour

Taille des arguments du modèle modifier

Le compteur de taille d’argument de modèle garde en mémoire la longueur totale des arguments de modèle qui ont été substitués. Sa limite est la même que la taille limite de l’article.

Exemple :

{{3x|{{2x|abcde}}}} a une taille d’argument de modèle de 40 octets : l’argument {{2x|abcde}} est compté 3 fois, l’argument abcde deux fois.

Les arguments dans l’appel du modèle qui ne correspondent à aucune balise de paramètre du modèle ne sont pas pris en compte.

Si un modèle contient un commutateur (switch), l’utilisation d’arguments de modèle au-delà d’une correspondance ne compte pas. Jusqu’à et y compris l’élément faisant l’objet de la correspondance, les arguments de modèle utilisés à gauche des signes égal comptent deux fois. Ceux à droite du signe égal comptent uniquement pour l’élément faisant l’objet de la correspondance.

Profondeur d’expansion la plus élevée modifier

Les pages dépassant cette limite sont automatiquement classées, sur Wikipédia, dans Catégorie:Pages où la profondeur d’expansion est dépassée.

Limites propres aux fonctions d’analyseur (parser functions) modifier

Expansion dans le cas des fonctions d’analyseur modifier

Les modèles dans les branches non exécutées des fonctions d’analyseur (parser functions, dont le code commence par {{#…) conditionnelles ne sont pas développés et ne sont donc pas comptés. Par exemple, dans le code {{#if:yes|{{bar}}|{{foo}}}}, le modèle {{bar}} est développé, mais le modèle {{foo}} n’est pas développé.

Néanmoins, il est possible qu’un argument de modèle contribue au décompte même s’il n’apparaît pas dans la sortie finale. Par exemple, si le code {{#if:{{foo}}|yes|no}} est analysé, la longueur de la version étendue du modèle {{foo}} sera ajoutée au compteur après expansion, car ce modèle doit être développé afin de décider quelle branche de la condition doit être sélectionnée.

Appels de fonction d’analyseur coûteux modifier

Il existe une limite de 500 au nombre de fonctions d’analyseur (parser functions) coûteuses qui sont :

  • #ifexist - branchement selon qu’une page particulière existe. Si la limite de ce compteur est dépassée, des appels #ifexist supplémentaires agiront comme si les pages qu’ils interrogent n’existaient pas ;
  • PAGESINCATEGORY ou PAGESINCAT ;
  • PAGESIZE ;
  • CASCADINGSOURCES ;
  • REVISIONUSER, lorsqu’il est utilisé sur une page autre que la page actuelle ;
  • REVISIONTIMESTAMP, lorsqu’il est utilisé sur une page autre que la page actuelle ;
  • Certaines fonctions Lua, dont beaucoup sont équivalentes à d’autres éléments de cette liste :

Il est également possible d’incrémenter manuellement le nombre de fonctions d’analyse coûteuses à partir d’un module Lua en utilisant mw.incrementExpensiveFunctionCount.

Voir aussi : mw:Manual:$wgExpensiveParserFunctionLimit, Template:Expensive.

Le cas de #time modifier

La longueur totale des chaînes de format de la fonction #time est limitée à 6 000 caractères [1]. Le message d’erreur est donné par MediaWiki:Pfunc time too long). Pour chaque combinaison du wikitexte développé d’une chaîne de format et du wikitexte développé d’une expression pour le temps (par exemple {{#time:r|1 Mar 2008 -1day}}, qui produit Fri, 29 Feb 2008 00:00:00 +0000), l’utilisation répétée n’est pas comptée, car les résultats sont mis en cache.

Toutefois, le décompte ne figure pas dans le rapport relatif aux limites.

Spécial:ExpansionDesModèles modifier

Lorsqu’une page dépasse les limites, un moyen simple de résoudre le problème consiste à utiliser Spécial:ExpansionDesModèles. Contrairement à la substitution, il développe de manière récursive tous les niveaux à la fois, sans qu’il soit nécessaire de préparer spécialement les modèles avec le code {{{|safesubst:}}} ou similaire (voir phab:T4777). Cela réduit tous les décomptes à zéro, à l’exception du compteur de nœuds de préprocesseur, mais même celui-là sera généralement réduit à un nombre bien inférieur à la limite.

Historique modifier

Les limites d’inclusion ont été mises en vigueur sur Wikipedia anglais par Tim Starling le 14 août 2006. Un nouveau préprocesseur a été activé en janvier 2008, supprimant la « limite d’inclusion avant expansion » (pre-expand include limit) et la remplaçant par une limite de « compteur de nœuds de préprocesseur » (preprocessor node count).

La pratique consistant à utiliser un modèle de page de documentation, bien qu’elle puisse toujours être utile pour d’autres raisons, n’est plus nécessaire pour éviter que la documentation ne soit comptée sur les pages qui appellent le modèle.

Notes et références modifier

  1. Le code développé à partir d’un appel de modèle peut être obtenu sur Spécial:ExpansionDesModèles, page spéciale décrite plus bas.


Voir aussi modifier

Pages d’aide et de discussion sur le Wikipédia anglophone :

Informations sur les parser functions : Parser functions