Comment WP Footprint mesure.
Cette page documente exactement ce qui est mesuré, comment c'est agrégé, et comment le grade A à E est calculé. La méthode est publique : vous pouvez la critiquer, la vérifier, refaire le calcul, et nous proposer des améliorations.
Méthodologie en vigueur : v4.1. Versionnée à chaque évolution — l'historique vit dans le code source.
En bref
Une mesure isolée par plugin, médianée sur 90 jours.
Chaque plugin est désactivé tour à tour pour isoler son impact propre. Les contributions de tous les sites contributeurs sont ensuite consolidées en médianes glissantes sur 90 jours, avec intervalle de confiance, avant d'être traduites en grade A à E.
Mesure différentielle : baseline puis désactivation
WP Footprint mesure une page plusieurs fois avec tous les plugins actifs (le baseline). Ensuite, pour chaque plugin et pour le thème actif, il rejoue la même page après l'avoir désactivé temporairement via un MU-loader, et mesure à nouveau.
L'impact propre d'un composant est la différence : delta = médiane(baseline) − médiane(baseline sans le composant). Cette approche par différence neutralise l'effet du serveur, du thème et des autres plugins — c'est ce qui rend les comparaisons inter-sites légitimes, sans avoir à instrumenter le code PHP en profondeur.
Plusieurs passes, médiane, intervalle de confiance
Pour absorber le bruit naturel d'un serveur web (cache, GC, latence DB), chaque mesure est répétée : jusqu'à 5 passes pour le baseline et jusqu'à 3 passes par composant désactivé. Le plugin peut s'arrêter plus tôt — dès 3 passes baseline ou 2 passes composant — quand l'échantillon est déjà serré (spread sous max(50 ms, 10 % de la médiane)) : pas de précision perdue, juste pas de passes inutiles. Les valeurs aberrantes sont éliminées par filtre Tukey k=1.5 sur l'intervalle interquartile, puis on garde la médiane des passes restantes (la médiane résiste aux outliers, contrairement à la moyenne).
Une demi-largeur d'intervalle de confiance à 95 % est calculée via la loi de Student t(0.975, n−1) — pas par approximation gaussienne, qui sous-estimerait l'incertitude sur de petits échantillons. Un delta non distinguable du bruit n'est pas comptabilisé dans le score public.
Plancher serveur (host-floor)
À chaque scan, le plugin lance également 3 passes synthétiques où WordPress est démarré sans aucun plugin et avec un thème par défaut. La requête est court-circuitée tôt (action init priorité 1) et renvoie un body minimal — on ne mesure ni le routing, ni la résolution du post, ni le rendu de la page. Ce qu'on capture est le temps pur de boot WP+serveur sur cette machine.
Cette mesure est indépendante de l'URL scannée et reproductible. Elle servira à normaliser les scores par hébergeur : un même delta de +90 ms n'a pas la même signification sur un floor de 80 ms (overhead +112 %) que sur un floor de 250 ms (overhead +36 %). Pour l'instant la donnée est collectée et archivée ; la pondération entrera en vigueur dans une révision ultérieure du calcul.
Limites d'isolation : plugins non mesurables
Certains plugins ne peuvent pas être désactivés sans casser la page : leur API est appelée directement (au niveau PHP) par le thème ou par d'autres plugins. La requête fataliserait, ce qui rendrait toute mesure différentielle impossible. Quand le scanner détecte ce cas (fatal sur la première passe), il arrête les retries, marque le composant non mesurable, et ne le remonte pas à Pulse. Les autres composants sont mesurés normalement.
Pour les plugins populaires qui exposent une API largement consommée par les thèmes (ACF, Polylang, Yoast, Rank Math, Meta Box, Pods, WPML, The Events Calendar, Gravity Forms…), le MU-loader charge des stubs de compatibilité pendant la passe : les fonctions du plugin restent définies et retournent des valeurs neutres, la page rend sans fataliser, et le coût propre du plugin reste mesuré correctement. La liste des plugins couverts est exposée dans /api/v1/methodology sous pipeline.isolation.compatibility_shims.covered_slugs.
Les cinq métriques mesurées
Cinq grandeurs sont capturées à chaque passe, dont deux sont normalisées en ratio du baseline et trois restent en valeur absolue :
- CPU PHP — temps CPU consommé via
getrusage(), exprimé en fraction du CPU PHP de la requête baseline. Auto-normalisant entre serveurs : 18 % du CPU sur un Xeon = 18 % sur un mutualisé. - Mémoire — pic mémoire supplémentaire, en fraction du pic mémoire baseline. Même raisonnement : la fraction parle, la valeur absolue dépend du serveur.
- Requêtes SQL ajoutées — comptage absolu. 1 requête = 1 requête, indépendant de la machine.
- Assets ajoutés — scripts + styles enqueués par le composant. Comptage absolu.
- Appels HTTP externes — comptage absolu des appels réseau sortants.
Le calcul du score 0-100 par composant
Convention : 100 = parfait, 0 = pire — comme une note scolaire. Pour chaque métrique, on applique une rampe linéaire entre un seuil bas (en-dessous, le composant ne perd 0 point) et un seuil haut (au-dessus, il perd le poids maximum). Les cinq pénalités sont sommées (max 100) puis on retourne score = 100 − pénalité. Le score est recalculé serveur à chaque ingestion, à partir des passes brutes — le client ne décide jamais de sa propre note.
| Métrique | Seuil bas (0 pt perdu) | Seuil haut (perte max) | Poids max |
|---|---|---|---|
| CPU (% baseline) | 2 % | 30 % | 30 pts |
| Mémoire (% baseline) | 2 % | 40 % | 20 pts |
| Requêtes SQL | 2 | 60 | 20 pts |
| Assets | 1 | 15 | 15 pts |
| HTTP externes | 0 | 5 | 15 pts |
Pourquoi CPU et mémoire en ratio et SQL/assets/HTTP en absolu ? Les deux premières grandeurs varient avec la machine ; les normaliser au baseline annule le facteur d'échelle. Les trois autres sont des comptages entiers, intrinsèquement invariants.
Le score global de la page
Le score que vous voyez en gros sur le rapport de scan reflète la lourdeur réelle de la page rendue, pas la somme des impacts attribués à chaque composant. La distinction est importante : avec ~10 plugins ou plus, l'attribution différentielle compte plusieurs fois les hooks partagés (deux plugins qui se partagent un même hook se voient chacun attribuer le coût total). En sommant ces deltas et en les comparant au baseline, on obtenait un ratio saturé à 100 % presque mécaniquement → 50 points perdus avant même de regarder si la page était lente. Méthodo v4.0 corrige ça en lisant directement les valeurs absolues du baseline.
Cinq mêmes dimensions, mais en absolu : durée serveur, pic mémoire, requêtes SQL, scripts/styles enqueués, appels HTTP externes. Mêmes rampes linéaires que la note par-composant, mais avec des seuils plus tolérants (un site fait forcément plus qu'un seul plugin).
| Métrique | Seuil bas (0 pt perdu) | Seuil haut (perte max) | Poids max |
|---|---|---|---|
| Temps serveur | 400 ms | 3000 ms | 30 pts |
| Pic mémoire | 24 MB | 192 MB | 20 pts |
| Requêtes SQL | 80 | 1500 | 20 pts |
| Scripts + styles | 15 | 120 | 15 pts |
| HTTP externes | 2 | 25 | 15 pts |
Du score au grade A–E
Le score est mappé sur une lettre A à E selon des bornes absolues sur la note 0-100. Si tout l'écosystème WordPress s'optimisait, tous les plugins pourraient passer en A — c'est voulu : on note un impact, pas un classement relatif.
| A | 85 – 100 | Impact négligeable, composant très léger |
| B | 65 – 84 | Impact modéré, raisonnable |
| C | 45 – 64 | Impact significatif, à surveiller |
| D | 25 – 44 | Impact important, alternative recommandée |
| E | 0 – 24 | Impact très lourd, critique |
Agrégation entre sites
Quand plusieurs sites mesurent la même version d'un plugin, on conserve la médiane par (plugin, version, page_type) — séparément pour la homepage et l'admin, qui n'ont rien à voir. La médiane résiste mieux aux valeurs aberrantes (sites mal configurés, mesures interrompues) que la moyenne.
Les scans bruts sont conservés en base 3 ans. Si la méthodologie change, on peut recalculer rétroactivement tous les scores sans avoir à redemander aux sites de re-scanner.
Score consolidé sur la fiche publique
Le score affiché sur la fiche d'un plugin ou d'un thème est consolidé sur les 90 derniers jours. Tous les scans valides de cette fenêtre alimentent la médiane, indépendamment de la version sur laquelle ils ont été pris. Sans ça, à chaque release d'une nouvelle version, le baromètre se réinitialiserait à zéro et un plugin actif passerait son temps en « pas assez de données ».
L'étiquette de version affichée sur la carte (« v4.1.0 ») reste celle de la version la plus récente représentée dans la fenêtre — pour qu'on voie quelle release est en train d'être mesurée — mais le score, lui, reste stable. Le détail version par version reste accessible dans la table d'historique plus bas sur la fiche.
Garde-fous avant publication
Trois filtres sont appliqués avant qu'un scan ne participe à la médiane publique. Les scans rejetés restent stockés pour audit mais n'influencent pas le grade affiché.
- Baseline trop léger : si la requête baseline consomme moins de 50 ms de CPU, les ratios deviennent extrêmes et bruités → scan exclu.
- Baseline bloaté : si la requête baseline dépasse 3 × la médiane mondiale du même type de page, le site est probablement déjà saturé d'autres plugins → scan exclu (sinon un plugin lourd y paraîtrait négligeable).
- Plausibilité statistique : sept heuristiques inter-métriques (ex. « 50 MB alloués sans aucun temps CPU consommé » est physiquement impossible) attribuent un score 0-100 à chaque scan. En dessous de 40/100, le scan est rejeté comme suspect.
Identité vérifiée des sites contributeurs
Chaque site contributeur génère localement une paire de clés Ed25519 et signe chaque envoi. L'identité est vérifiée une fois à l'enrôlement par un challenge cryptographique sur admin-ajax.php. Aucune clé partagée — fabriquer une fausse identité demande de posséder un vrai domaine WordPress, ce qui rend la triche économiquement non rentable. Cf. la politique de confidentialité pour ce qui transite (et surtout ce qui ne transite pas).
Composants opt-out du classement public
L'utilisateur peut marquer un plugin ou un thème — typiquement un module développé en interne ou un produit propriétaire — comme privé dans les réglages du plugin WordPress. Le composant est alors envoyé à Pulse avec un flag private: true.
Le serveur calcule et renvoie son score (l'utilisateur le voit dans son rapport local) mais ne persiste rien : pas de ligne dans plugin_scans, pas d'entrée dans le catalogue public, pas d'agrégation dans les médianes communautaires. Le slug ne fait que transiter en signé puis est oublié. Cette séparation entre « pas de score » et « pas publié » a été introduite en méthodo v3.2.
Seuil de publication
Tant qu'une version de plugin ou de thème compte moins de 15 scans uniques (sites distincts vérifiés), son grade n'est pas affiché publiquement. WP Footprint Pulse indique « données insuffisantes » à la place, pour ne jamais induire en erreur sur la base d'un échantillon trop petit.
Refaites le calcul vous-même
Tous les seuils, poids et garde-fous décrits ci-dessus sont exposés en JSON sur l'endpoint public https://www.wpfootprint.com/api/v1/methodology, versionné par méthodologie. Vous pouvez aussi lire directement le code de scoring sur le dépôt — il tient en quatre fichiers et chacun fait moins de 200 lignes.
Limites assumées
- Pas de tracing PHP fin. L'attribution est différentielle : si un plugin A déclenche un hook qui exécute du code d'un plugin B, l'impact mesuré peut être partiellement attribué à l'un ou à l'autre. C'est le compromis pour rester non-intrusif (pas besoin de Xdebug).
- Biais d'environnement résiduel. Les ratios CPU/mémoire annulent le biais de fréquence du serveur, mais restent sensibles à la version PHP majeure (PHP 7.4 ne distribue pas les coûts comme PHP 8.3). Stratification par version PHP prévue v1.1.
- Échantillon auto-sélectionné. Les sites qui installent WP Footprint sont probablement plus techniques que la moyenne. Le ranking est « vrai pour les sites qui scannent », pas pour tout WordPress.
- Pas de mesure de la valeur fournie. Un plugin lourd qui fait beaucoup et un plugin léger qui fait peu auront le même grade si leurs deltas sont identiques. La catégorisation aidera mais ne résoudra pas tout.
- Plugins asynchrones. Les plugins qui font la majorité de leur travail en cron différé ou en queue (workers, webhooks) auront un impact frontal sous-estimé sur un scan de page unique.
- Plugins non isolables. Certains plugins fatalisent quand on les désactive parce que leur API est consommée au niveau PHP par le thème ou un autre plugin. Ils sont marqués « non mesurables » dans le rapport local et exclus du ranking public. Leur liste est remontée anonymement pour prioriser de nouveaux stubs de compatibilité.
Suggestions et critiques bienvenues — écrivez-nous à [email protected]. Toute amélioration retenue est documentée dans le changelog de la méthodologie.