ZJIT は冗長なオブジェクトのロードとストアを削除します。

2026/03/19 6:26

ZJIT は冗長なオブジェクトのロードとストアを削除します。

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

改善された概要

ZJIT は、インスタンス変数の処理を劇的に高速化する新しいロード・ストア最適化パスを導入しました。このパスは YJIT および Ruby インタープリタの両方を上回ります。setivar ベンチマークの時間は、YJIT の約 5 ms から ZJIT で約 2 ms に短縮され、YJIT の倍速、ベースラインインタープリタより 25 倍以上高速です。このパスは基本ブロックを走査し、

(object, offset)
ペアをキャッシュして、冗長な
LoadField
/
StoreField
命令を削除または置換します。キャッシュされたロードは取り除かれ、その使用箇所がキャッシュ値に置き換えられます。ストアは、同一の
(object, offset, value)
トリプレットが既に存在する場合にのみ削除されます。
WriteBarrier
などの変更命令でキャッシュエントリーはクリアされ、ストアが発生すると同じオフセットを持つすべてのエントリーが無効化されます(完全な型ベースのエイリアス解析はまだ実装中です)。このパスはブロック局所的であり、メソッド境界を越えません。また、依存関係のある
StoreField
は現在除外されています。既存のパス(
type_specialize
inline
など)の後、
fold_constants
の前に配置されます。将来のリリースでは型ベースのエイリアス解析を追加し、オブジェクトレベルで SSA を試験し、初期化コードへのデッドストア除去を拡張し、全体的にさらに多くの最適化パスを導入します。Ruby 開発者、とりわけインスタンス変数代入が頻繁なワークロードを実行している場合、この機能は実行速度を顕著に向上させ、CPU 消費を削減し、企業がアプリケーションのスケールアップをより効率的に行えるよう支援します。

本文

イントロダクション

昨年末の投稿以降、ZJIT は大きく成長し、いくつか興味深い変化を遂げました。今回の記事では、新しく自己完結型の最適化パスが ZJIT の性能を YJIT を上回るマイクロベンチマークで示した経緯をご紹介します。ZJIT が Ruby に統合されてから 10 ヶ月が経ち、YJIT と ZJIT の設計差異が実際に性能の違いとして現れ始めています。

この記事では、ZJIT の HIR(High‑level Intermediate Representation)で導入された ロード/ストア最適化 について掘り下げます。ZJIT の構造は次のようになっています。

flowchart LR
  A(["Ruby"])
  A --> B(["YARV"])
  B --> C(["HIR"])
  C --> D(["LIR"])
  D --> E(["Assembly"])

Hir(高レベル中間表現)での最適化パスに焦点を当てます。HIR レイヤーでは、SSA(Static Single Assignment)表現と HIR の命令効果システムという他のコンパイル段階とは異なる二つの機能を活用できます。


現在実行される最適化パス(ロード/ストア最適化未導入時)

run_pass!(type_specialize);
run_pass!(inline);
run_pass!(optimize_getivar);
run_pass!(optimize_c_calls);
run_pass!(fold_constants);
run_pass!(clean_cfg);
run_pass!(remove_redundant_patch_points);
run_pass!(eliminate_dead_code);

ロード/ストア最適化を追加後のパス

run_pass!(type_specialize);
run_pass!(inline);
run_pass!(optimize_getivar);
run_pass!(optimize_c_calls);
run_pass!(optimize_load_store);   ← 新しいパス
run_pass!(fold_constants);
run_pass!(clean_cfg);
run_pass!(remove_redundant_patch_points);
run_pass!(eliminate_dead_code);

概要

Ruby はオブジェクト指向言語であるため、CRuby(MRI)は「オブジェクトのロード・変更・ストア」という概念を持つ必要があります。形状システムは CRuby(インタープリターと JIT の両方)に性能改善をもたらしますが、JIT の性能向上余地はまだ十分に残っています。オペコード単位で最適化を行うだけでは、繰り返し発生するロードやストアをプログラム解析パスで洗い出すことができません。この点について先に成果を振り返ってみましょう。


成果

setivar
ベンチマークは 2026‑03‑06(ロード/ストア最適化が ZJIT に統合された日)に劇的に変化しました。執筆時点で、ZJIT はこのベンチマークで平均 2 ms/イテレーション、YJIT は 5 ms/イテレーション を記録しています。

下図は ZJIT(黄色)と YJIT(緑色)が「インタープリターより何倍速いか」(青色)を示したものです。ロード/ストア最適化が実装された瞬間に、ZJIT が YJIT を追い抜く様子が確認できます。

これは ZJIT が YJIT を明確に上回った二度目のケースです。初めての例はここにあります。

高レベルで言えば、ZJIT は繰り返しインスタンス変数への代入で YJIT の約 2 倍、さらにインタープリターより 25 倍以上 速く動作します。


心配な発見

オブジェクトのロードとストアに対する最適化パスが、実際にインスタンス変数代入にどう関係しているのでしょうか?答えは、ZJIT の HIR が

LoadField
StoreField
を「オブジェクトのインスタンス変数と形状」両方で使用していることです。CRuby 形状と ZJIT HIR の内部構造を掘り下げてみましょう。


背景

HIR は

LoadField
StoreField
を持ちます。これらは多目的に使われ、性能向上は主にオブジェクト形状の最適化から生じますが、インスタンス変数にも適用できます。アルゴリズムは両方で同様に機能するため、ここでは扱いやすさを重視してインスタンス変数に焦点を当てます。


以下のような簡単なコードには「二重ストア」があります。

class C
  def initialize
    value = 1
    @a = value
    @a = value   # 冗長なストア
  end
end

この冗長な

StoreField
命令は HIR で除去されます。


Ruby ↔︎ HIR のマッピング

RubyHIR
@var = value
StoreField var, @obj@offset, value
@var
LoadField var, @obj@offset

クラスの

initialize
内ではインスタンス変数操作が形状遷移を引き起こすことが多く、
initialize
外ではロードとストアは直接インスタンス変数にアクセスするケースが増えます。


エッジケース

以下のスニペットは

LoadField
/
StoreField
を除去できる場合とできない場合を示します。

ケースコード
冗長ストア
ruby<br>class C<br>  def initialize<br>    value = 1<br>    @a = value<br>    @a = value   # 冗長<br>  end<br>end
冗長ロード
ruby<br>class C<br>  def initialize<br>    value = 1<br>    @a = value<br>    @a          # すでに value と分かっている<br>  end<br>end
エイリアシング付きストア
ruby<br>class C; attr_accessor :a; def initialize(v); @a=v; end; end<br>class D; attr_accessor :a; def initialize(v); @a=v; end; end<br>def multi_object_test<br>  x = C.new(1)<br>  y = D.new(1)<br>  new_x_val = 2<br>  new_y_val = 3<br>  x.a = new_x_val<br>  y.a = new_y_val<br>  # エイリアシングが分かれば次行を除去できる<br>  x.a = new_x_val\nend
エイリアシングで必要なストア
ruby<br>class C; attr_accessor :a; def initialize(v); @a=v; end; end<br>def multi_object_test<br>  x = C.new(1)<br>  y = x   # エイリアス<br>  new_x_val = 2<br>  new_y_val = 3\n  x.a = new_x_val\n  y.a = new_y_val   # `x` を変更する<br>  x.a = new_x_val    # 除去不可\nend
副作用があるストア
ruby<br>def scary_method(obj); obj.a="modified"; end<br>class C; attr_accessor :a; def initialize(v); @a=v; end; end<br>def effectful_operations_between_stores_test<br>  x = C.new(1)\n  x.a = 5\n  scary_method(x)   # `x` を変更する可能性がある\n  x.a = 5            # 除去不可\nend

アルゴリズム

核心アイデア: オブジェクトに対して軽量な抽象解釈を行う。ロードの置換とストアの除去はプログラム挙動を変えない範囲で実施されますが、機会損失もあるかもしれません。

  • 基本ブロック: 各基本ブロックを走査し、冗長なロード/ストアを検索・更新します。
    StoreField
    は直接削除可能ですが、
    LoadField
    の参照はキャッシュされた値に置き換えます。
  • WriteBarrier: ガーベジコレクション用の書き込みバリアは「ストア」と同様に扱い、関連するキャッシュエントリをクリアしますが削除は行いません。
  • ポインタの詳細: HIR 命令は常にオブジェクトベースと境界内のオフセットで参照します。異なるオフセットは同一メモリ領域を指さないため、エイリアシングチェックが必要です。

擬似コード

for each basic block:
    cache = {}  # key: (object, offset) → value

    for each instruction:
        if LoadField:
            key = (obj, offset)
            if key in cache:
                replace all uses with cached value
                delete this instruction
            else:
                cache[key] = loaded_value

        elif StoreField:
            key = (obj, offset)
            if key in cache and cache[key] == stored_value:
                delete instruction   # 冗長ストア
            else:
                remove all cache entries with same offset  # エイリアシング回避

        elif WriteBarrier:
            remove all cache entries with same offset

        elif instruction can modify objects:
            flush entire cache

return pruned HIR

ソースコード

実装は ZJIT リポジトリに公開されています(リンクは省略)。


HIR の改善例

最適化後、冗長ロード/ストアが消えます。以下はその一例です。

冗長ロード除去

bb3(v8:BasicObject, v9:NilClass):
  ...
  StoreField v30, :@a@0x10, v13
  WriteBarrier v30, v13
  ...
-   v40:BasicObject = LoadField v20, :@a@0x10
-   Return v40
+   Return v13

冗長ストア除去

bb3(v8:BasicObject, v9:NilClass):
  ...
  StoreField v35, :@a@0x10, v13
  WriteBarrier v35, v13
  ...
-   StoreField v20, :@a@0x10, v13
+   # 削除済み
  Return v13

デザインの議論

このパスはオブジェクトに対するロード/ストアのグラフを剪定します。SSA と同様の問題(オブジェクトレベルでの SSA)を解決しつつ、完全な SSA を導入すると HIR の構造が大幅に変わり、他の部分が扱いづらくなる恐れがあります。軽量な SSA 表現を維持することで、Hir 全体をシンプルに保ちつつ、確実な最適化を可能にしています。


今後の展開

  • デッドストア除去: さらに初期化性能を向上させるためのアイデア。
  • タイプベースのエイリアス解析: より積極的な除去を実現するが、型混同バグを防ぐ慎重な設計が必要(phrack 記事 4.1 章参照)。

結論

ZJIT の最適化パートに関する初めての記事をご覧いただきありがとうございます。今後も継続的にアップデートしていく予定ですので、ぜひご期待ください!

同じ日のほかのニュース

一覧に戻る →

2026/03/22 5:32

子ども保護をインターネットアクセス制御に変えるな。

## Japanese Translation: ** ``` ## Summary この記事は、年齢確認が成人向けコンテンツサイトを越えて、ヨーロッパ・米国・英国・オーストラリアなどの主流サービス(ソーシャルメディア、ゲーム、検索等)へと拡大していることを論じている。 規制当局は、OS が永続的に「年齢ステータス」を保持し、システムレベルのインターフェースで公開するよう求めており、これによりすべてのデバイスに適用される一般的なアイデンティティ層が作られる。Linux の systemd は既に年齢保証法への対応としてオプションの `birthDate` フィールドを追加していることから、OS 変更は規制によって駆動されていることが示されている。 成人サイトでの過去の施行は、ユーザーが VPN、借用アカウント、偽データでチェックを回避できたため失敗した。提案された OS レベルのアプローチは、コンテンツモデレーションと保護者責任を混同し、有害なコンテンツ問題を純粋に技術的なものとして扱うリスクがある。一度確立されれば、このアイデンティティ層は位置情報や国籍など他の属性へ拡張でき、規制当局が将来の恐慌時に再利用するゲートとなる可能性がある。 ユーザーにとって、新しいインフラストラクチャはアイデンティティチェック、メタデータログ、ベンダー間での摩擦を追加し、信頼できるデバイスや書類を持たない人々には特に厳しくなる。企業側では、子ども保護の責任がプラットフォーム・ブラウザ・アプリストア・OS ベンダー・アイデンティティ仲介者へと移転し、現地の親や教育者の判断力を侵食する。 著者は、コンテンツモデレーションはローカル(ブラウザ/デバイス/学校ネットワーク)に留め、保護者・教師との監督を維持し、OS はポリシー表面としてのみ使用すべきであり、普遍的な年齢放送層とならないようにすることを訴えている。規制は推奨システム、ダークパターン、依存性メトリクス、拡大を報酬化するビジネスモデルに焦点を当て、全体的なアイデンティティチェックの実施ではなく、これらを対象とすべきだ。 ```

2026/03/22 5:08

TinyBox – オフライン AI デバイス(120 B パラメータ)

## Japanese Translation: Tinycorpのフラッグシッププロジェクトは **Tinygrad** で、エレメントワイズ演算(Unary、Binary、Ternaryを含む)、ReduceOps、および MovementOps の3つのコア操作タイプを中心に構築された軽量ニューラルネットワークフレームワークです。SQRT、LOG2、ADD、MUL、WHERE、SUM、MAX、RESHAPE、PERMUTE、EXPAND などの一般的な数学関数をサポートし、コード内で畳み込みと行列乗算が隠れています。Tinygrad は既に Snapdragon 845 GPU 上で Openpilot モデルを実行するために使用されており、従来の SNPE スタックを置き換えるとともに ONNX サポート、トレーニング機能、注意メカニズム、および推論と逆伝搬の完全な自動微分を追加しています。 同社のフラッグシップハードウェア **Tinybox** は、赤・緑・黒・(近日発売予定)エクサの複数構成で提供されています。主要スペックは以下の通りです:FP16/FP32 加速 FLOPS が 778 TFLOPS / 3 086 TFLOPS(約 1 EXAFLOP)、最大 25 920 GB GPU RAM、GPU 帯域幅 1 244 TB/s、PCIe 5.0 x16 ファブリック、32 コア AMD EPYC/GENOA CPU、最大 23 040 GB システム RAM、480 TB RAID ディスク、53.2 TB/s スケールアウトネットワーク、電力オプションは 1.6 kW〜600 kW、Ubuntu 24.04 OS、12U または独立型ラックマウント フォームファクター。 価格は赤/緑モデルが $12 000、黒/ウェレックスボックスが $65 000 で、エクサモデルは 2027 年頃に約 $10 百万で発売予定です。Tinybox はディープラーニング分野で最高のパフォーマンス/ドル比を実現すると市場にアピールしており、MLPerf Training 4.0 ベンチマークでは価格が 10 倍高いシステムを上回っています。 注文は同社ウェブサイトから行い、支払後 1 週間以内に発送(サンディエゴでの受け取りまたは世界配送)が可能です。支払いは銀行振込のみで、W‑9 フォームはリクエスト時に提供できますが、購入後のカスタマイズは許可されていません。 Tinygrad は現在アルファ版ですが、来年第2四半期までに単一 NVIDIA GPU および Apple の M1 を上回ることを目指しており、推論とトレーニングの両方のワークロードに対して高性能で軽量な代替案としての可能性を示しています。

2026/03/22 9:30

**コメントをもとにしたハッカーニュース利用者のプロファイリング**

## Japanese Translation: Simon Willison(Django、Datasetteの共同開発者であり、Python Software Foundationボードに在籍する独立系ソフトウェア開発者)は、AlgoliaのHacker News APIとClaude大規模言語モデルを使用して自身のコメント履歴を収集・分析し、詳細な個人プロフィールを生成する方法を示しています。APIはCORSを有効にした状態で日付順にコメントをリストアップします。カスタムツール(2023年8月に構築)は最新の最大1,000件のコメントを取得し、Claudeで洗練されたコピー・トゥー・クリップボードボタンを提供します。ダンプデータをClaude Opus 4.6へ貼り付けると、モデルはオンライン活動の包括的なプロファイルを作成します。 Willisonのより広範なワークフロー―「エージェント工学」に根ざしたもの―では、iPhoneでClaude Codeを使用してウェブタスクをコーディングしながら通勤中に2〜3つの並列エージェントセッションを$200/月のClaude Maxプランで実行し、テスト駆動開発(`uv run pytest`)でそれらを安定化させています。彼はサンドボックス/セキュリティ(WebAssembly、Pyodide、Firecracker)、SQLite、uv & PyPIトリック、ブラウザ内のブラウザテスト(`v86`、WASM Linux)、ローカルLLM推論、およびコーディングエージェントを通じてGoを学習する実験に積極的です。彼は「プロンプトインジェクション」という概念を創出し、半年以内にヘッドラインを揺さぶる攻撃の可能性を警告するとともに、OpenClaw/Clawdbotに関するリスクも指摘しています。 Willisonはsimonwillison.net/guidesでエージェント工学に関するガイドを公開予定であり、自身の手法がLLMをプログラマの代替ではなく補完として活用し、将来の開発者ワークフローやAI支援コーディングのセキュリティ実践、責任あるAIに関する議論を形成できることを示すことを期待しています。個人的なタッチとしては、彼のエネルギッシュで対立的なスタイル、透明性の高いバイアス、そして自虐的な「ペリカンベンチマーク」SVGテストがあり、ニッチな博物館、新西蘭のカカポオウム、外国料理、そしてカリフォルニア州ハーフムーン・ベイでの園芸を楽しんでいます。

ZJIT は冗長なオブジェクトのロードとストアを削除します。 | そっか~ニュース