Docsの目次

並行処理

Nagiの非同期処理はTokio上で動きます。HTTPやタイマーを待っている間に、ほかの処理を進められます。使い方はasyncとscopeから確認してください。

このページの目次

CPU処理のために待ち時間をふさぎたくない

Pythonでも、async defの中で長い同期計算をすると、そのイベントループのほかの処理を遅らせます。asyncio.to_thread(...)などで処理を外へ渡す書き方があります。Nagiでは任意の関数を渡す同等のAPIは未対応です。

SQLiteは専用スレッドで処理します。任意のCPU処理は自動で移されません。次のcpu_sumは、Tokioのblocking workerへ渡す検証用APIです。

async def main() -> Result[unit, Error]:
    result = try await cpu_sum(100000)
    print(result)
    return ok(print("完了"))

上の完全な例は、生成した整数列の合計を表示してから完了を表示します。cpu_sum(100000)の結果は-3184です。

async defに変えれば任意の同期計算も別スレッドへ移る、と考えるのがよくある間違いです。長い処理は分割して待ち合わせの機会を作るか、停止を管理できるRust連携や別プロセスを検討してください。

一言でいうと:待つ処理と、CPUを使い続ける処理は別に扱う。 taskの開始と終了待ちはasyncとscope、長寿命workerの停止はSupervisorにあります。

CPU実行とデータの現行リファレンス

cpu_sumはCPU処理を分けて実行するためのサンプルです。同時に実行するCPU処理は最大4件です。利用者が任意の関数をこの枠へ渡すAPIは未対応です。

データの受け渡し

複数のtaskへ、変更できる値を自動で共有することはありません。所有権を移して渡すか、sharedで共有します。shared自体は読み取り用の参照で、内側の型が持つ独自の可変性をなくすものではありません。spawnへviewは直接渡せません。sharedで包むだけで、どんな値でもthread-safeになるわけではありません。共有handleの複製と中身のコピーも別です。Rust側のSend/Syncの要件は最終的にbuildで検証します。actorのmessage・replyではsharedも未対応です(actorの制約)。

すでに始まったCPU処理は、呼び出し元をキャンセルしただけでは止まりません。長い処理には、その処理自身が停止の要求を確認する仕組みが必要です。

task数とHTTPの接続数は別です。待ち時間やメモリを含む測定結果は、測定結果と通信の負荷試験を参照してください。

Nagi独自のVMやCPU時間でtaskを強制的に切り替える仕組みはありません。yieldしない処理は他のtaskや停止処理を遅らせます。並行実行と共有データの安全性は、Nagiの検査に加えてRustの型検査とTokioの実行規則に依存します。実装は並行処理のruntimeにあります。

Nagi 0.2.0 · Docsこのページのソース