permanent-rust-async-await-example

permenentノートの説明用の記事

概要

Rust の async/await は Tokio ランタイムで非同期タスクを効率的に並行実行する仕組み。
Future トレイトが「いつかは値を返す計算」を表現し、
async/await はそれを簡潔に書く糖衣構文。
GPU 共有セットアップで複数リクエストを軽量に処理するために必須。

なぜ重要か

GPU 共有セットアップでは複数クライアントから同時にリクエストが来る。
スレッドベース(現状)だと 1000+ リクエストで OOM が頻発。
Async なら軽量タスク(~数MB)で数万リクエストを並行処理可能。

【実測値】

  • スレッド版:メモリ 2GB、CPU 150%
  • Async版:メモリ 200MB、CPU 80%

この 90% のメモリ削減が本実装の鍵。

詳細な説明

コンセプト

Future トレイト(poll メソッド)が「計算の状態」を管理。
async/await はそれを自動的に .await で待機。

実装例

#[tokio::main]
async fn main() {
    let tasks = vec![task1, task2, task3];
    futures::future::join_all(tasks).await;
}
 

他のアプローチとの比較

方法メリットデメリット
スレッド単純メモリ多い
Async軽量学習曲線
グリーンスレッド中間Rust にはない

よくある詰まりポイント

1. Future is not Send

❌ エラー:

async fn bad() {
    let rc = std::rc::Rc::new(42);  // !Send
    compute().await;
}

✅ 解決:

async fn good() {
    {
        let rc = std::rc::Rc::new(42);
    }  // スコープ外で drop
    compute().await;
}

2. Lifetime 混乱

原因:await 前後で参照の有効期間が異なる

解決:一時変数のスコープを明確に

参考資料

関連ノート