- Zig remplace, pour les cibles x86_64, le chemin par défaut où LLVM abaissait le bitcode en fichiers objet par son propre backend x86, ce qui réduit fortement le temps de compilation et l’usage mémoire des builds debug
- Le backend x86 maison passe 1 987 behavior tests, soit davantage que les 1 980 du backend LLVM ; certains tests supplémentaires sur un total de 2 084 ne s’exécutent que dans les tests x86 self-hosted
- Dans le benchmark
hello.zig, la moyenne de 918 ms avec le chemin LLVM tombe à 275 ms avec le backend maison par défaut, soit une baisse de 70,1 % du wall time, tandis que le pic de RSS passe de 214 Mo à 137 Mo - Même sur de gros projets comme le compilateur Zig lui-même, le temps de build passe de 75 secondes à 20 secondes, mais Windows n’est pas encore concerné par le changement de valeur par défaut, car le linker COFF nécessite encore du travail
- Les travaux restants portent sur la parallélisation complète de la génération de code, l’amélioration du linker, la stabilisation de l’incremental compilation, l’amélioration de la qualité du code x86 et l’extension du backend aarch64
Changement du backend par défaut pour x86_64
- Pour les builds ciblant x86_64, Zig utilise désormais par défaut son propre backend x86
- L’ancien chemin par défaut consistait pour LLVM à abaisser des fichiers de bitcode en fichiers objet
- Sous Windows, la valeur par défaut n’a pas encore changé
- Parce que le linker COFF nécessite encore du travail
État des behavior tests réussis
- Le backend x86 maison passe 1 987 behavior tests
- Le backend LLVM passe 1 980 behavior tests
- Le total des behavior tests est de 2 084, mais les tests supplémentaires recoupent en grande partie les tests du backend x86 LLVM lui-même
- Ces tests supplémentaires ne sont exécutés que lors des tests x86 self-hosted
- En nombre de tests réussis, le backend x86 de Zig est donc plus avancé que le backend LLVM dans l’implémentation du langage Zig
Pourquoi concurrencer le chemin LLVM
- La principale raison pour laquelle Zig concurrence LLVM sur la génération de code est qu’il peut créer un écart important en matière de vitesse de compilation
- Le contexte associé est résumé dans l’explication sur Ziggit
Benchmark hello.zig
- Résultat de
zig build-exe hello.zig -fllvm:- Wall time moyen : 918 ms
- Pic RSS : 214 Mo
- Cycles CPU : 4,53 G
- Instructions : 8,50 G
- Résultat du chemin par défaut
zig build-exe hello.zig:- Wall time moyen : 275 ms
- Pic RSS : 137 Mo
- Cycles CPU : 1,57 G
- Instructions : 3,21 G
- Le backend maison par défaut réduit plusieurs métriques par rapport au chemin LLVM
- Wall time réduit de 70,1 %
- Pic RSS réduit de 36,2 %
- Cycles CPU réduits de 65,2 %
- Instructions réduites de 62,2 %
- Cache misses réduits de 86,1 %
- Branch misses réduits de 78,3 %
Effets sur les grands projets
- Sur de plus grands projets, comme le compilateur Zig lui-même, le temps de build passe de 75 secondes à 20 secondes
- Le backend x86 maison peut fortement réduire les temps de compilation non seulement sur de petits exemples, mais aussi sur de grandes bases de code
Prochaines étapes
- Zig a déjà commencé à travailler sur la parallélisation complète de la génération de code
- Une démo associée est disponible sous forme d’enregistrement asciinema
- Avec de nouvelles améliorations du linker et corrections de bugs, il sera possible de rendre l’incremental compilation stable et robuste avec ce backend
- La qualité du code x86 généré peut encore être améliorée
- La prochaine cible est aarch64, et le nouveau pass Legalize devrait accélérer le travail
- Les builds les plus récents de la branche master peuvent être téléchargés depuis la page de téléchargement de Zig pour être testés directement
1 commentaires
Avis de Hacker News
D’après ce que je sais, Zig a beaucoup de chantiers en cours pour améliorer l’expérience de développement. Il y a quelque chose qui avance presque tous les jours, et il vient encore d’y avoir un truc comme https://github.com/ziglang/zig/pull/24124
Il me semble qu’ils avaient aussi prévu le remplacement de code à chaud ; au rythme actuel de développement, ça ne m’étonnerait pas que ça fonctionne sur x86_64 d’ici un an
Aujourd’hui, ma plus grosse douleur personnelle, c’est la vitesse de
comptime. Le compilateur a beaucoup de travail à faire là-dessus, et faire tourner un DSL brainF** à la compilation est assez lent. Je l’ai essayé moi-même, c’était une expérience marranteLes nouveaux backends que Zig est en train d’introduire sont globalement très prometteurs. J’aimerais bien essayer d’écrire moi-même un backend URCL(https://github.com/ModPunchtree/URCL) pour Zig
comptime, on sait ce qu’il faut faire, et une branche avait même été commencée il y a longtemps. Cela dit, il faut retravailler une bonne partie du code d’analyse sémantique ; c’est clairement faisable, nécessaire, et ça sera fait, mais c’est en concurrence avec d’autres prioritéscomptimeest vraiment un problème. Je construis une bibliothèque JSON-RPC et je m’appuie beaucoup surcomptimepour dispatcher les requêtes JSON vers des fonctions arbitrairesÀ cause du typage statique strict, il n’y a pas moyen de faire à l’exécution un dispatch dynamique vers des fonctions ayant des paramètres arbitraires ; la seule méthode que j’ai trouvée consiste à déterminer à la compilation, avec
comptime, le mapping des types de fonctionsComme chaque fonction arbitraire ajoute une copie de code passée par
comptime, la taille du code risque d’augmenterPlus précisément, j’imagine qu’on pourrait créer un backend qui prend l’AIR et produit un rapport de sûreté mémoire : identifier l’utilisation de valeurs indéfinies, les pointeurs de pile qui s’échappent, les use-after-free, les double free, les cas du type alias xor mut, etc.
C’est déjà un énorme accomplissement, mais comme l’indique le journal de développement, il reste encore beaucoup à faire. L’idée d’un compilateur qui, pendant la compilation, ne modifie dans le binaire que les parties nécessaires est à la fois fraîche et complètement radicale, et elle semble désormais à portée du projet Zig
J’ai hâte de voir la suite
Le passage « un gros projet comme le compilateur Zig passe de 75 secondes à 20 secondes. Et ce n’est que le début » me donne envie d’en voir plus. Je me demande ce que cette personne pourra en faire, elle a vraiment l’air brillante
Je me demande où en est la gestion de paquets. J’avais essayé de faire une appli QuickJS + SDL3, mais je suis passé à Rust à cause du bazar côté C++, et là ça a juste marché. J’aimerais pouvoir tenter la même chose avec Zig
Cela a aussi des avantages : on peut dépendre d’archives arbitraires, et beaucoup de paquets Zig qui enveloppent des bibliothèques C ressemblent surtout à des scripts de build dépendant de releases tarball non modifiées. Bien sûr, c’est un peu plus difficile pour les débutants
Il existe un wrapper Zig natif pour SDL3 : https://github.com/Gota7/zig-sdl3
Il existe aussi un repackaging plus basique de la bibliothèque/API C : https://github.com/castholm/SDL
Pour QuickJS, l’API C est la seule option : https://github.com/allyourcodebase/quickjs-ng
Zig rend très facile l’utilisation directe de paquets C de cette manière, mais les types de Zig sont beaucoup plus stricts, donc on finit par faire beaucoup de casts lorsqu’on interagit avec l’API
real 0m18.444s,user 0m17.408s,sys 0m1.688sMême sur un très vieux processeur, il va assez vite pour que je n’aie pas vraiment eu besoin de mettre à niveau
C’est quelque chose comme un
AMD Athlon(tm) 64 X2 Dual Core Processor 4400+, 2 cœurs, 2,3 GHz, 512 Ko de cacheJe l’ai déjà dit à propos de D et de Nature, mais pour tous les langages qui disposent de leur propre backend, nous avons le devoir de soutenir les projets qui cherchent à ne pas dépendre de LLVM
LLVM a figé la R&D sur les compilateurs ; trop de langages ont choisi d’en dépendre, et trop de gens ont cessé de considérer des temps d’itération rapides comme quelque chose de précieux, ou ont cessé d’attendre mieux
La compilation incrémentale, le patching de binaires pour itérer vite, et un bon débogage devraient faire partie des attentes envers les nouveaux langages, pas être traités comme des fonctionnalités de niche ou des choses trop difficiles
Toute l’industrie du rendu temps réel repose pratiquement sur LLVM ou des forks de LLVM ; Microsoft a aussi remplacé son compilateur de shaders par LLVM et commence seulement maintenant à upstreamer son code
La majeure partie de l’infrastructure de compilation des consoles de jeux est également basée sur Clang. Xbox reste jusqu’ici attachée à MSVC, mais c’est plutôt l’exception
Dans l’ensemble, LLVM a été un immense succès, surtout pour le bootstrap de nouvelles choses
Je ne veux pas donner l’impression d’exiger quoi que ce soit ni de manquer de gratitude. Zig est un travail fait gratuitement. Mais ce qui m’intéresse le plus, c’est un calendrier réaliste pour la 1.0
Zig correspond presque exactement à ce que j’attendais d’un langage bas niveau, et j’attends qu’il se stabilise
Bien sûr, j’apprécie vraiment la philosophie de conception minimaliste de Zig
Un programme hello world créé avec
zig initfait 9,3 Mo une fois compilé. Comparé aux 7,6 Ko avec-Doptimize=ReleaseSmall, c’est plus de 1000 fois plus gros, c’est énorme-OReleaseSmall -fno-stripproduit un exécutable de 580 Ko, et-ODebug -fstripproduit un exécutable de 1,4 MoLe backend x86 de Zig offre une bien meilleure expérience de débogage avec un fork de lldb qui comprend Zig : https://github.com/ziglang/zig/wiki/LLDB-for-Zig
Je ne me souviens pas si l’on peut actuellement exécuter pas à pas la logique
comptime. C’était un sujet discuté récemmentJulia devrait peut-être envisager de passer à Zig pour obtenir des gains de performance significatifs. Je me souviens que les auteurs de Julia s’inquiétaient nerveusement des régressions de performance à chaque release de LLVM
Le compilateur est assez largement reciblable, et c’est aussi un domaine en cours de développement actif. On pourrait donc peut-être imaginer, à l’avenir, Zig comme compilateur alternatif pour certaines parties du langage
@code_llvmqui affichent l’IRPar exemple des caches de compilation plus fins, de meilleurs outils pour éviter les invalidations, la suppression de l’optimisation de world splitting, une utilisation accrue du multithreading dans le compilateur, la précompilation automatique des signatures concrètes, et une génération de code plus paresseuse qui hot-swap le code une fois compilé
En tant que débutant complet, je me demande ce qui rend Zig meilleur que d’autres langages. Je le comprends comme un C plus moderne, mais quelle est cette partie moderne ?
Contrairement aux tableaux en C, Zig a des slices qui connaissent leur longueur, ce qui est meilleur vis-à-vis des dépassements de tampon ; les types optionnels explicites doivent obligatoirement être vérifiés, et les pointeurs nuls ne sont pas autorisés. Même lorsqu’ils le sont pour l’intégration avec du code C, le type l’indique clairement
Il y a aussi les enum, les unions taguées et la vérification exhaustive imposée des expressions
switchLa gestion des erreurs est explicite : une fonction renvoie une erreur (une valeur d’enum) que l’appelant doit traiter d’une manière ou d’une autre. En C, même si une fonction renvoie un entier pour indiquer une erreur, on peut l’ignorer complètement
En revanche, il n’y a pas de manière standard intégrée au langage pour renvoyer des données avec une erreur. Le pattern consistant à passer une structure d’erreur en paramètre donne l’impression d’avoir été greffé, et je pense qu’il faudrait une syntaxe spéciale pour cela
Il existe des blocs
defereterrdeferpour le nettoyage après un retour de fonction ou une erreur, et au lieu de macros on peut utiliser la génération de codecomptimeet la réflexion de type comme@typeInfoEn passant des allocateurs aux bibliothèques, l’appelant décide généralement où et comment allouer la mémoire, et rien qu’avec
GeneralPurposeAllocator, il est facile de trouver les fuites mémoireDepuis que j’ai commencé à programmer, j’ai toujours utilisé des langages de haut niveau et je détestais les aspects obscurs et contre-intuitifs de C et de son écosystème ; Zig m’a donné envie, pour la première fois, de faire de la programmation système avec plaisir
Est-ce seulement le backend qui a été remplacé ? Je me demande si toutes les passes d’analyse et de typage restent présentes, ou si la validation est elle aussi réduite
Les cycles de compilation rapides aident la productivité, mais seulement s’ils incluent aussi des tests rapides
Dans ce cas, ne serait-il pas plus simple d’exécuter Zig en mode interprété pour le debug ? Cela résoudrait aussi le problème de devoir refaire le travail pour chaque cible
gdboulldbne me semble pas trivial. Ces outils s’attendent à un exécutable avec des informations de débogage DWARFJ’ajouterais que, notamment dans des domaines comme le développement de jeux, les performances en mode debug comptent vraiment beaucoup
Il n’y a pas de réel besoin d’ajouter un interpréteur. Avoir un backend personnalisé signifie qu’il sert aujourd’hui au debug, mais qu’à bien plus long terme il pourrait aussi rivaliser avec LLVM en vitesse
Ajouter un interpréteur serait peu utile, puisqu’il faudrait de toute façon écrire un backend personnalisé
Le problème est que LLVM est lent, aussi bien en debug qu’en release
N’est-ce pas l’un des prérequis pour ramener async/await dans Zig ?
https://github.com/ziglang/zig/wiki/FAQ#what-is-the-status-o...