Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
作ってわかる!非同期ランタイム
Search
Tech Leverages
March 04, 2025
0
88
作ってわかる!非同期ランタイム
Tech Leverages
March 04, 2025
Tweet
Share
More Decks by Tech Leverages
See All by Tech Leverages
ディメンショナルモデリングを軽く語る
leveragestech
0
94
アクターモデルによる効率的な分散システム設計
leveragestech
0
87
Terraform による運用効率化の取り組みと最新のテストアプローチの紹介
leveragestech
0
89
OpenFGAで拓く次世代認可基盤 〜予告編〜
leveragestech
0
87
リソース・管理効率の向上だけでない、分散システムとしてのTiDBの魅力
leveragestech
0
88
レバテック開発部 技術広報 これまでとこれから
leveragestech
0
87
改めて「型」について考えてみよう
leveragestech
1
58
苦しいTiDBへの移行を乗り越えて快適な運用を目指す
leveragestech
0
1.1k
Biome で Format と Lint のストレスをゼロに
leveragestech
0
59
Featured
See All Featured
Navigating Team Friction
lara
183
15k
Optimizing for Happiness
mojombo
376
70k
Become a Pro
speakerdeck
PRO
26
5.2k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
4 Signs Your Business is Dying
shpigford
182
22k
Faster Mobile Websites
deanohume
306
31k
Building an army of robots
kneath
303
45k
Building a Scalable Design System with Sketch
lauravandoore
461
33k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.3k
How GitHub (no longer) Works
holman
314
140k
Keith and Marios Guide to Fast Websites
keithpitt
411
22k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.5k
Transcript
作って分かる!非同期処理ランタイム Leverages TechFes 2025 Winter
None
今日話すこと • 非同期処理とはなにか • 非同期処理ランタイムについて • 非同期処理ランタイムをつくってみ た
非同期処理とはなにか?
処理が終わるまで 待たずに他の処理を実 行すること
task_1 task_2 task_1 task_2 task_1 task_2 同期処理 task_2はtask_1が終わって から処理を開始する 非同期処理
(並行)
なぜ非同期処理が必要なのか?
時間がかかる処理を 待っている間を 有効活用するため
task_1 task_2 task_3 task_1 task_2 task_3 同期処理
task_1 task_2 task_3 task_1 task_2 task_3 非同期処理
task_1 task_2 task_3 task_1 task_2 task_3 task_1 task_2 task_3 task_1
task_2 task_3 同期処理 非同期処理
時間がかかる処理とは?
https://i.gzn.jp/img/2017/07/07/intel-core-i9-7900x/00.jpg,(参照2025-02-05)
CPU Intel Core i9 • 動作周波数:2.3 ~ 6.0GHz https://i.gzn.jp/img/2017/07/07/intel-core-i9-7900x/00.jpg,(参照2025-02-05)
CPU Intel Core i9 • 動作周波数:2.3 ~ 6.0GHz → 1秒間に23億回
~ 60億回の計算が 可能 https://i.gzn.jp/img/2017/07/07/intel-core-i9-7900x/00.jpg,(参照2025-02-05)
CPU Intel Core i9 • 動作周波数:2.3 ~ 6.0GHz → 1秒間に23億回
~ 60億回の計算が 可能 → CPUが一回の計算にかかる時間は 0.2 ~ 0.5ナノ秒 https://i.gzn.jp/img/2017/07/07/intel-core-i9-7900x/00.jpg,(参照2025-02-05)
CPUとコンポーネント間の通信にかかる時間 レジスタ :0.2 ~ 0.5 ナノ秒 RAM :80 ~ ナノ秒
SSD (SATA3.0) :100 ~ マイクロ秒 HDD (SATA3.0) :10 ~ ミリ秒 ネットワーク :10 ~ 100 ミリ秒 図:Socket AM3+マザーボードの進化系、GIGABYTE「GA~990FXA-UD5 R5」徹底検証 https://www.gdm.or.jp/review/2015/0515/114349/2,(参照2025-02-05)
CPUとコンポーネント間の通信にかかるクロック数 レジスタ :1 クロック RAM :400~ クロック SSD (SATA3.0) :50,000~
クロック HDD (SATA3.0) :5,000,000~ クロック ネットワーク :5,000,000~ クロック 図:Socket AM3+マザーボードの進化系、GIGABYTE「GA~990FXA-UD5 R5」徹底検証 https://www.gdm.or.jp/review/2015/0515/114349/2,(参照2025-02-05)
CPUとコンポーネント間の通信にかかるクロック数 CPUがHDDにアクセスしてデータを得るまでに一 千万回計算ができる! レジスタ :1 クロック RAM :400~ クロック SSD
(SATA3.0) :50,000~ クロック HDD (SATA3.0) :5,000,000~ クロック ネットワーク :5,000,000~ クロック 図:Socket AM3+マザーボードの進化系、GIGABYTE「GA~990FXA-UD5 R5」徹底検証 https://www.gdm.or.jp/review/2015/0515/114349/2,(参照2025-02-05)
I/O待ち中のプロセス I/O発生 I/O 結果返る
• プロセスがディスクやネットワーク に対してI/Oを行うとそのプロセス を実行待機状態にして他の実行 可能なプロセスを動かす とはいえOSも馬鹿じゃ ない I/O 発生 I/O
結果返る 現代のOSは こっち
• プロセスがディスクやネットワーク に対してI/Oを行うとそのプロセス を実行待機状態にして他の実行 可能なプロセスを動かす • プロセスを切り替えるときに切り替 えるためのオーバーヘッド(スイッ チングコスト )が生じるのでシング
ルプロセスと比べて時間がかかる とはいえOSも馬鹿じゃ ない ただし… I/O 発生 I/O 結果返る スイッチングコスト
• I/Oは発生しないが時間のかかる 処理が存在する • 時間計算量の大きい計算が該当 する CPU bound…?
CPU bound…? 別スレッドで 非同期に処理をする • I/Oは発生しないが時間のかかる 処理が存在する • 時間計算量の大きい計算が該当 する
時間がかかる処理は CPU boundな処理と I/O boundな処理の 2つがある
CPU bound • CPUの処理速度によって律速され る • プロセスレベルで最適化するために は並列処理が有効 • 特定のワークロードに最適化された
専用ハードウェアを使うことで最適 化が可能(ネットワーク、グラフィッ ク、暗号化) I/O bound • ディスクのIOPS、レイテンシによっ て律速される • プロセスレベルで最適化するために は並行処理が有効 • HDD→SSDにするなどしてスルー プットやレイテンシを向上させること で最適化が可能
CPU bound • 文字列処理(正規表現など) • 全文検索 • 暗号化 • ハッシュ化
• 圧縮・解凍処理 • 画像処理 • 動画エンコード I/O bound • ファイルの読み取り・書き出し • APIへのリクエスト • メモリスワップ 基本的なWebアプリケーションはほとんど I/Oが問 題になる(テーブルフルスキャン , N + 1問題, 外部 API連携, …etc)
これらの処理で CPUを効率よく扱うた めに生まれたのが非同 期処理
非同期処理ランタイムについて
非同期処理を ユーザー空間レベルで 実現するための機構が 非同期処理ランタイム
言語機能として組み込み • JavaScript(Promise) • Java(CompletableFuture) • Kotlin(Coroutines) • Scala(Future) •
Go(Goルーチン) • C#(Task) • Erlang ライブラリとして提供 • Rust(tokio) • C言語 • PHP(ReactPHP) • Python(asyncio)
非同期処理ランタイムを 構成しているもの
非同期処理ランタイムを構成しているもの • Executor • Scheduler • (Reactor) • Task
非同期処理ランタイムを構成しているもの • Executor • Scheduler • (Reactor) • Task TaskをSchedulerから受け
取って実際に処理を行う 実装によっては他の ExecutorからTaskを奪うこと もある(stealing)
非同期処理ランタイムを構成しているもの • Executor • Scheduler • (Reactor) • Task Taskを受け取っていつ、どれ
くらい実行するのかを決めて Executorに実行させる
非同期処理ランタイムを構成しているもの • Executor • Scheduler • (Reactor) • Task 非同期なIOにおいて結果が
返ったときにTaskを実行可能 状態に変える
非同期処理ランタイムを構成しているもの • Executor • Scheduler • (Reactor) • Task 処理の実行状態を管理する
オブジェクト 一般にコルーチンを用いて実 装される
非同期処理ランタイムの構成例 Executor Executor Executor Scheduler 実行キュー Task Task Task Task
Task ランタイム I/Oキュー Task Reactor
非同期処理ランタイムの構成例 Executor Executor Executor Scheduler 実行キュー Task Task Task Task
Task ランタイム I/Oキュー Task Reactor Executorは処理をある程度 進めると実行キューに戻す
非同期処理ランタイムの構成例 Executor Executor Executor Scheduler 実行キュー Task Task Task Task
Task ランタイム I/Oキュー Task Reactor Executorは処理をある程度 進めると実行キューに戻す 処理は実行・中断・再開が 可能でないといけない
こんな非同期処理があったとき...
こんな非同期処理があったとき... 時間のかかる処理 (ネットワーク IO)
こんな非同期処理があったとき... 時間のかかる処理 (ネットワーク IO) ここまで到達したら一 時中断する
こんな非同期処理があったとき... 時間のかかる処理 (ネットワーク IO) ここまで到達したら一 時中断する レスポンスが 届いたら再開する
こんな非同期処理があったとき... 時間のかかる処理 (ネットワーク IO) ここまで到達したら一 時中断する レスポンスが 届いたら再開する こっちも同じ
タスクA,B,Cを A 1 →B 1 →C 1 →A 2 →…と進
めることで非同期処理が 可能になる
JavaScriptだとawaitは プログラマがランタイムに 中断ポイントを 明示する構文
Goはawaitがなくランタイムが 強制的に割り込んで処理の中断・再 開を行う →プログラマに非同期を極力意識さ せない言語設計になっている
None
None
実際にJavaScriptで実装してみよう!
今回作るもの • Executor • Scheduler • (Reactor) • Task シングルスレッドで実行する
のでExecutorは必要ない 非同期I/Oはサポートしない 非同期処理の状態を管理す るTaskとTaskを実行する Schedulerのみを実装する
Scheduler + Executor 実行キュー 実装する非同期処理ランタイムの構成 Task Task ランタイム
https://github.com/nonaka-shu-lvgs/async-runtime
Runtime = Executor + Scheduler spawnされるとタスクを 実行キューに積む
JSで中断可能な関数(コルーチン)→ ジェネレータ Runtimeから処理を進めるように 指示がされるとコルーチンを進める コルーチンを進めた結果、 それが終了したら完了状態にする
None
None
None
None
出力結果が同じに なった!
さらなる高みへ • 非同期処理ランタイムを実現するために今回はコルーチンを用いたがこの方式を 協調的マルチタスキングという ◦ 協調的マルチタスキングは非協調的マルチタスキングと比べて実装が容易というメリットがある反 面、あるタスクが無限ループに陥ると処理系全体が機能不全に陥るというデメリットがある ◦ 協調的マルチタスク方式を採用している言語は JavaScript,
Python, Ruby, Rustなどがある • 非同期タスクが自発的に他のタスクに譲らず、処理系から割り込む方式を非協調 的マルチタスキングという ◦ 実装が複雑になる反面、無限ループに陥ったタスクを処理系が強制終了させることができる ◦ OSはこっち
さらなる高みへ ー 最適化への道 • V8エンジンの制約によりNode.jsでは不可能だったが、複数Executorによる並列処 理を実装することで更にスループットが向上する ◦ Rust(tokio)はイベント駆動 × マルチ軽量スレッド
◦ Goは同期IO × マルチ軽量スレッド ◦ Node.jsはイベント駆動 × シングルスレッド • 今回は非同期I/Oを実装しなかったが、I/Oをポーリングするのではなくイベント駆動 にすることで計算負荷が低減する
Thank you for listening!