Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java Virtual Threads, Kotlin Coroutines, Go Gor...

Java Virtual Threads, Kotlin Coroutines, Go Goroutinesの比較

2025年11月15日に実施されたJJUG CCC 2025 Fallでの登壇資料です

More Decks by LINEヤフーTech (LY Corporation Tech)

Other Decks in Technology

Transcript

  1. 1 © LY Corporation 和⽥ 隆道 Wada Takamichi LINEヤフー株式会社 コマースドメイン

    ソーシャルコマースSBU サービス開発ユニット #LINEギフト #ショッピングタブ #サーバーサイドエンジニア #新卒3年⽬ 前回のJJUGでも発表しました Java, Go, Rustのメモリ管理⼿法の⽐較
  2. @wadayamada 伝えたいこと © LY Corporation 2 1リクエスト1OSスレッド⽅式はOSスレッド数がボトルネックになる(C10K問題) この問題はノンブロッキングI/O+⾮同期処理を⾏える以下の技術により解決できる これらの技術は利⽤する開発者の意識すべき範囲がそれぞれ異なる #

    ノンブロッキングI/O ⾮同期処理 イベントループ 意識する 意識する Coroutine (Kotlin Coroutines) 意識する 意識しない 軽量スレッド (Java Virtual Threads, Go Goroutines) 意識しない 意識しない
  3. Todayʼs Agenda 3 © LY Corporation 1. 1リクエスト1OSスレッドの課題と解決 2. イベントループ

    3. Coroutine(Kotlin Coroutines) 4. 軽量スレッド(Java Virtual Threads, Go Goroutines)
  4. @wadayamada リクエストを捌くための並⾏処理 © LY Corporation 4 CPU、メモリなどのリソースを効率的に使って多数のリクエストを捌くために 並⾏処理の技術が発展してきた サーバー CPU

    メモリ l 1リクエスト1プロセス l 1リクエスト1OSスレッド l 多リクエスト1OSスレッド(イベントループ・Coroutine・軽量スレッド)
  5. @wadayamada 1リクエスト1OSスレッド © LY Corporation 5 Apache Tomcatで使われている⽅式 サーバー OS

    スレッド OS スレッド OS スレッド リクエスト リクエスト リクエスト CPUコア CPUで実⾏ ブロッキングI/O
  6. @wadayamada 1リクエスト1OSスレッド © LY Corporation 8 CPUコア CPUが参照するスタックを切り替えることで実⾏するリクエストを切り替える この制御はOSが⾏なっている スタック

    ポインタ 切り替え ✳実際にはスタック以外にプログラムカウンタなどの レジスタ情報も切り替える OSスレッド スタック getFromDBBlocking handle OSスレッド スタック getFromDBBlocking handle リクエスト リクエスト
  7. @wadayamada サーバー 1リクエスト1OSスレッドの課題 © LY Corporation 9 リソース的にOSスレッド数には上限がある これがボトルネックとなり、同時に捌けるリクエスト数が少なくなることがある (C10K問題)

    OS スレッド OS スレッド OS スレッド リクエスト リクエスト リクエスト リクエスト ❌ 使えるOSスレッドがない CPUコア CPUは余裕ある😭 ブロッキングI/O
  8. @wadayamada 1リクエスト1OSスレッドの課題の解決 © LY Corporation 10 サーバー CPUコア OS スレッド

    イベントループ、Coroutine、軽量スレッドを使うことで 少数のOSスレッドで多数のリクエストを捌くことができる 軽量 スレッド 軽量 スレッド 軽量 スレッド スケジューリング リクエスト リクエスト リクエスト 軽量スレッドでリクエストを捌く例
  9. @wadayamada 1リクエスト1OSスレッドの課題と解決: まとめ © LY Corporation 11 l Apache Tomcatなどでは1リクエストを1OSスレッドで処理している

    l この⽅式はブロッキングI/Oと同期処理でリクエストを捌くが、OSスレッド数がボト ルネックになってしまうことがある(C10K問題) l イベントループ、Coroutine、軽量スレッドを使うことで、これが解決できる イベントループ、Coroutine、軽量スレッドを使うことで 少数のOSスレッドで多数のリクエストを捌くことができる
  10. Todayʼs Agenda 12 © LY Corporation 1. 1リクエスト1OSスレッドの課題と解決 2. イベントループ

    3. Coroutine(Kotlin Coroutines) 4. 軽量スレッド(Java Virtual Threads, Go Goroutines)
  11. @wadayamada イベントループ © LY Corporation 13 1つのOSスレッドでイベントループを回して、リクエストを捌く サーバー OS スレッド

    リクエスト リクエスト リクエスト CPUコア CPUで実⾏ イベント ループ ノンブロッキングI/O
  12. @wadayamada イベントループ: まとめ © LY Corporation 16 l クライアントからのリクエストやDBへのI/O完了は全てイベントとして通知される l

    イベントを捌き続けることで多数のリクエストを1つのOSスレッドで捌ける l 1つのOSスレッドで処理し続けるので、ノンブロッキングI/Oを使う必要があり、後続 の処理はI/O完了時に⾮同期に実⾏する 1つのOSスレッドでイベントループを回して、リクエストを捌く
  13. Todayʼs Agenda 17 © LY Corporation 1. 1リクエスト1OSスレッドの課題と解決 2. イベントループ

    3. Coroutine(Kotlin Coroutines) 4. 軽量スレッド(Java Virtual Threads, Go Goroutines)
  14. @wadayamada Coroutine(Kotlin Coroutines): まとめ © LY Corporation 21 l リクエストはイベントループで捌く

    l イベントループなので、ノンブロッキングI/Oを使う必要がある l コンパイル時に継続オブジェクト(Continuation)で実⾏状態を保持する実装に変換 (CPS変換)することで同期的に書いた処理が⾮同期に実⾏できるようになる CPS変換により、⾮同期処理を同期的に書くことができる
  15. Todayʼs Agenda 22 © LY Corporation 1. 1リクエスト1OSスレッドの課題と解決 2. イベントループ

    3. Coroutine(Kotlin Coroutines) 4. 軽量スレッド(Java Virtual Threads, Go Goroutines)
  16. @wadayamada 軽量スレッド(Java Virtual Threads, Go Goroutines) © LY Corporation 23

    プロセス CPUコア OS スレッド OSスレッドを共有して1リクエストを1軽量スレッドで処理する 少数のOSスレッドでリクエストを捌ける 軽量 スレッド 軽量 スレッド 軽量 スレッド スケジューリング リクエスト リクエスト リクエスト
  17. @wadayamada 軽量スレッド(Java Virtual Threads, Go Goroutines) © LY Corporation 24

    Java Virtual Thread(VT)はブロッキングI/Oかつ同期的に書ける JVMがノンブロッキングI/O+⾮同期処理に変換して実⾏する
  18. @wadayamada Java Virtual Thread 軽量スレッド(Java Virtual Threads, Go Goroutines) ©

    LY Corporation 25 CPUコア OS スレッド JVM VTがブロッキングI/OしようとするとJVMが検知してノンブロッキングI/Oに書き換える 開発者はI/Oがブロッキングかどうかを意識する必要はない I/O⽤ OS スレッド 4. ノンブロッキングI/O Java Virtual Thread Virtual Thread Virtual Thread Java Server 1. ブロッキングI/Oしたい︕ 2. 検知 3. VTを⼀時停⽌する I/O多重化
  19. @wadayamada 軽量スレッド(Java Virtual Threads, Go Goroutines) © LY Corporation 26

    VTの実⾏状態はVTのスタックで保持する ここまで 実⾏中 Virtual Thread スタック getFromDB Blocking handle
  20. @wadayamada 軽量スレッド(Java Virtual Threads, Go Goroutines) © LY Corporation 27

    CPUコア OSスレッド I/Oが完了したら、VTのスタックをOSスレッドのスタックに復元することで VTの実⾏を再開する スタック ポインタ スタック 3. 参照して実⾏ 2. 復元 1. 実⾏を再開したい︕ ✳実際にはスタック以外にプログラムカウンタなどの レジスタ情報も必要 Virtual Thread スタック getFromDB Blocking handle
  21. @wadayamada 軽量スレッド(Java Virtual Threads, Go Goroutines) © LY Corporation 28

    GoroutineもブロッキングI/Oかつ同期的に書ける Java VTと同じく、ランタイムがノンブロッキングI/O+⾮同期処理に変換して実⾏する
  22. @wadayamada 軽量スレッド(Java Virtual Threads, Go Goroutines) © LY Corporation 30

    I/Oが完了したら、GoroutineのスタックをCPUが直接参照することで、 Goroutineの実⾏を再開する CPUコア OSスレッド スタック ポインタ スタック 2. 参照して実⾏ 1. 実⾏を再開したい︕ ✳実際にはスタック以外にプログラムカウンタなどの レジスタ情報も必要 Goroutine スタック getFromDB Blocking handle
  23. @wadayamada 軽量スレッド(Java Virtual Threads, Go Goroutines): まとめ © LY Corporation

    31 l 軽量スレッドの実⾏状態は軽量スレッドのスタックで保持している l 軽量スレッドがブロッキングI/Oしようとするとランタイムが検知してノンブロッキン グI/Oに書き換えてI/Oを⾏い、軽量スレッドを⼀時停⽌する l I/Oが完了したら、軽量スレッドのスタックをOSスレッドのスタックに復元すること で実⾏を再開する ランタイムがI/Oと軽量スレッドの実⾏を管理してくれる
  24. @wadayamada まとめ © LY Corporation 32 1リクエスト1OSスレッド⽅式はOSスレッド数がボトルネックになる(C10K問題) この問題はノンブロッキングI/O+⾮同期処理を⾏える以下の技術により解決できる これらの技術は利⽤する開発者の意識すべき範囲がそれぞれ異なる #

    ノンブロッキングI/O ⾮同期処理 イベントループ 意識する 意識する Coroutine (Kotlin Coroutines) 意識する 意識しない 軽量スレッド (Java Virtual Threads, Go Goroutines) 意識しない 意識しない
  25. @wadayamada 参考⽂献 © LY Corporation 33 1. JEP 444: Virtual

    Threads 2. Project Loom Fibers and Continuations – OpenJDK WIKI 3. Virtual Threads - 導⼊の背景と、効果的な使い⽅ - 4. src/runtime/HACKING – Go 5. Go Networking Internals - Go Optimization Guide 6. 内部実装から理解するKotlin Coroutines︓suspend関数・Continuation編 7. suspendCancellableCoroutine – Kotlin 8. Webサーバーアーキテクチャ進化論2023