- Für x86_64-Ziele hat Zig den bisherigen Standardpfad, bei dem LLVM Bitcode in Objektdateien absenkte, auf das selbstgehostete x86-Backend umgestellt und damit die Kompiliergeschwindigkeit sowie den Speicherverbrauch bei Debug-Builds deutlich reduziert
- Das selbstgehostete x86-Backend besteht 1987 Behavior-Tests und damit mehr als das LLVM-Backend mit 1980; von insgesamt 2084 Tests werden einige zusätzliche Tests nur bei self-hosted-x86-Tests ausgeführt
- Im
hello.zig-Benchmark sank die durchschnittliche 918 ms des LLVM-Pfads beim standardmäßigen selbstgehosteten Backend auf 275 ms, wodurch die Wall Time um 70,1 % zurückging; auch der Peak-RSS fiel von 214 MB auf 137 MB - Selbst bei großen Projekten wie dem Zig-Compiler selbst sank die Build-Zeit von 75 Sekunden auf 20 Sekunden, doch unter Windows ist die Umstellung noch nicht Standard, da beim COFF Linker noch mehr Arbeit nötig ist
- Zu den verbleibenden Aufgaben gehören vollständige Parallelisierung der Codegenerierung, Verbesserungen am Linker, Stabilisierung der inkrementellen Kompilierung, bessere x86-Codequalität und die Erweiterung des aarch64-Backends
Umstellung des Standard-Backends für x86_64
- Bei Builds für x86_64-Ziele verwendet Zig jetzt standardmäßig das selbstgehostete x86-Backend
- Der bisherige Standardpfad war, dass LLVM Bitcode-Dateien in Objektdateien absenkt
- Unter Windows wurde der Standardwert noch nicht geändert
- Dafür ist noch mehr Arbeit am COFF Linker nötig
Stand der bestandenen Behavior-Tests
- Das selbstgehostete x86-Backend besteht 1987 Behavior-Tests
- Das LLVM-Backend besteht 1980 Behavior-Tests
- Insgesamt gibt es 2084 Behavior-Tests, aber die zusätzlichen Tests überschneiden sich größtenteils mit den LLVM-eigenen x86-Backend-Tests
- Diese zusätzlichen Tests werden nur bei self-hosted-x86-Tests ausgeführt
- Gemessen an der Zahl bestandener Tests ist Zigs x86-Backend in der Implementierung der Zig-Sprache weiter als das LLVM-Backend
Warum mit dem LLVM-Pfad konkurrieren?
- Der wichtigste Grund, warum Zig bei der Codegenerierung mit LLVM konkurriert, ist, dass sich dadurch ein großer Unterschied bei der Kompiliergeschwindigkeit erzielen lässt
- Der Hintergrund dazu ist in der Erklärung auf Ziggit zusammengefasst
hello.zig-Benchmark
- Ergebnis von
zig build-exe hello.zig -fllvm:- durchschnittliche Wall Time: 918 ms
- Peak RSS: 214 MB
- CPU cycles: 4.53G
- instructions: 8.50G
- Ergebnis des Standardpfads mit
zig build-exe hello.zig:- durchschnittliche Wall Time: 275 ms
- Peak RSS: 137 MB
- CPU cycles: 1.57G
- instructions: 3.21G
- Das standardmäßige selbstgehostete Backend reduziert gegenüber dem LLVM-Pfad mehrere Kennzahlen
- Wall Time 70,1 % weniger
- Peak RSS 36,2 % weniger
- CPU cycles 65,2 % weniger
- instructions 62,2 % weniger
- cache misses 86,1 % weniger
- branch misses 78,3 % weniger
Wirkung bei großen Projekten
- Bei größeren Projekten wie dem Zig-Compiler selbst sank die Build-Zeit von 75 Sekunden auf 20 Sekunden
- Das selbstgehostete x86-Backend kann die Kompilierzeit also nicht nur bei kleinen Beispielen, sondern auch in großen Codebasen deutlich reduzieren
Nächste Arbeiten
- Zig hat bereits mit der vollständigen Parallelisierung der Codegenerierung begonnen
- Eine zugehörige Demo ist als asciinema-Aufzeichnung verfügbar
- Wenn weitere Verbesserungen am Linker und Bugfixes erfolgen, kann zusammen mit diesem Backend die inkrementelle Kompilierung stabil und robust gemacht werden
- Bei der Qualität des erzeugten x86-Codes gibt es noch Raum für Verbesserungen
- Das nächste Ziel ist aarch64; dank des neuen Legalize-Passes dürfte die Arbeit daran beschleunigt werden
- Aktuelle Builds des Master-Branches können direkt von der Zig-Download-Seite heruntergeladen und ausprobiert werden
1 Kommentare
Hacker-News-Meinungen
Soweit ich weiß, passiert bei Zig viel, um die Entwicklererfahrung zu verbessern. Fast jeden Tag wird an irgendetwas gearbeitet, und gerade eben kam auch so etwas wie https://github.com/ziglang/zig/pull/24124 rein.
Früher war meines Wissens auch Hot Code Replacement geplant; bei dem aktuellen Entwicklungstempo würde es mich nicht überraschen, wenn es auf x86_64 innerhalb eines Jahres funktioniert.
Mein persönlich größter Schmerzpunkt ist derzeit die Geschwindigkeit von
comptime. Der Compiler hat hier noch viel zu tun, und zur Compile-Zeit eine brainF**-DSL laufen zu lassen, ist ziemlich langsam. Ich habe es selbst ausprobiert; es war aber ein lustiges Experiment.Die neuen Backends, die Zig einführt, machen insgesamt sehr viel Hoffnung. Ich würde gern selbst ein URCL-Backend (https://github.com/ModPunchtree/URCL) für Zig bauen.
comptimeist bekannt, was zu tun ist, und vor langer Zeit wurde auch schon ein Branch dafür begonnen. Allerdings muss dafür viel am semantischen Analysecode überarbeitet werden; es ist also definitiv machbar, nötig und wird passieren, konkurriert aber mit anderen Prioritäten.comptimelangsam ist. Ich baue gerade eine JSON-RPC-Bibliothek und verlasse mich stark aufcomptime, um JSON-Requests an beliebige Funktionen zu dispatchen.Wegen der strengen statischen Typisierung gibt es zur Laufzeit keine Möglichkeit, dynamisch an Funktionen mit beliebigen Parametern zu dispatchen; der einzige Weg, den ich gefunden habe, war, die Zuordnung der Funktionstypen zur Compile-Zeit mit
comptimezu ermitteln.Für jede beliebige Funktion wächst die Zahl der mit
comptimeerzeugten Codekopien, daher dürfte die Codegröße zunehmen.Konkret könnte ich mir vorstellen, ein Backend zu bauen, das AIR entgegennimmt und einen Bericht zur Speichersicherheit erstellt. Also Dinge wie die Nutzung undefinierter Werte, entweichende Stack-Pointer, Use-after-free, Double-free oder alias xor mut identifiziert.
Das ist schon eine enorme Leistung, aber wie im Entwicklungslog steht, bleibt noch viel mehr zu tun. Die Idee eines Compilers, der beim Kompilieren nur die nötigen Teile im Binary verändert, ist frisch und zugleich völlig radikal; jetzt scheint sie für das Zig-Projekt in greifbare Nähe gerückt zu sein.
Ich bin gespannt auf das, was kommt.
Der Teil „ein großes Projekt wie der Zig-Compiler sinkt von 75 Sekunden auf 20 Sekunden. Wir fangen gerade erst an“ macht mich neugierig. Ich bin gespannt, was diese Person damit erreichen kann; sie wirkt wirklich sehr klug.
Ich frage mich, wie der Stand beim Package Management ist. Ich hatte versucht, eine QuickJS- + SDL3-App zu bauen, bin wegen des Chaos auf der C++-Seite aber zu Rust gewechselt, und dort hat es einfach funktioniert. Es wäre schön, wenn man das auch mit Zig ausprobieren könnte.
Das hat auch Vorteile: Man kann von beliebigen Archiven abhängen, und viele Zig-Pakete, die C-Bibliotheken umhüllen, sind eher Build-Skripte, die von unveränderten Tarball-Releases abhängen. Für Anfänger ist es natürlich etwas anspruchsvoller.
Für SDL3 gibt es einen nativen Zig-Wrapper: https://github.com/Gota7/zig-sdl3
Es gibt auch eine grundlegendere Neuverpackung der C-Bibliothek/API: https://github.com/castholm/SDL
Bei QuickJS ist die C-API die einzige Option: https://github.com/allyourcodebase/quickjs-ng
Zig macht es sehr einfach, C-Pakete auf diese Weise direkt zu nutzen, aber Zigs Typen sind deutlich strenger, sodass man bei der Interaktion mit APIs viel casten muss.
real 0m18.444s,user 0m17.408s,sys 0m1.688sSelbst auf einem sehr alten Prozessor ist er so schnell, dass ich keinen Grund hatte, aufzurüsten.
Die Spezifikationen sind etwa
AMD Athlon(tm) 64 X2 Dual Core Processor 4400+, 2 Kerne, 2,3 GHz, 512 KB Cache.Ich habe es schon bei D und Nature gesagt: Für alle Sprachen mit eigenem Backend haben wir die Pflicht, Projekte zu unterstützen, die nicht von LLVM abhängig sein wollen.
Wegen LLVM ist die Compiler-Forschung und -Entwicklung ins Stocken geraten, zu viele Sprachen haben sich entschieden, von LLVM abzuhängen, und zu viele Menschen scheinen schnelle Iterationszeiten nicht mehr für wertvoll zu halten oder nichts Besseres mehr zu erwarten.
Schnelle Iteration durch inkrementelle Kompilierung und Binary-Patching sowie gutes Debugging sollten die Erwartung an neue Sprachen sein, nicht als Nischenfeature oder als zu schwieriges Problem gelten.
Die gesamte Echtzeit-Rendering-Branche ist praktisch auf LLVM oder LLVM-Forks aufgebaut, Microsoft hat seinen Shader-Compiler ebenfalls auf LLVM umgestellt und beginnt erst jetzt, Code upstream zu bringen.
Auch der Großteil der Compiler-Infrastruktur für Spielkonsolen basiert auf Clang. Xbox hält bisher an MSVC fest, ist damit aber eher die Ausnahme.
Insgesamt war LLVM besonders beim Bootstrap neuer Dinge ein enormer Erfolg.
Ich möchte nicht so klingen, als würde ich etwas einfordern oder undankbar sein. Zig ist schließlich Arbeit, die kostenlos geleistet wird. Am meisten interessiert mich aber ein realistischer Zeitplan für 1.0
Zig entspricht ziemlich genau dem, was ich mir von einer Low-Level-Sprache gewünscht habe, und ich warte darauf, dass sie stabil wird
Natürlich schätze ich Zigs minimalistische Designphilosophie wirklich sehr
Ein mit
zig initerstelltes Hello-World-Programm ist nach dem Kompilieren 9,3 MB groß. Verglichen mit 7,6 KB bei-Doptimize=ReleaseSmallist das über 1000-mal größer, also enorm-OReleaseSmall -fno-striperzeugt eine ausführbare Datei von 580 KB, und-ODebug -fstriperzeugt eine ausführbare Datei von 1,4 MBZigs x86-Backend bietet zusammen mit einem lldb-Fork, der Zig versteht, eine deutlich bessere Debugging-Erfahrung: https://github.com/ziglang/zig/wiki/LLDB-for-Zig
Ich erinnere mich nicht, ob man
comptime-Logik derzeit schrittweise ausführen kann. Das war kürzlich ein Thema in der DiskussionDamit Julia deutliche Performance-Gewinne erzielen kann, sollte es vielleicht einen Umstieg auf Zig in Betracht ziehen. Ich erinnere mich an Julia-Autoren, die bei jedem LLVM-Release nervös wegen möglicher Performance-Regressionen waren
Der Compiler lässt sich ziemlich gut retargeten, und das ist ebenfalls ein aktiv bearbeitetes Gebiet. Vielleicht kann man sich deshalb in Zukunft Zig als alternativen Compiler für Teile der Sprache vorstellen
@code_llvm, die IR anzeigenEtwa feingranularere Compile-Caches, bessere Werkzeuge zur Vermeidung von Invalidierungen, die Entfernung der World-Splitting-Optimierung, stärkere Nutzung von Multithreading im Compiler, automatische Vorkompilierung konkreter Signaturen und eine noch trägere Codegenerierung, die Code hot-swappt, sobald er kompiliert ist
Aus Sicht eines völligen Anfängers frage ich mich, worin Zig anderen Sprachen überlegen ist. Ich verstehe es als moderneres C, aber was genau ist daran modern?
Anders als C-Arrays hat Zig Slices, die ihre Länge kennen, was in Bezug auf Buffer Overflows besser ist; explizite Option-Typen müssen zwingend geprüft werden, und Null-Pointer sind nicht erlaubt. Selbst wenn sie bei der Integration mit C-Code zulässig sind, macht der Typ das eindeutig sichtbar
Es gibt außerdem enums, Tagged Unions und erzwungene Vollständigkeitsprüfungen bei
switch-AusdrückenFehlerbehandlung ist explizit: Funktionen geben Fehler zurück (enum-Werte), die der Aufrufer auf irgendeine Weise behandeln muss. In C kann man eine Ganzzahl, die eine Funktion als Fehler zurückgibt, komplett ignorieren
Allerdings ist in die Sprache kein Standardweg eingebaut, zusammen mit einem Fehler auch Daten zurückzugeben. Das Muster, eine Fehler-Struct als Parameter zu übergeben, wirkt angeflanscht; ich denke, dafür sollte es spezielle Syntax geben
Für Aufräumarbeiten nach Funktionsrückgaben oder Fehlern gibt es
defer- underrdefer-Blöcke, und statt Makros kann mancomptime-Codegenerierung und Typ-Reflection wie@typeInfoverwendenMan übergibt Bibliotheken Allocators, sodass der Aufrufer normalerweise entscheidet, wo und wie Speicher alloziert wird, und schon mit dem
GeneralPurposeAllocatorlassen sich Speicherlecks leicht findenSeit ich mit dem Programmieren angefangen habe, habe ich durchgehend High-Level-Sprachen verwendet und die schwer durchschaubaren, kontraintuitiven Aspekte von C und seinem Umfeld gehasst; durch Zig macht mir Systemprogrammierung zum ersten Mal Spaß
Wurde hier nur das Backend ausgetauscht? Ich frage mich, ob alle Analyse- und Typ-Passes weiterhin vorhanden sind oder ob auch die Validierung reduziert wird
Schnelle Kompilierzyklen helfen der Produktivität, aber meiner Meinung nach nur, wenn sie auch schnelle Tests einschließen
Wäre es dann für Debug-Zwecke nicht einfacher, Zig einfach interpretiert auszuführen? Das würde wohl auch das Problem lösen, die Arbeit für jedes Target wiederholen zu müssen
gdboderlldbanzubinden, dürfte nicht trivial sein. Solche Werkzeuge erwarten nämlich ausführbare Dateien mit DWARF-Debug-InformationenAußerdem ist gerade in Bereichen wie der Spieleentwicklung auch die Performance im Debug-Modus tatsächlich sehr wichtig
Es gibt keinen wirklichen Bedarf, einen Interpreter hinzuzufügen. Ein eigenes Backend zu haben bedeutet, dass es derzeit für Debug genutzt wird, in deutlich fernerer Zukunft aber in Sachen Geschwindigkeit auch mit LLVM konkurrieren könnte
Selbst wenn man einen Interpreter hinzufügt, müsste man ohnehin ein eigenes Backend schreiben, daher wäre das wenig nützlich
Das Problem ist, dass LLVM sowohl im Debug- als auch im Release-Modus langsam ist
Ist das nicht eine der Voraussetzungen dafür, async/await zurück nach Zig zu bringen?
https://github.com/ziglang/zig/wiki/FAQ#what-is-the-status-o...