- Rust コミュニティでは、「スレッドは async/await でできることをすべて行え、しかもよりシンプルなのに、なぜ async/await を選ぶのか?」という疑問をよく目にする
- Rust は低レベル言語であり、Coroutine の複雑さを隠さない。これは、プログラマーが非同期を意識しなくてもデフォルトで非同期になる Go のような言語とは対照的な考え方である
- 賢いプログラマーは複雑さを避けようとするが、なぜ
async/await が必要なのか?
背景を知る
- Rust は低レベル言語である。コードは一般に線形的で、ある作業が終わると別の作業が実行される
- Web サーバーのように、同時に多くの作業を実行しなければならない場合、線形コードでは問題が生じる
- 初期の Web は、この問題を解決するためにスレッディングを導入しようとした
- スレッドを使えば複数のクライアントを同時に処理できるが、プログラマーたちは並行性を OS 空間からユーザー空間へ持ち込みたいと考えてきた
タイムアウトの問題
- Rust の最大の利点の 1 つは 合成可能性(composability) である
async/await は、この合成可能性を I/O バウンドな関数にも適用できるようにする
- たとえば、クライアント処理関数にタイムアウトを追加したい場合、2 つのコンビネーターを使って実装できる
テーマ別スレッド
- スレッドを使った例でタイムアウトを実装するのは簡単ではない
TcpStream には set_read_timeout と set_write_timeout 関数があるが、その使い方には制約がある
- Rust のコンビネーターを使ってタイムアウトをプログラミングする方法も示されているが、これは
TcpStream に限られ、追加のシステムコールも必要になる
Async の成功事例
- HTTP エコシステムは、主要なランタイム機構として
async/await を採用している
tower は async/await の強力さを示す例であり、タイムアウト、レート制限、ロードバランシングなどを提供する
macroquad は Rust のゲームエンジンで、async/await を使ってエンジンを実行している
Async のイメージ改善
async の利点は広く知られておらず、一部の人には誤解されることがある
- Rust コミュニティは、
async Rust の性能上の利点を過大評価し、意味のある利点を過小評価する傾向がある
async/await は、同期 Rust では数十のスレッドやチャネルなしには表現できないパターンを簡潔に表現できる、強力なプログラミングモデルとして捉えるべきである
GN⁺ の意見
async/await は並行性を扱う際にコードの複雑さを増す一方で、非常に多くのクライアントを効率的に処理する能力を提供する
- この記事は、
async/await が単なる性能上の利点を超えて、プログラミングモデルとしての強みを持つことを強調している
- Rust の
async/await は、さまざまな I/O 処理に対する合成可能性を提供し、これは特にネットワークサービスや Web サーバーのような分野で有用である
- 批判的な視点で見ると、
async/await の複雑さは初心者開発者にとって参入障壁となり得るため、それを乗り越えるための教育的な取り組みが必要である
- 同様の機能を提供する別のプロジェクトとしては、Node.js の
async/await 実装や Python の asyncio ライブラリがあり、これらも似たパラダイムを提供している
async/await を導入する際には、コードの複雑さと保守性を考慮する必要があるが、同時に多数のクライアントを処理しなければならない場合には、このモデルが大きな利点をもたらす
1件のコメント
Hacker Newsの意見
async/await とシングルスレッド
async/await 対スレッド
記事に対する問題点
触れられていない点
キャンセルに関する重要な点
async/await に対するマーケティングのようなキャンペーン
async/await 対ファイバー
Rust における async/await の主な利点
async/await に関する誤解
async/await をスレッドより選ぶ理由