HeadlinesBriefing favicon HeadlinesBriefing.com

Buildprof Visualise temps de compilation

Hacker News •
×

J’ai créé buildprof (GitHub), un outil open source qui montre où le temps est dépensé lorsque vous compilez un logiciel sous Linux. Voici une vidéo en temps réel de celui-ci le profilant une compilation propre de ripgrep : Regardez la démo buildprof. Parfois, les compilations sont lentes simplement parce qu’il y a beaucoup de code à compiler.

Mais bien plus souvent, il y a des problèmes réparables : mauvais parallélisme, travail répété, téléchargements de dépendances ou une énorme invocation compilateur/éditeur de liens. buildprof rend tout cela clairement visible, afin que vous puissiez voir ce qui vaut la peine d’être investigué et optimisé. Vous lancez en mettant buildprof -- devant n’importe quelle commande de compilation que vous utilisez déjà : buildprof -- make -j16, buildprof -- cargo build, buildprof -- ninja -C out/target, buildprof -- just build, buildprof -- ./dev/custom-build-script.sh. buildprof enregistre chaque processus que votre commande de compilation lance, y compris leurs sous-processus (et leurs sous-processus…), et les dispose sur une ligne du temps. Le temps se déplace de gauche à droite, la largeur de la barre montre la durée, et les processus enfants apparaissent sous ce qui les a lancés.

J’ai créé buildprof parce que ce tweet de Jarred Sumner, architecte en chef du runtime Bun, habitait gratuitement dans mon esprit : Plus précisément, l’affirmation selon laquelle la nouvelle compilation Rust de Bun était >5× plus rapide en Linux que son ancienne compilation Zig. Dans mon expérience, les projets Zig se compilent généralement beaucoup plus rapidement que les projets Rust de complexité similaire. Cette intuition m’a suffit pour me sentir qu’il y avait un mystère à résoudre.

Cela a été encore compliqué par un autre détail important, mais facilement manqué, dans le tweet : la compilation Zig utilisait Full LTO, tandis que la compilation Rust utilisait Thin LTO. Les compilateurs optimisent généralement en grande isolation les unités de compilation séparées. L’optimisation en temps de liaison (LTO) leur permet de optimiser à travers ces frontières.

Full LTO réunit ces unités dans un seul grand travail d’optimisation, tandis que Thin LTO préserve plus de séparation de sorte que beaucoup de travail peut s’exécuter en parallèle. D’après mon expérience passée, cette différence peut avoir un effet énorme sur le temps de compilation. Le tweet l’a mentionnée en passant, mais je me suis demandé combien de l’amélioration affichée dans l’en-tête il expliquait réellement.

J’ai commencé par essayer de reproduire les chiffres. Les chiffres se sont reproduits. Mais maintenant ? J’ai vérifié Bun 1.3.14 et Bun 1.4.0 et j’ai écrit des scripts pour rejouer leurs builds Linux x64 CI sur une VM Linux 6 cœurs, 12 threads.

Les scripts ont préservé les étapes de construction et leurs dépendances, en exécutant tout sur une machine unique. Mes temps étaient dans la même fourchette que ceux de Jarred : Linux x64 build Zig era 30m06s, Rust era 5m37s. Mon replay CI sur une seule machine 24m24s 5m40s.

OK, donc l’écart s’est aussi présenté sur ma machine. Mais beaucoup avait changé entre les deux mesures en plus du langage ; alors qu’est-ce qui était réellement responsable ? Était-ce le compilateur Zig qui prenait tout ce temps supplémentaire ? Ou peut-être était-ce le lien Full LTO. Ou peut-être y avait-il quelque chose d’autre dans le build de Bun que je n’avais même pas pensé à regarder.

C’est là que mon cerveau d’analyseur de développeur a pris le relais. En général, quand j’essaie de comprendre pourquoi quelque chose est lent, je veux un trace : ce qui s’est passé, quand cela s’est passé et combien de temps cela a pris. Ce serait vraiment cool d’avoir cela pour ces builds, pour les mettre sur une ligne du temps et voir où leur temps est réellement allé.

Mais une compilation implique de nombreux outils différents, chacun ayant sa propre idée de ce qui se passe. Qu’est-ce que je pourrais enregistrer pour pouvoir voir à travers tous eux ? Les builds sont des arbres de processus. Quand vous tapez cargo build ou zig build, cela semble comme si vous exécutiez un seul programme.

Le système de construction détermine ce qui doit être reconstruit, l’ordre entre ces pièces et ce qui peut s’exécuter en parallèle. Mais généralement, il ne effectue pas tout ce travail lui-même ; il lance des compilateurs, des générateurs de code, des archivistes, des éditeurs de liens et des scripts arbitraires. Ceux-ci peuvent lancer plus de programmes qui lancent encore plus… Différents systèmes de construction décrivent ce travail de différentes manières.

Cargo voit des crates, Ninja voit des bords de construction et CMake génère des instructions pour un autre système de construction. Depuis le système d’exploitation.