Rust非同期処理入門|tokio・async/awaitの実務パターン
Rustで高性能なネットワークサーバーやCLIツールを構築する際、非同期処理は避けて通れません。async/awaitの構文自体はJavaScriptやPythonと似ていますが、Rustの非同期モデルには「ランタイムが言語に組み込まれていない」「Futureはポーリングされるまで何もしない」という独自の特徴があります。 Goのgoroutineはランタイムが暗黙的にスケジューリングし、Node.jsはシングルスレッドのイベントループで非同期処理を実行します。一方Rustは、どのランタイムを使うか、何スレッドで動かすかを開発者が明示的に選択します。この設計によりゼロコスト抽象化が実現されています。 本記事では、Futureトレイトとasync/await構文の基礎から、事実上の標準ランタイムであるtokioの実務パターンまでを段階的に解説します。 async/awaitの基本 Futureトレイトの仕組み Rustの非同期処理は Future トレイトを基盤としています。Future は「まだ完了していないかもしれない計算」を表す型です。 pub trait Future { type Output; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; } poll が Ready(T) を返せば計算完了、Pending を返せばまだ完了していないことを意味します。ランタイムは Pending を受け取ると、Wakerで通知されるまでポーリングを中断します。 async fnと.await async fn は Future を返す関数のシンタックスシュガーです。.await はFutureの完了を待つ演算子で、Ready になるまで現在のタスクの実行権を他のタスクに譲ります。 async fn fetch_data(url: &str) -> String { let response = reqwest::get(url).await.unwrap(); response.text().await.unwrap() } 他言語との比較 項目 Rust (tokio) Go (goroutine) Node.js Python (asyncio) 非同期モデル ポーリング型Future CSPベースのグリーンスレッド イベントループ コルーチン ランタイム 外部クレート(tokio等) 言語組み込み V8組み込み 標準ライブラリ スレッドモデル マルチスレッド対応 M:Nスケジューリング シングルスレッド シングルスレッド ゼロコスト抽象化 あり なし なし なし メモリ管理 所有権システム GC GC GC async fn はコンパイル時にステートマシンに変換され、ヒープアロケーションやランタイムの余分なオーバーヘッドが発生しません。これがゼロコストと呼ばれる理由です。 ...