Mon économiseur d'écran bouffait du CPU écran allumé (et c'est moi qui l'ai écrit)
Hier soir je faisais le ménage sur mon MacBook. Seize gigas de RAM, quarante-sept jours sans redémarrer, un swap plein. Le classique. Je trie les processus par CPU, et je tombe sur une ligne que je ne devrais pas voir.
legacyScreenSaver. 6 % de CPU. Depuis trois heures quarante. Écran allumé, déverrouillé, moi en train de bosser dessus.
Le processus qui fait tourner les économiseurs d'écran. Et l'économiseur, c'est le mien. OmSaver, le petit truc en Swift que j'ai publié en septembre, avec les barres de CPU et le faux journal qui défile.
Ce qui se passe
Un économiseur macOS n'est pas un programme. C'est un plugin, chargé par un processus système, legacyScreenSaver. Le système l'instancie, l'anime avec un timer, et quand tu bouges la souris il est censé appeler stopAnimation() puis tuer le processus.
Depuis macOS 14, il ne fait plus ni l'un ni l'autre de façon fiable. Le processus survit à l'économiseur. Et quand stopAnimation() n'est pas appelé, le timer continue. Mon code continuait donc à échantillonner les dix cœurs, à calculer la RAM et à repeindre une fenêtre plein écran que personne ne voyait. Huit fois par seconde. Pendant des heures.
Un économiseur d'écran qui consomme pendant que tu travailles. C'est exactement l'inverse de sa raison d'exister.
Ce que je n'avais pas vu
Je pourrais m'en tirer en disant que c'est un bug d'Apple. C'en est un, des gens se plaignent depuis Sonoma. Mais mon code lui facilitait la vie.
Il faisait confiance au système pour s'arrêter. Pas une seule vérification de son côté. Et chaque image, il recréait deux formateurs de date, relisait la version dans le bundle et demandait le nom de la machine au système, un appel qui prend quelques millisecondes. Huit fois par seconde. Pour un nom qui ne change jamais.
Ça marchait. Ça marchait même bien, dans le sens où ça s'affichait. Je n'avais jamais mesuré ce que ça coûtait quand ça ne s'affichait pas.
Le correctif, en quatre ceintures
La version 1.1 est sortie ce matin. Elle ne fait plus confiance.
Elle écoute les annonces que le système diffuse à tous les processus quand l'économiseur se termine ou que l'écran est déverrouillé, et s'arrête toute seule. Elle a un chien de garde : deux secondes sans fenêtre visible, elle s'arrête. Et quand plus rien n'anime, elle termine elle-même le processus hôte. macOS en relancera un propre la prochaine fois, ce qu'il aurait dû faire tout seul. Jamais dans l'aperçu des Réglages, bien sûr, sinon la vignette gèle.
Au passage : quatre images par seconde au lieu de huit, puisque rien ne bouge en continu sur cet écran. Et les objets coûteux sont créés une fois, pas à chaque image. Le saver consomme maintenant une fraction de ce qu'il consommait quand il tourne, et zéro quand il ne tourne pas.
La leçon, qui n'a rien à voir avec les économiseurs
Je passe mes journées à surveiller des serveurs. Prometheus, Grafana, des alertes sur tout. Et le truc qui tournait en boucle depuis des semaines était sur ma propre machine, écrit par moi, et je ne l'ai vu que parce que je cherchais autre chose.
On ne mesure jamais ses propres outils. On mesure ceux des autres.
Un ps trié par CPU, une fois par mois, sur ton poste. C'est gratuit, ça prend dix secondes, et ça m'aurait évité trois heures quarante de ventilation pour rien. Multipliées par le nombre de gens qui ont installé le truc.
Désolé pour la batterie. La 1.1 est là, elle se contente de la place qu'on lui laisse.
- Télécharger : https://github.com/stranix79/omsaver/releases/tag/v1.1
- Le code, 450 lignes commentées : https://github.com/stranix79/omsaver
- La suite Om : https://om.stranix.net