**OCaml でのスレッド制御:Delimited Continuations と Lwt の比較**

- **Delimited Continuations(境界付き継続)**  
  - 軽量に制御フローを扱える手段。計算を任意の箇所で一時停止・再開したい場合、スレッド全体を生成するオーバーヘッドなしで実装できる。
- **Lwt(Lightweight Threads)**  
  - コオペラティブスレッド用の標準ライブラリ。成熟度が高く、ドキュメントも充実しており、多くの OCaml プロジェクトと自然に統合できる。

---

## Delimited Continuations を使うケース

| 条件 | 理由 |
|------|------|
| **細粒度な非同期制御** | 生成器(generator)やコルーチンを実装する際、計算を任意のポイントで停止させたいが、スレッドのオーバーヘッドは避けたい場合。 |
| **可合成効果(Composable Effects)** | 独自の効果ハンドラを構築し、状態管理や例外処理など他の抽象と組み合わせて使いたい時に便利。 |
| **パフォーマンスクリティカルな箇所** | Lwt のプロミスベースモデルではコンテキストスイッチングが発生するため、そのコストを回避したい場合。 |

---

## Lwt が適しているケース

| 条件 | 理由 |
|------|------|
| **標準的なネットワーク I/O** | ソケット、HTTP クライアント/サーバー、ファイル操作など、既に Lwt 用のバインディングが揃っている場合。 |
| **大規模コードベース** | 既存のライブラリが `Lwt.t` 型を前提としているとき、継続を導入すると膨大なリファクタリングが必要になる。 |
| **コミュニティサポート・ツールチェーン** | デバッグツールや診断機能、豊富なサードパーティ製パッケージが揃っている。 |

---

## 実用的比較

| 特徴 | Delimited Continuations | Lwt |
|------|------------------------|-----|
| **API 形態** | `unit -> 'a` のコールバックや独自ハンドラ | `('a, 'e) result Lwt.t` のプロミス |
| **ボイラープレート** | シンプルな一時停止であれば最小限 | `let%lwt` や `>>=` などチェーンが必要 |
| **相互運用性** | 他の非同期ライブラリとの統合は難しい | 多くのライブラリとシームレスに連携 |
| **パフォーマンス** | オーバーヘッド低いが複雑さが増すと管理が大変 | やや高めだが予測可能で安定 |

---

## 推奨

- **ドメイン固有言語(DSL)を構築する際**、または「プロミスでは表現しにくい」制御フローが必要な場合は *Delimited Continuations* を採用。
- **一般的なネットワークサービスや I/O 集約型の処理**、あるいはメンテナンス性とコミュニティサポートを重視するプロジェクトでは *Lwt* を選択。

要するに、抽象度に合わせてツールを使い分けることが重要です。  
- 低レベルの細かな制御 → **Delimited Continuations**  
- 高レベルで実運用可能な非同期プログラミング → **Lwt**

2026/02/03 3:19

**OCaml でのスレッド制御:Delimited Continuations と Lwt の比較** - **Delimited Continuations(境界付き継続)** - 軽量に制御フローを扱える手段。計算を任意の箇所で一時停止・再開したい場合、スレッド全体を生成するオーバーヘッドなしで実装できる。 - **Lwt(Lightweight Threads)** - コオペラティブスレッド用の標準ライブラリ。成熟度が高く、ドキュメントも充実しており、多くの OCaml プロジェクトと自然に統合できる。 --- ## Delimited Continuations を使うケース | 条件 | 理由 | |------|------| | **細粒度な非同期制御** | 生成器(generator)やコルーチンを実装する際、計算を任意のポイントで停止させたいが、スレッドのオーバーヘッドは避けたい場合。 | | **可合成効果(Composable Effects)** | 独自の効果ハンドラを構築し、状態管理や例外処理など他の抽象と組み合わせて使いたい時に便利。 | | **パフォーマンスクリティカルな箇所** | Lwt のプロミスベースモデルではコンテキストスイッチングが発生するため、そのコストを回避したい場合。 | --- ## Lwt が適しているケース | 条件 | 理由 | |------|------| | **標準的なネットワーク I/O** | ソケット、HTTP クライアント/サーバー、ファイル操作など、既に Lwt 用のバインディングが揃っている場合。 | | **大規模コードベース** | 既存のライブラリが `Lwt.t` 型を前提としているとき、継続を導入すると膨大なリファクタリングが必要になる。 | | **コミュニティサポート・ツールチェーン** | デバッグツールや診断機能、豊富なサードパーティ製パッケージが揃っている。 | --- ## 実用的比較 | 特徴 | Delimited Continuations | Lwt | |------|------------------------|-----| | **API 形態** | `unit -> 'a` のコールバックや独自ハンドラ | `('a, 'e) result Lwt.t` のプロミス | | **ボイラープレート** | シンプルな一時停止であれば最小限 | `let%lwt` や `>>=` などチェーンが必要 | | **相互運用性** | 他の非同期ライブラリとの統合は難しい | 多くのライブラリとシームレスに連携 | | **パフォーマンス** | オーバーヘッド低いが複雑さが増すと管理が大変 | やや高めだが予測可能で安定 | --- ## 推奨 - **ドメイン固有言語(DSL)を構築する際**、または「プロミスでは表現しにくい」制御フローが必要な場合は *Delimited Continuations* を採用。 - **一般的なネットワークサービスや I/O 集約型の処理**、あるいはメンテナンス性とコミュニティサポートを重視するプロジェクトでは *Lwt* を選択。 要するに、抽象度に合わせてツールを使い分けることが重要です。 - 低レベルの細かな制御 → **Delimited Continuations** - 高レベルで実運用可能な非同期プログラミング → **Lwt**

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

要約

Japanese Translation:

現在の要約はすでに明確で簡潔かつ主要ポイントリストに忠実です。追加の改訂は不要です。


元の要約の繰り返し

MirageOS はイベント駆動型アーキテクチャを中心に構築されているため、開発者は通常 OCaml の Lwt モナドまたはその構文拡張を使用して非同期コールバックを整理します。この記事では、プレーンな Lwt と

delimcc
ライブラリを介したデリミテッド継続(fiber 実装)を比較しています。マイクロベンチマークによると、ブロッキング呼び出しが多い場合や深い再帰が使用される場合は fiber がわずかに遅くなることがありますが、スタックの末尾で一つだけブロックが発生するケースでは Lwt を上回るパフォーマンスを示します。しかし、MirageOS のワークロードはこれらの差異に対して十分に感度が高くないため、性能のみでどちらのアプローチを採用すべきか決まるわけではありません。代わりに相互運用性と JavaScript サポート(
js_of_ocaml
経由)がより重要になります。この議論は、将来の MirageOS プロジェクトが測定可能な速度向上を必要とする場合に Lwt_fiber や類似の fiber インターフェースを採用するかもしれないことを示唆していますが、現在のところ実行時効率を損なうことなくコードの明瞭さとツール互換性によって選択が導かれる可能性があります。

本文

ミラージュOSは完全にイベント駆動型のシステムであり、従来型のプリエンプティブスレッドをサポートしていません。
プログラムは「イベント」(例えば受信したネットワークパケット)によって起床され、対応するコールバックが実行されます。このコールバックは I/O やタイマーなどでブロックしなければならない場合やタスクを完了したときまで実行され続けます。

イベント駆動型システムは実装が簡単で、ネットワーククライアント数に応じてスケールできる上、node.js のようなフレームワークのおかげで人気があります。
しかし、イベントコールバックを直接書くと制御ロジックが多数の小さな関数に散らばってしまうため、イベント登録・待機による中断を隠す抽象化が必要です。

OCaml の Lwt スレッドライブラリはモナド的アプローチを採用しています。

val return : 'a -> 'a Lwt.t
val bind   : 'a Lwt.t -> ('a -> 'b Lwt.t) -> 'b Lwt.t
val run    : 'a Lwt.t -> 'a

スレッドは型

'a Lwt.t
を持ち、終了時に型
'a
の値を返します。
return
は OCaml の値からそのようなスレッドを作成し、
bind
はスレッドが完了したときに呼び出される関数(=「将来実行する」処理)を組み合わせます。

例えば sleep 操作の場合:

val sleep : int -> unit Lwt.t

let x = sleep 5
let y = bind x (fun () -> print_endline "awake!")
run y

ここで

x
unit Lwt.t
型です。
bind
に渡したクロージャは sleep が終了したときに
unit
を引数として呼び出されます。
run
は実際に Lwt スレッドの評価を開始します。


懸念事項

ミラージュOS はすでに Lwt を広範囲に利用していますが、ユーザーの中には使いづらさを感じる方もいます。主な問題は次のとおりです。

  1. コード書き換え – ブロッキング処理を
    return
    bind
    で適応させる必要があり、サードパーティライブラリの統合が複雑になります。
  2. 割当コスト – すべての潜在的ブロックポイントでクロージャが生成されます。OCaml では軽量ですが、オーバーヘッドは無視できない場合があります(例:Jun Furuse は自らの Planck パーサで組み込み型ベースシステムより遅いと報告)。

Lwt は

pa_lwt
シンタックス拡張を通じて第 1 の問題に対処しています。これにより、以下のようなキーワードが利用できます。

lwt x = sleep 5 in
print_endline "awake"

lwt
キーワードは自動的に
bind
を挿入します。


フィーバー(Fiber)

代替手段として delimcc があり、これはデリミテッド継続を実装しています。
Lwt と組み合わせることも可能で(例:Jake Donham の Lwt_fiber ライブラリ)、フィーバーは次のように開始します。

val start : (unit -> 'a) -> 'a Lwt.t
val await : 'a Lwt.t -> 'a

実行中にフィーバーは

await
で別スレッドをブロックできます。
再開可能例外がスタックを
start
が呼ばれた位置まで戻し、待機していたスレッドが完了すると再開します。


ベンチマーク

ミクロベンチマークでは Lwt スレッドとフィーバーの性能を比較しています。
フィーバーテスト

module Fiber = struct
  let basic fn yields =
    for i = 1 to 15000 do
      for x = 1 to yields do
        Lwt_fiber.await (fn ())
      done
    done

  let run fn yields =
    Lwt_fiber.start (fun () -> basic fn yields)
end

LWT テスト

module LWT = struct
  let basic fn yields =
    for_lwt i = 1 to 15000 do
      for_lwt x = 1 to yields do
        fn ()
      done
    done

  let run = basic
end

両テストは最初に高速な

Lwt.return ()
を使用します。
ブロッキング関数を次のように置き換えると:

  • slow
    Lwt_unix.sleep 0.0
    (タイムアウト登録)
  • medium
    Lwt.pause ()
    (スケジューラへ投げ込む)

フィーバーは浅い呼び出しスタックでも単なる Lwt より遅くなります。

次のテストでは再帰深度を調べます:

module Fiber = struct
  let recurse fn depth =
    let rec sum n =
      Lwt_fiber.await (fn ());
      match n with
      | 0 -> 0
      | n -> n + sum (n-1)
    in
    for i = 1 to 15000 do ignore (sum depth) done

  let run fn depth =
    Lwt_fiber.start (fun () -> recurse fn depth)
end

同等の LWT バージョンは冗長ですが、ロジックは同じです。

Lwt_unix.sleep 0.0
をブロッキング関数にすると、フィーバー実装は再帰深度が増すにつれて性能が低下しますが、単純な Lwt は線形のままです。


再帰に関するフォローアップ

Jake Donham は、コピー/復元コストを大きなスタックで均等化できればフィーバーが速くなる可能性があると指摘しました。
彼はテストを再実行し、

fn
1 回だけ 長い呼び出しスタックの終端で呼ばれるように変更しました:

module Fiber = struct
  let recurse fn depth =
    let rec sum n =
      match n with
      | 0 -> Lwt_fiber.await (fn ()) ; 0
      | n -> n + sum (n-1)
    in
    for i = 1 to 15000 do ignore (sum depth) done

  let run fn depth =
    Lwt_fiber.start (fun () -> recurse fn depth)
end

このシナリオではフィーバーが速くなります。
違いは、単純な LWT バージョンの各再帰呼び出しでクロージャ(

Lwt.bind
)が割り当てられる一方、delimcc バージョンは最終的な yield まで通常の再帰を行うためです。


結論

  • MirageOS のワークロードに対しては Lwt とフィーバー間の性能差はほぼ無視できるレベルです。
  • 相互運用性 がより重要です:
    • Lwt コードは
      js_of_ocaml
      を通じて JavaScript 上でそのまま動作します。
    • Delimcc コードは既存の同期コードを移行する際に役立ちます。
  • 将来的には、JavaScript の yield 演算子が導入されれば、
    shift
    /
    reset
    と同等の表現力を持つため、両者の収束も可能です。

つまり、性能だけでなく統合と移植性に最適なスレッドモデルを選択することが推奨されます。

同じ日のほかのニュース

一覧に戻る →

2026/02/07 6:51

**OpenCiv3:サイクリズム・III のオープンソースでクロスプラットフォーム化した再構築**

## Japanese Translation: OpenCiv3は、Civilization IIIのオープンソースでクロスプラットフォームなリメイクであり、レガシー制限を取り除き、モッドサポートを拡張しつつもコアゲームプレイを保持します。Godot EngineとC#で構築されており、Windows、Linux、macOS上でネイティブに動作し、専用のCivilization IIIファイルは不要です(ただしローカルコピーがあると互換性が向上します)。 現在のプレアルファ版(v0.3「Dutch」、2025年12月)は、OS固有のzipまたはtgz(「スタンドアロンモード」でプレースホルダーグラフィック付き)として配布されます。インストール手順は以下の通りです。 - **Windows** – zipを解凍し、`OpenCiv3.exe` をダブルクリックします。ブロックされている場合は解除し、自動検出できない場合は環境変数 `CIV3_HOME` にCivilization IIIフォルダーのパスを設定してください。 - **Linux** – `.tgz` を解凍し、`export CIV3_HOME="/path/to/civ3"` としてから `OpenCiv3.x86_64` を実行します。 - **macOS** – zipを解凍し、`xattr -cr /path/to/OpenCiv3.app` でクォータリゼーションを解除し、同様に `CIV3_HOME` を設定してターミナルから起動します。 既知の問題としてはプレースホルダー資産、不完全なBIQ/SAVファイルサポート(クラッシュを引き起こす可能性があります)、および新規ゲーム開始時にマップ生成用保存ファイルが欠如しているためmacOSでクラッシュするケースがあります。最低ハードウェア要件はまだ公開されていません。プロジェクトはMITライセンスの下でリリースされ、Firaxis、CivFanatics.com、その他の団体とは独立しています。 開発者はBIQ/SAVサポートの完全復元、プラットフォーム別クラッシュ(特にmacOS)の修正、後半ゲームコンテンツの追加、およびグラフィックと安定性の向上に積極的に取り組んでいます。バグや機能要望はGitHubで追跡されており、コミュニティからの貢献が奨励されています。 モッドフレンドリーでクロスプラットフォームな基盤を提供することで、OpenCiv3はプレイヤーと開発者にオリジナルIPを侵害せずにクラシックなCivilization体験を拡張する機会を提供します。

2026/02/07 1:20

Waymoワールドモデル

## Japanese Translation: > **Waymoは、Waymo World Modelという生成シミュレーションエンジンを公開しました。このエンジンは、極端な天候・自然災害・象やロングホーンのような珍しいオブジェクト、逆走トラックなど安全に関わるインシデントを含むハイパーリアリスティックな自律運転シナリオを生成します。** > Google DeepMind の Genie 3 をベースにしたこのモデルは、カメラと LiDAR データを融合し、ドライビングアクション制御・シーンレイアウト制御・時間帯、天候、カスタムシナリオを調整する言語プロンプトという3つの制御機構を提供します。録画済みまたは新規生成されたルートに対して代替ドライビング決定を評価する「what‑if」反実仮想シミュレーションもサポートしています。 > Waymo Driver は米国都市で約 2 億マイルの完全自律走行距離を記録し、数十億マイルに相当するバーチャル走行をシミュレートしてきました。World Model はリアルなダッシュカムやモバイルカメラ映像を多模態シミュレーションへ変換し、正確な視覚シーンと一致させることでこの機能を拡張します。効率的なバリアントは実時間の最大4倍速で動作し、計算資源を削減しつつ長時間テストが可能です。 > このシステムは、安全性が証明された自律運転を実現するために Waymo の AI エコシステムの重要柱となっており、Waymo と Google DeepMind からなる大規模チームによって開発されています。

2026/02/05 20:19

**ジオジョインをH3インデックスで400 倍高速化した手法** - **問題点:** 大規模な空間データセットに対する従来のジオジョインクエリは、ポイント‐イン‐ポリゴン判定やテーブル全体のスキャンが必要だったため遅延が大きかった。 - **解決策:** Uber の H3 ヘキサゴナル階層インデックスシステムを利用し、空間情報を固定サイズセルへ事前集約した。 - **実装手順:** 1. すべてのジオメトリ(点・線・多角形)を適切な解像度で対応する H3 インデックスに変換する。 2. 生成されたインデックスを別テーブルに格納し、H3 キーで索引付けする。 3. ジョイン時には、重複した H3 インデックスをキーとしてマッチさせ、膨大な空間判定処理を回避する。 - **結果:** クエリ遅延が数時間から数分へと短縮され、約 400 倍の高速化を実現。また、選択した解像度内であれば空間的正確性は維持された。 ジオメトリ比較を単純な整数キー検索に置き換えることで、データの忠実度を損なうことなく大幅なパフォーマンス向上を達成しました。

## Japanese Translation: ## Summary この記事は、コストの高い空間述語をH3ベースの集合演算に置き換えることで、遅い二次元空間結合をコンパクトなキーで高速ハッシュ結合へと変換する方法を示しています。各ジオメトリを解像度 3 の少数の H3 セルで覆うことにより、結合は最初にセルを共有する候補ペアをフィルタリングし、その後で正確な `ST_Intersects` をその候補のみに適用します。これにより、潜在的に何百万もの交差チェックが、フィルタ済みセットだけに減少し、テストで 400 倍の速度向上を実現しています。この手法は CTE、ビュー、およびサブクエリとシームレスに機能し、追加のマテリアライズドテーブルやスキーマ変更は不要です。したがって、精度を下げるなどの実験も容易になります。高い H3 解像度では偽陽性が減少しますが、形状ごとのセル数が増加し、低解像度ではインデックス作成が簡単ですが、解像度 4 を超えるとセル数の増加により急激に大きくなります。実際には、この書き換えにより 15 ワーカーの Xeon クラスターで結合時間を約 459 秒から約 1.2 秒へ短縮し、正確な一致精度(最終的な `ST_Intersects` によって偽陽性が除去される)を維持したまま高速な空間分析を可能にしています。

**OCaml でのスレッド制御:Delimited Continuations と Lwt の比較** - **Delimited Continuations(境界付き継続)** - 軽量に制御フローを扱える手段。計算を任意の箇所で一時停止・再開したい場合、スレッド全体を生成するオーバーヘッドなしで実装できる。 - **Lwt(Lightweight Threads)** - コオペラティブスレッド用の標準ライブラリ。成熟度が高く、ドキュメントも充実しており、多くの OCaml プロジェクトと自然に統合できる。 --- ## Delimited Continuations を使うケース | 条件 | 理由 | |------|------| | **細粒度な非同期制御** | 生成器(generator)やコルーチンを実装する際、計算を任意のポイントで停止させたいが、スレッドのオーバーヘッドは避けたい場合。 | | **可合成効果(Composable Effects)** | 独自の効果ハンドラを構築し、状態管理や例外処理など他の抽象と組み合わせて使いたい時に便利。 | | **パフォーマンスクリティカルな箇所** | Lwt のプロミスベースモデルではコンテキストスイッチングが発生するため、そのコストを回避したい場合。 | --- ## Lwt が適しているケース | 条件 | 理由 | |------|------| | **標準的なネットワーク I/O** | ソケット、HTTP クライアント/サーバー、ファイル操作など、既に Lwt 用のバインディングが揃っている場合。 | | **大規模コードベース** | 既存のライブラリが `Lwt.t` 型を前提としているとき、継続を導入すると膨大なリファクタリングが必要になる。 | | **コミュニティサポート・ツールチェーン** | デバッグツールや診断機能、豊富なサードパーティ製パッケージが揃っている。 | --- ## 実用的比較 | 特徴 | Delimited Continuations | Lwt | |------|------------------------|-----| | **API 形態** | `unit -> 'a` のコールバックや独自ハンドラ | `('a, 'e) result Lwt.t` のプロミス | | **ボイラープレート** | シンプルな一時停止であれば最小限 | `let%lwt` や `>>=` などチェーンが必要 | | **相互運用性** | 他の非同期ライブラリとの統合は難しい | 多くのライブラリとシームレスに連携 | | **パフォーマンス** | オーバーヘッド低いが複雑さが増すと管理が大変 | やや高めだが予測可能で安定 | --- ## 推奨 - **ドメイン固有言語(DSL)を構築する際**、または「プロミスでは表現しにくい」制御フローが必要な場合は *Delimited Continuations* を採用。 - **一般的なネットワークサービスや I/O 集約型の処理**、あるいはメンテナンス性とコミュニティサポートを重視するプロジェクトでは *Lwt* を選択。 要するに、抽象度に合わせてツールを使い分けることが重要です。 - 低レベルの細かな制御 → **Delimited Continuations** - 高レベルで実運用可能な非同期プログラミング → **Lwt** | そっか~ニュース