Contexte et objectifs
Les frameworks GUI natifs en Rust gagnent en popularité, à tel point que Discord a annoncé la réécriture de son client avec GPUI. L’auteur du billet, qui a porté le rendu Linux de GPUI vers wgpu2 et construit le banc d’essai utilisé, critique le modèle d’état de GPUI et d’egui, le qualifiant de point mort pour les applications de bureau complexes. Il expose deux arguments : la nécessité de connaître les dépendances de chaque changement d’état et la supériorité des composants réactifs basés sur des signaux.
Modèle d'état de GPUI
GPUI se décrit comme un framework « hybride immediate et retained mode ». L’état est stocké dans des entités ; le rendu s’exécute dans des fonctions Rust classiques. Lors d’une modification, le développeur doit déclencher manuellement une notification :
self.threads.unread = false;
cx.notify;La notification ne porte que l’identifiant de l’entité, car Rust ne fournit pas de barrière d’écriture sur les références mutables. Ainsi, GPUI ne sait pas quel champ a changé et doit, par défaut, re‑rendre chaque vue qui n’est pas protégée par .cached(). En pratique, les développeurs utilisent rarement .cached(), ce qui conduit à des rafraîchissements globaux.
Benchmarks et limites de performance
Les mesures présentées portent sur une interface contenant 3 000 lignes actives, chaque ligne disposant d’une vue mise en cache. Modifier une étiquette entraîne un temps de rendu de 8,4 ms. Le même changement, sans mise en cache, passe à 92 ms, montrant que le coût suit la taille de l’arbre plutôt que la portée du changement. Un garde d’égalité écrit à la main réduit le temps d’écriture à 0,9 µs, illustrant le potentiel d’optimisation manuelle.
Le fork gpui‑fast, qui retient chaque sous‑arbre entre deux images, abaisse le temps à 3,4 ms pour le même scénario, soit une amélioration de 60 %. Cependant, même avec cette optimisation, le rendu parcourt toujours l’ensemble de l’arbre, limitant les gains. Sur des charges réelles, Zed (application construite avec GPUI) a mesuré une rétention 1–3 % plus lente que l’exécution ordinaire, et les gains de micro‑benchmarks ne se traduisent pas toujours en amélioration perceptible.
Analyse comparative et perspectives
Les frameworks réactifs basés sur des signaux, comme le zgui de l’auteur, permettent de déclarer explicitement les dépendances entre état et vue. Chaque composant s’abonne à un signal précis, évitant ainsi les rafraîchissements inutiles. Des solutions web similaires (Redux, MobX) recommandent déjà de fragmenter les composants et de lire les données de façon granulaire, ce qui montre que le problème n’est pas propre à Rust.
En conclusion, le modèle d’état de GPUI, bien qu’attrayant par sa simplicité syntaxique, montre des limites de scalabilité lorsqu’il s’agit de grandes interfaces. Les optimisations basées sur la rétention partielle atténuent le problème mais ne l’éliminent pas. Les développeurs qui recherchent une granularité fine et des performances prévisibles pourraient privilégier des architectures signal‑first, même si cela implique une complexité supplémentaire dans la construction du graphe de dépendances.