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

Virtual Threadの動作と効果的な使い方

Yuichi.Sakuraba
October 20, 2023
570

Virtual Threadの動作と効果的な使い方

2023.10.20 Javaコミュ@福岡
Java 21リリースイベント@福岡 発表資料

Yuichi.Sakuraba

October 20, 2023
Tweet

Transcript

  1. Performance 応答時間 1 タスクを処理する時間 スループット 単位時間当たりのタスク処理数 応答時間 スループット スループット 応答時間

    → → → → 応答時間重視 : 統計処理、データ解析、機械学習 スループット重視 : アプリケーション、業務システム Web
  2. スループットを向上させるには タスクごとにスレッドを割りつけ Thread per Task/Request Threadの切替 : スレッドのコンテキストスイッチ OS Threadオブジェクト生成:

    重い & メモリ消費大 重い & メモリ消費大 問題点 スレッドが増加すると 応答速度悪化 スループット頭打ち OutOfMemoryEerror
  3. 業務タスクの特徴 Comp. I/O C I/O I/O C C 通信、 DBアクセスなど

    I/O処理が多い I/O処理は計算処理に対して多大な時間を要する I/Oの待ち時間が長い その中でも I/O待ちの間 CPUが遊んでしまう I/O待ちの間に他の処理を行いたい
  4. Solution #1 非同期処理 CompletableFuture Reactive Programming ex. Spring WebFlux Oracle

    Helidon SE 非同期処理を関数で記述 } 処理を非同期実行することで スループット向上 I/O とはいうものの 従来の逐次的な記述と考え方が異なる ... 例外処理が ... デバッグが ...
  5. Virtual Threads Platform Threadとタスクの仲介 Platform Thread タスクからは と区別がつかない Platform Thread

    にマウントして実行 Carrier Thread マウントしたスレッドを と呼ぶ 積極的なコンテキストスイッチ 限定継続を導入してコンテキストスイッチの高速化 Work-Stealingによるスレッドスケジューリング 一貫性のあるスタックトレース Carrier Threadが変わってもスタックトレースが切れない
  6. Platform Thread Platform Thread ...... Virtual Thread Task public int

    read(ByteBuffer buf) throws IOException { ... readLock.lock(); try { ... configureSocketNonBlockingIfVirtualThread(); n = IOUtil.read(fd, buf, -1, nd); if (blocking) { while (IOStatus.okayToRetry(n) && isOpen()) { park(Net.POLLIN); n = IOUtil.read(fd, buf, -1, nd); } } ... sun.nio.ch.SocketChannelImpl 例
  7. void park() { ... boolean yielded = false; setState(PARKING); try

    { yielded = yieldContinuation(); } finally { ... } ... } java.lang.VirtualThread private boolean yieldContinuation() { ... unmount(); try { return Continuation.yield(VTHREAD_SCOPE); } finally { mount(); ... } } 限定継続
  8. VT使う必要なし or CompletableFutureゴリゴリ書ける Spring Boot, Jakarta EE など FWの対応待ち その他

    使ってない or ボトルネックは? データ量 / 計算量 ParallelStream Fork/Join FW Vector API File Memory Map DB 通信 / VirtualThread
  9. スレッドの注意点 Virtual Threads 特に synchronizedをなるべく使わないようにする 1. synchronized = モニタロック リソースへのアクセスを

    1 つのスレッドだけに限定 他のスレッドをブロックする ボトルネックになりやすい Virtual Threadでは Carrier Threadをブロックしてしまう
  10. スレッドの注意点 Virtual Threads 特に synchronized を使わないようにするには イミュータブルクラスの活用 record 型の利用 状態が変化しなければ複数スレッドからもアクセス可

    処理結果の受け渡しがある場合 Callableを使う どうしてもロックが必要であれば synchronizedではなくReentrantLock クラスを使う java.util.concurrent.locksにロッククラスあり 他にも
  11. スレッドの注意点 Virtual Threads 特に ThreadLocal を使わない 2. ThreadLocal はミュータブル &

    ライフタイムが不明確 Virtual Threads ThreadLocalをサポートしているが は スケールしないためボトルネック化 ScopedValueで代用する Java 21 Preview JEP では ただし FWが ThreadLocal を使っている場合 対応してくれるまで待ちましょう
  12. スレッドの注意点 Virtual Threads 特に スレッドを使いまわさない 3. Virtual Threadsは使い捨て ExecutorService スレッドのプールは

    にまかせる タスクを記述することに集中しよう クラスの 4. Thread APIをもう 1 度チェック @Deprecated(forRemoval=true)なメソッド stop, suspend, resumeなど