Le WordPress d'aujourd'hui, décodé pour les développeurs

Performance

WeakMap PHP 8.0 pour mémoriser un résultat sans empêcher sa libération mémoire

WeakMap permet d'associer une valeur calculée à un objet PHP sans empêcher le ramasse-miettes de le libérer. Un mécanisme discret mais précieux pour un cache en mémoire.

Par Clément Hadrot • 27 février 2021 • 4 min de lecture • Aucun commentaire
WeakMap PHP 8.0 pour mémoriser un résultat sans empêcher sa libération mémoire

$cache = new WeakMap(); — cette seule ligne change la façon dont on peut mémoriser un résultat lié à un objet, sans risquer de créer une fuite mémoire silencieuse. WeakMap fait partie des ajouts discrets de PHP 8.0, moins commentés que les types d’union ou les arguments nommés, mais tout aussi utiles dans certains cas précis de développement WordPress.

Le problème qu’elle résout est simple à décrire une fois qu’on l’a rencontré : un tableau PHP classique utilisé comme cache, indexé par un objet (via spl_object_id() par exemple), garde une référence forte vers cet objet. Tant que le tableau existe, l’objet ne peut jamais être libéré par le ramasse-miettes, même si plus rien d’autre dans le code n’y fait référence. Sur un traitement qui instancie des milliers d’objets temporaires, cela peut faire grimper la consommation mémoire d’un script PHP bien au-delà de ce qui serait nécessaire.

Ce que change une référence faible

Une WeakMap associe une clé (qui doit être un objet) à une valeur, mais sans empêcher cet objet d’être détruit par le ramasse-miettes s’il n’est plus référencé ailleurs. Dès que l’objet clé disparaît, l’entrée correspondante disparaît automatiquement de la WeakMap, sans qu’il soit nécessaire d’appeler quoi que ce soit pour nettoyer. C’est exactement le comportement qu’on attend d’un cache éphémère : mémoriser un résultat tant que l’objet source existe, et l’oublier proprement dès qu’il n’existe plus.

Dans un contexte WordPress, ce mécanisme trouve sa place quand un même objet métier (un objet WP_Post enrichi, une instance de classe personnalisée représentant une fiche produit) sert de point d’ancrage à un calcul coûteux qu’on ne veut pas refaire deux fois pendant la même requête, sans pour autant vouloir gérer manuellement l’invalidation.

Un exemple concret de mise en œuvre

final class CalculPrixAffiche {
    private WeakMap $cache;

    public function __construct() {
        $this->cache = new WeakMap();
    }

    public function pour(WP_Post $produit): float {
        if (isset($this->cache[$produit])) {
            return $this->cache[$produit];
        }

        $prix = $this->calculerPrixComplexe($produit);
        $this->cache[$produit] = $prix;

        return $prix;
    }

    private function calculerPrixComplexe(WP_Post $produit): float {
        // agrégation de plusieurs meta et d'une remise conditionnelle
        return 0.0;
    }
}
L'essentiel à retenir : Une clé de tableau classique retient l'objet indéfiniment ; WeakMap laisse le ramasse-miettes faire son travail ; Utile pour des calculs coûteux liés à un objet temporaire

Pourquoi ce n’est pas un remplacement du cache d’objet persistant

Il faut garder une distinction claire entre les deux outils. Le cache d’objet persistant (Redis ou Memcached derrière wp_cache_get()) survit d’une requête HTTP à l’autre et sert à éviter des lectures en base de données répétées entre visiteurs. La WeakMap ne survit jamais au-delà de la requête PHP courante : elle vit et meurt avec le processus, et son seul rôle est d’éviter des recalculs redondants pendant l’exécution d’un même script.

Quand l’utiliser, et quand s’abstenir

  • Utile quand une même instance d’objet transite plusieurs fois dans le même appel (boucles imbriquées, hooks déclenchés à plusieurs reprises pour le même contenu).
  • Inutile si le calcul dépend uniquement d’un identifiant scalaire : un tableau associatif classique indexé par cet identifiant suffit largement, sans le coût conceptuel supplémentaire.
  • À éviter si l’on a besoin d’itérer sur toutes les entrées du cache dans un ordre prévisible : WeakMap est conçue pour l’association clé-objet, pas pour le parcours ordonné.

Un piège de compatibilité à vérifier

Comme WeakMap n’existe qu’à partir de PHP 8.0, tout code destiné à tourner sur un parc d’hébergement hétérogène doit vérifier la version PHP disponible avant de l’utiliser, ou prévoir un repli vers un tableau associatif classique pour les environnements encore en PHP 7.4.

En résumé

WeakMap répond à un besoin précis et rare mais réel : mémoriser un résultat lié à un objet sans figer cet objet en mémoire pour toute la durée du script. Ce n’est pas un outil à sortir systématiquement, mais quand le besoin se présente, il évite un genre de fuite mémoire particulièrement difficile à diagnostiquer, puisqu’elle ne se manifeste que sur des volumes de données suffisamment grands pour la rendre visible dans les journaux.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi