1 ポイント 投稿者 GN⁺ 2025-06-09 | 1件のコメント | WhatsAppで共有
  • 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 はすでに コード生成の完全並列化 作業を開始している
  • linker の改善とバグ修正がさらに進めば、このバックエンドとともに incremental compilation を安定的で堅牢なものにできる
  • 生成される x86 コード品質には、まだ改善の余地が残っている
  • 次のターゲットは aarch64 で、新しい Legalize pass により作業が加速すると期待されている
  • 最新の master branch ビルドは Zig のダウンロードページから入手して直接試せる

1件のコメント

 
GN⁺ 2025-06-09
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 の性能改善については、何をすべきか分かっていて、かなり前にブランチでの作業も始めていました。ただし意味解析コードをかなり作り直す必要があるため、確実に可能で、やるべきで、いずれやることではありますが、他の優先事項と競合しています
    • ホットコード置換はゲーム開発にとって非常に大きいでしょう。Zig が実質的にコンパイラフラグ1つで標準サポートするようになるという発想はすごいです。clang で一度やってみろと言いたくなります
    • comptime が遅いことが本当に問題なのか気になります。JSON-RPC ライブラリを作っていて、JSON リクエストを任意の関数にディスパッチするために comptime に大きく依存しています
      厳格な静的型付けのため、実行時に任意の引数を持つ関数へ動的ディスパッチする方法がなく、見つけた唯一の方法はコンパイル時に comptime で関数型のマッピングを解決することでした
      任意の関数ごとに comptime 済みのコードコピーが増えるので、コードサイズは大きくなりそうです
    • カスタムバックエンドを作るのが簡単なのか気になります。まだ見ていませんが、実験してみたいです
      具体的には、AIR を受け取ってメモリ安全性レポートを作るバックエンドを作れるのではないかと思います。未定義値の使用、スタックポインタの脱出、解放後使用、二重解放、alias xor mut のようなものを特定する形です
    • URCL のせいでラビットホールに入りつつあります。まだ深く見てはいませんが、いちばん面白いタイムラインは、Minecraft用に作られた中間表現が複数言語の実用的なコンパイル先になることです
  • すでに大きな成果ですが、開発ログに書かれているように、これからさらに多くが残っています。コンパイル中にバイナリ内の必要な部分だけを修正するコンパイラというアイデアは新鮮でありながら完全に型破りですが、いまや Zig プロジェクトの手が届くところに入ってきたようです
    今後が楽しみです

  • 「Zig コンパイラのような大きなプロジェクトは75秒から20秒に短縮される。これはまだ始まったばかりだ」という部分に期待しています。この人がこれで何をできるのか気になりますし、本当に頭が良さそうです
    パッケージ管理はどんな状態なのか気になります。QuickJS + SDL3 アプリを作ってみようとしましたが、C++ 側の混乱のため Rust に移り、そちらでは普通にうまくいきました。Zig でも試せるとよいのですが

    • Zig のパッケージ管理は Rust よりも手作業寄りです。CLI でパッケージ URL を取得したあと、ビルドスクリプトでモジュールを取り込む方式です
      利点もあり、任意のアーカイブに依存できますし、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 とやり取りするときに多くのキャストをすることになります
    • dmd D コンパイラは自分自身をデバッグビルドでコンパイルできます
      real 0m18.444s, user 0m17.408s, sys 0m1.688s
      かなり古いプロセッサでもこの程度なので、あまりに速く動くため、あえてアップグレードしませんでした
      AMD Athlon(tm) 64 X2 Dual Core Processor 4400+, 2コア、2.3GHz、キャッシュ512KB といった仕様です
    • それを行うガイドがあるのか気になります。Zig をコンパイルしてみたときは複数の段階を経るため時間がかかり、wasm でブートストラップする全工程が含まれていました
    • Zig が自分自身を75秒でコンパイルできるというのは驚きです。LLVM を使うとしてもそうです
  • D や Nature のときにも言いましたが、独自バックエンドを持つすべての言語について、私たちはLLVM に依存しないようにするプロジェクトを支援する義務があります
    LLVM のせいでコンパイラの研究開発が停滞し、あまりに多くの言語が LLVM に依存することを選び、あまりに多くの人が速いイテレーション時間を価値あるものと見なさなくなった、あるいはより良いものを期待しなくなったように思います
    インクリメンタルコンパイルとバイナリパッチで高速に反復し、デバッグも優れていることが新しい言語への期待値であるべきで、ニッチな機能や難しすぎることとして扱われるべきではありません

    • 逆に LLVM は、個人が作った言語でもすぐに競争力のある性能と幅広いプラットフォーム対応を持てるようにし、爆発的に増やしました。Zig もその一つです
      リアルタイムレンダリング業界全体が事実上 LLVM または LLVM フォークの上に構築されており、Microsoft もシェーダーコンパイラを LLVM に切り替え、ようやくコードをアップストリームし始めています
      ほとんどのゲームコンソールのコンパイラインフラも Clang ベースです。Xbox はこれまで MSVC に固執していますが、例外に近いです
      全体として LLVM は、特に新しいもののブートストラップにおいて非常に大きな成功を収めました
    • その通りです。Go について肯定的に見ている数少ない点の一つが、ブートストラップ済みで LLVM に依存していないことです
  • 催促したり、感謝していないように聞こえたりしたいわけではありません。Zig は無償で行われている作業なので。ただ、現実的な 1.0 のスケジュールが一番気になります
    Zig は低レベル言語に求めていたものとほぼぴったり一致していて、安定化を待っているところです
    もちろん、Zig のミニマルな設計哲学には本当に感謝しています

    • TigerBeetle のような本格的なプロジェクトはバージョンを固定していて、おそらく最新リリースを使っているのだと思います。nightly は実験用に近いと見ています
  • zig init で作った hello world プログラムは、コンパイルすると 9.3MB になります。-Doptimize=ReleaseSmall の 7.6KB と比べると 1000 倍以上大きく、すごい差です

    • その観察は正しいです。もう一つの観察として、そのうち 82% がデバッグ情報だという点があります
      -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 作者たちを覚えています

    • Julia は実質的に LLVM に強く結び付いています。エコシステムの大きな部分が、intrinsic、自動微分(Enzyme)、GPU コンパイルのために LLVM の存在に依存しています。Base と Core は言うまでもありません
      コンパイラはかなりリターゲット可能で、これも活発に進行中の領域です。そのため将来、言語の一部の断片向けの代替コンパイラとして Zig を想像することはできるかもしれません
    • LLVM は Julia の公開 API の一部と見なされているのでは? 実際に IR を表示する @code_llvm のようなマクロがあります
    • コンパイル時間を減らす方法にはなり得ますが、Julia 側にはまだやるべきことが多いと思います
      より細粒度のコンパイルキャッシュ、無効化を防ぐより良いツール、world splitting 最適化の削除、コンパイラのマルチスレッド活用拡大、具体的なシグネチャの自動事前コンパイル、コンパイル後にコードをホットスワップするより遅延的なコード生成、といったものです
    • 新しいコンパイラバックエンドが出るたびに、こういう話が出ます。かなり懐疑的ではありますが、誰かがプロジェクトとして取り組んだら何が起きるのかを見るのは興味深いでしょう
  • 完全な初心者の立場から、Zig が他の言語より優れている点は何なのか気になります。より現代的な C だと理解していますが、その 現代的な部分とは何ですか?

    • 思い付くものをいくつか挙げると、まず複数の別々の難解なツールや言語を使わない統合ビルドシステムがあります
      C の配列と違って Zig には長さを知っているスライスがあり、バッファオーバーフローに関してより安全です。また、明示的な選択型は必ず確認しなければならず、ヌルポインタは許されません。C コードと統合する際に許される場合でも、型がその点を明確に示します
      enum、タグ付き union、switch 式の強制された網羅性チェックもあります
      エラー処理は明示的で、関数は呼び出し側が何らかの形で処理しなければならないエラー(enum 値)を返します。C では関数がエラーを表す整数を返しても、完全に無視できます
      ただし、エラーと一緒にデータを返す標準的な方法は言語に組み込まれていません。パラメータとしてエラー構造体を渡すパターンは後付けのように感じるので、そのための特別な構文があるべきだと思います
      関数の return やエラー発生後のクリーンアップ用に defererrdefer ブロックがあり、マクロの代わりに comptime コード生成@typeInfo のような型リフレクションを使えます
      ライブラリにアロケータを渡すことで、通常は呼び出し側がメモリをどこでどのように割り当てるかを決めますし、GeneralPurposeAllocator だけでもメモリリークを見つけやすくなります
      プログラミングを始めてからずっと高水準言語を使ってきて、C とその周辺エコシステムの難解で直感に反する点が嫌いだったのですが、Zig のおかげで初めてシステムプログラミングを楽しくできるようになりました
  • これはバックエンドだけを置き換えたものですか? すべての解析と型パスはまだ残っているのか、それとも検証も減らしているのか気になります
    高速なコンパイルサイクルは生産性に役立ちますが、高速なテストも含まれている場合に限ると思います
    それならデバッグ用には Zig をそのままインタプリタ実行するほうが簡単では? そうすれば各ターゲットごとに作業を繰り返す問題も解決しそうです

    • デバッグモードの核心はデバッグ可能性ですが、インタプリタ実行している Zig を gdblldb のような標準デバッガに接続するのは些細なことではなさそうです。そうしたツールは DWARF デバッグ情報付きの実行ファイルを期待するからです
      付け加えると、特にゲーム開発のような領域では デバッグモードの性能も実際に非常に重要です
    • 置き換えられたのはバックエンドだけです。テストも速くなるはずです
      インタプリタを追加する実質的な必要はありません。カスタムバックエンドがあるということは、今はデバッグに使われていますが、ずっと先の将来には速度面で LLVM と競争できる可能性もあるということです
      インタプリタを追加しても、結局カスタムバックエンドを書く必要があるので、あまり有用ではありません
      問題は LLVM がデバッグでもリリースでも遅いことです
  • これは Zig に async/await を戻すための前提条件の一つではありませんか?
    https://github.com/ziglang/zig/wiki/FAQ#what-is-the-status-o...

    • その部分はすべて整理済みで、今後 2〜3 か月以内に興味深いアップデートを共有できると思います。I/O を土台から作り直していて、その大半は標準ライブラリの作業です
    • リンクを読んでみると、async は戻ってこないか、少なくとも 2028 年までは戻ってこないように見えます