デバッグモードでセルフホスト x86 バックエンドがデフォルトに
(ziglang.org)- Zig は x86_64 ターゲットで、LLVM が bitcode をオブジェクトファイルへ lowering していた従来のデフォルト経路を セルフホスト x86 バックエンドに変更し、デバッグビルドのコンパイル速度とメモリ使用量を大きく削減
- セルフホスト x86 バックエンドは 1987件の behavior test に合格し、LLVM バックエンドの1980件を上回る。全2084件のうち一部の追加テストは self-hosted x86 テストでのみ実行される
hello.zigベンチマークでは、LLVM 経路の平均 918ms がデフォルトのセルフホストバックエンドで 275ms に短縮され、wall time が70.1%減少し、peak RSS も214MBから137MBに低下- Zig compiler 自体のような大規模プロジェクトでもビルド時間が 75秒から20秒 に短縮されたが、Windows は COFF linker の作業がさらに必要なため、まだデフォルト切り替えの対象ではない
- 残作業は、コード生成の完全並列化、linker 改善、incremental compilation の安定化、x86 コード品質の改善、aarch64 バックエンド拡張へと続く
x86_64 デフォルトバックエンドの切り替え
- x86_64 ターゲットのビルドで、Zig は今後デフォルトで セルフホスト x86 バックエンドを使用する
- 以前のデフォルト経路は、LLVM が bitcode ファイルをオブジェクトファイルへ lowering する方式だった
- Windows ではまだデフォルトは変更されていない
- COFF linker の作業がさらに必要なため
behavior test の合格状況
- セルフホスト x86 バックエンドは 1987件の behavior test に合格
- LLVM バックエンドは 1980件の behavior test に合格
- behavior test 全体は2084件だが、追加テストはおおむね LLVM のセルフホスト x86 バックエンドテストと重複している
- これらの追加テストは self-hosted x86 テスト時のみ実行される
- 合格数で見ると、Zig の x86 バックエンドは Zig 言語実装において LLVM バックエンドより先行している状態
LLVM 経路と競合する理由
- Zig がコード生成で LLVM と競合する最大の理由は、コンパイル速度の差を大きくできるため
- 関連する背景は Ziggit の説明 にまとめられている
hello.zig ベンチマーク
zig build-exe hello.zig -fllvmの結果:- 平均 wall time: 918ms
- peak RSS: 214MB
- CPU cycles: 4.53G
- instructions: 8.50G
zig build-exe hello.zigのデフォルト経路の結果:- 平均 wall time: 275ms
- peak RSS: 137MB
- CPU cycles: 1.57G
- instructions: 3.21G
- デフォルトのセルフホストバックエンドは、LLVM 経路に比べて複数の指標を削減
- wall time 70.1%減少
- peak RSS 36.2%減少
- CPU cycles 65.2%減少
- instructions 62.2%減少
- cache misses 86.1%減少
- branch misses 78.3%減少
大規模プロジェクトでの効果
- Zig compiler 自体のようなより大規模なプロジェクトでは、ビルド時間が 75秒から20秒 に短縮
- セルフホスト x86 バックエンドは小さな例だけでなく、大規模コードベースでもコンパイル時間を大きく削減できる
次の作業
- Zig はすでに コード生成の完全並列化 作業を開始している
- 関連デモは asciinema の記録 として提供されている
- linker の改善とバグ修正がさらに進めば、このバックエンドとともに incremental compilation を安定的で堅牢なものにできる
- 生成される x86 コード品質には、まだ改善の余地が残っている
- 次のターゲットは aarch64 で、新しい Legalize pass により作業が加速すると期待されている
- 最新の master branch ビルドは Zig のダウンロードページから入手して直接試せる
1件のコメント
Hacker Newsの意見
私の知る限り、Zigではより良い開発体験のために進行中の作業がたくさんあります。ほぼ毎日のように何かが進められていて、つい先ほども https://github.com/ziglang/zig/pull/24124 のようなものが上がりました
以前はホットコード置換も計画していたと記憶していますが、今の開発速度なら x86_64 で1年以内に動いても驚かないと思います
今、個人的に一番つらいのは
comptimeの速度です。コンパイラがここでやるべきことは多く、コンパイル時に brainF** DSL を走らせるのはかなり遅いです。実際にやってみましたが、面白い実験ではありましたZig が導入している新しいバックエンド全般にはとても期待しています。Zig 用の URCL(https://github.com/ModPunchtree/URCL) バックエンドを自分で作ってみたいです
comptimeの性能改善については、何をすべきか分かっていて、かなり前にブランチでの作業も始めていました。ただし意味解析コードをかなり作り直す必要があるため、確実に可能で、やるべきで、いずれやることではありますが、他の優先事項と競合していますcomptimeが遅いことが本当に問題なのか気になります。JSON-RPC ライブラリを作っていて、JSON リクエストを任意の関数にディスパッチするためにcomptimeに大きく依存しています厳格な静的型付けのため、実行時に任意の引数を持つ関数へ動的ディスパッチする方法がなく、見つけた唯一の方法はコンパイル時に
comptimeで関数型のマッピングを解決することでした任意の関数ごとに
comptime済みのコードコピーが増えるので、コードサイズは大きくなりそうです具体的には、AIR を受け取ってメモリ安全性レポートを作るバックエンドを作れるのではないかと思います。未定義値の使用、スタックポインタの脱出、解放後使用、二重解放、alias xor mut のようなものを特定する形です
すでに大きな成果ですが、開発ログに書かれているように、これからさらに多くが残っています。コンパイル中にバイナリ内の必要な部分だけを修正するコンパイラというアイデアは新鮮でありながら完全に型破りですが、いまや Zig プロジェクトの手が届くところに入ってきたようです
今後が楽しみです
「Zig コンパイラのような大きなプロジェクトは75秒から20秒に短縮される。これはまだ始まったばかりだ」という部分に期待しています。この人がこれで何をできるのか気になりますし、本当に頭が良さそうです
パッケージ管理はどんな状態なのか気になります。QuickJS + SDL3 アプリを作ってみようとしましたが、C++ 側の混乱のため Rust に移り、そちらでは普通にうまくいきました。Zig でも試せるとよいのですが
利点もあり、任意のアーカイブに依存できますし、C ライブラリをラップした多くの Zig パッケージは、変更していない tarball リリースに依存するビルドスクリプトに近いものでもあります。もちろん初心者には少し難しめです
SDL3 にはネイティブの Zig ラッパーがあります: https://github.com/Gota7/zig-sdl3
C ライブラリ/API をよりそのまま再パッケージしたものもあります: https://github.com/castholm/SDL
QuickJS は C API が唯一の選択肢です: https://github.com/allyourcodebase/quickjs-ng
Zig はこのようにC パッケージを直接使うことを非常に簡単にしてくれますが、Zig の型はずっと厳格なので、API とやり取りするときに多くのキャストをすることになります
real 0m18.444s,user 0m17.408s,sys 0m1.688sかなり古いプロセッサでもこの程度なので、あまりに速く動くため、あえてアップグレードしませんでした
AMD Athlon(tm) 64 X2 Dual Core Processor 4400+, 2コア、2.3GHz、キャッシュ512KB といった仕様ですD や Nature のときにも言いましたが、独自バックエンドを持つすべての言語について、私たちはLLVM に依存しないようにするプロジェクトを支援する義務があります
LLVM のせいでコンパイラの研究開発が停滞し、あまりに多くの言語が LLVM に依存することを選び、あまりに多くの人が速いイテレーション時間を価値あるものと見なさなくなった、あるいはより良いものを期待しなくなったように思います
インクリメンタルコンパイルとバイナリパッチで高速に反復し、デバッグも優れていることが新しい言語への期待値であるべきで、ニッチな機能や難しすぎることとして扱われるべきではありません
リアルタイムレンダリング業界全体が事実上 LLVM または LLVM フォークの上に構築されており、Microsoft もシェーダーコンパイラを LLVM に切り替え、ようやくコードをアップストリームし始めています
ほとんどのゲームコンソールのコンパイラインフラも Clang ベースです。Xbox はこれまで MSVC に固執していますが、例外に近いです
全体として LLVM は、特に新しいもののブートストラップにおいて非常に大きな成功を収めました
催促したり、感謝していないように聞こえたりしたいわけではありません。Zig は無償で行われている作業なので。ただ、現実的な 1.0 のスケジュールが一番気になります
Zig は低レベル言語に求めていたものとほぼぴったり一致していて、安定化を待っているところです
もちろん、Zig のミニマルな設計哲学には本当に感謝しています
zig initで作った hello world プログラムは、コンパイルすると 9.3MB になります。-Doptimize=ReleaseSmallの 7.6KB と比べると 1000 倍以上大きく、すごい差です-OReleaseSmall -fno-stripは 580KB の実行ファイルを作り、-ODebug -fstripは 1.4MB の実行ファイルを作りますZig の x86 バックエンドは、Zig を理解する lldb のフォークと組み合わせることで、はるかに良いデバッグ体験を提供します: https://github.com/ziglang/zig/wiki/LLDB-for-Zig
今
comptimeロジックをステップ実行できるかどうかは覚えていません。最近議論していた話題ではありますJulia がかなりの性能向上を得るには、Zig への移行を検討すべきなのではないかと思います。LLVM のリリースごとに性能低下を心配して不安がっていた Julia 作者たちを覚えています
コンパイラはかなりリターゲット可能で、これも活発に進行中の領域です。そのため将来、言語の一部の断片向けの代替コンパイラとして Zig を想像することはできるかもしれません
@code_llvmのようなマクロがありますより細粒度のコンパイルキャッシュ、無効化を防ぐより良いツール、world splitting 最適化の削除、コンパイラのマルチスレッド活用拡大、具体的なシグネチャの自動事前コンパイル、コンパイル後にコードをホットスワップするより遅延的なコード生成、といったものです
完全な初心者の立場から、Zig が他の言語より優れている点は何なのか気になります。より現代的な C だと理解していますが、その 現代的な部分とは何ですか?
C の配列と違って Zig には長さを知っているスライスがあり、バッファオーバーフローに関してより安全です。また、明示的な選択型は必ず確認しなければならず、ヌルポインタは許されません。C コードと統合する際に許される場合でも、型がその点を明確に示します
enum、タグ付き union、
switch式の強制された網羅性チェックもありますエラー処理は明示的で、関数は呼び出し側が何らかの形で処理しなければならないエラー(enum 値)を返します。C では関数がエラーを表す整数を返しても、完全に無視できます
ただし、エラーと一緒にデータを返す標準的な方法は言語に組み込まれていません。パラメータとしてエラー構造体を渡すパターンは後付けのように感じるので、そのための特別な構文があるべきだと思います
関数の return やエラー発生後のクリーンアップ用に
defer、errdeferブロックがあり、マクロの代わりにcomptimeコード生成や@typeInfoのような型リフレクションを使えますライブラリにアロケータを渡すことで、通常は呼び出し側がメモリをどこでどのように割り当てるかを決めますし、
GeneralPurposeAllocatorだけでもメモリリークを見つけやすくなりますプログラミングを始めてからずっと高水準言語を使ってきて、C とその周辺エコシステムの難解で直感に反する点が嫌いだったのですが、Zig のおかげで初めてシステムプログラミングを楽しくできるようになりました
これはバックエンドだけを置き換えたものですか? すべての解析と型パスはまだ残っているのか、それとも検証も減らしているのか気になります
高速なコンパイルサイクルは生産性に役立ちますが、高速なテストも含まれている場合に限ると思います
それならデバッグ用には Zig をそのままインタプリタ実行するほうが簡単では? そうすれば各ターゲットごとに作業を繰り返す問題も解決しそうです
gdbやlldbのような標準デバッガに接続するのは些細なことではなさそうです。そうしたツールは DWARF デバッグ情報付きの実行ファイルを期待するからです付け加えると、特にゲーム開発のような領域では デバッグモードの性能も実際に非常に重要です
インタプリタを追加する実質的な必要はありません。カスタムバックエンドがあるということは、今はデバッグに使われていますが、ずっと先の将来には速度面で LLVM と競争できる可能性もあるということです
インタプリタを追加しても、結局カスタムバックエンドを書く必要があるので、あまり有用ではありません
問題は LLVM がデバッグでもリリースでも遅いことです
これは Zig に async/await を戻すための前提条件の一つではありませんか?
https://github.com/ziglang/zig/wiki/FAQ#what-is-the-status-o...