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

Javaで最強 コンカレントプログラミング/concurrent-programming-in-java

Javaで最強 コンカレントプログラミング/concurrent-programming-in-java

OCHaCafe Season 6 #6 で使用した資料です。

oracle4engineer
PRO

February 09, 2023
Tweet

More Decks by oracle4engineer

Other Decks in Technology

Transcript

  1. Javaで最強!
    コンカレントプログラミング
    Oracle Cloud Hangout Café – Season 6 #6
    Shuhei Kawamura
    Cloud Solution Engineer
    Solutions Architect, Oracle Corporation Japan
    February 8, 2022

    View Slide

  2. Copyright © 2023, Oracle and/or its affiliates
    2
    • 所属
    • 日本オラクル株式会社
    • ソリューション・アーキテクト本部
    • 担当領域
    • Cloud Native, App Dev
    • Data Platform(Spark 周り)
    • AI Services
    • Search Service with OpenSearch
    • (趣味) 認証・認可関連
    • コミュニティ
    • OCHaCafe
    • CloudNative Days – Observability
    川村 修平 (Shuhei Kawamura)
    @shukawam
    Twitter/GitHub/Qiita

    View Slide

  3. Copyright © 2023, Oracle and/or its affiliates
    3
    Agenda
    1. Warming up
    2. Virtual Threads Overview
    3. Helidon & Helidon Níma

    View Slide

  4. Copyright © 2023, Oracle and/or its affiliates
    4
    Warming Up

    View Slide

  5. Copyright © 2023, Oracle and/or its affiliates
    5
    java.lang.Thread を継承して、run() メソッドをオーバーライドする
    実行は、Thread.start() で行う
    Java でスレッドを扱う方法アレコレ 1/3
    java.lang.Thread, java.lang.Runnable
    public class SimpleThread extends Thread {
    @Override
    public void run() {
    System.out.println(String.format("[%s]: %s", Thread.currentThread().getName(), "Hello world!"));
    }
    }
    SimpleThread thread = new SimpleThread();
    thread.start();

    View Slide

  6. Copyright © 2023, Oracle and/or its affiliates
    6
    java.lang.Thread のコンストラクタに java.lang.Runnable インターフェースの実装を渡す
    もちろん、ラムダ式でもOK
    Java でスレッドを扱う方法アレコレ 2/3
    java.lang.Thread, java.lang.Runnable
    public class SimpleRunnable implements Runnable {
    @Override
    public void run() {
    System.out.println(String.format("[%s]: %s", Thread.currentThread().getName(), "Hello world!"));
    }
    }
    public static void main(String[] args) {
    System.out.println(String.format("[%s]: %s", Thread.currentThread().getName(), "Hello world!"));
    Thread thread = new Thread(() -> {
    System.out.println(String.format("[%s]: %s", Thread.currentThread().getName(), "Hello world!"));
    });
    thread.start();
    }
    Thread thread = new Thread(new SimpleRunnable());
    thread.start();

    View Slide

  7. Copyright © 2023, Oracle and/or its affiliates
    7
    • Concurrency Utilities: 並行処理でよく使われるユーティリティ・パッケージ
    • スレッドプール(※後述)によるスレッド管理や Callable/Future などの非同期処理の結果を取得する仕組み等を提供
    • java.lang.Thread をそのまま用いるよりも安全かつ抽象度の高い実装が可能となるので、通常はこちらを使う
    Java でスレッドを扱う方法アレコレ 3/3
    java.util.concurrent.*
    ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
    Future result = singleThreadPool.submit(new SimpleCallableTask());
    System.out.println(result.get());
    singleThreadPool.shutdown();
    if (!singleThreadPool.awaitTermination(1, TimeUnit.SECONDS)) {
    singleThreadPool.shutdownNow();
    }
    public class SomeCallableTask implements Callable {
    @Override
    public String call() throws Exception {
    return "Hello world!";
    }
    }

    View Slide

  8. Copyright © 2023, Oracle and/or its affiliates
    8
    複数のスレッドをあらかじめ作成して待機させておく
    タスクが来たら待っているスレッドにタスクを割り当てて処理を開始させる
    実行させるスレッドに空きがない場合は、タスクをキューに入れてスレッドに空きができるまで待つ
    java.util.concurrent.ExecutorService というインターフェースを持った様々なスレッドプールの仕組みを提供している
    • AbstractExecutorService, ForkJoinPool, ScheduledThreadPoolExecutor, ThreadPoolExecutor
    通常は Executors というユーティリティクラスを使って ExecutorService インターフェースのインスタンスを取得する
    • Executors.newSingleThreadExecutor()
    • Executors.newCachedThreadPool()
    • Executors.newFixedThreadPool(int nThreads)
    • Executors.newScheduledThreadPool(int corePoolSize)
    • etc.
    スレッドプール
    複数のタスクを同時実行する際に、複数のスレッドを効率よく使う仕組み

    View Slide

  9. Copyright © 2023, Oracle and/or its affiliates
    9
    • work-stealing アルゴリズムを実装したスレッドプール
    • work-stealing: 自分のタスクが終了したワーカースレッドが別のスレッドのタスクキューからタスクを盗む(steal)よ
    うなスケジューリング方式
    • スレッドが遊んでいる時間を極力減らし、並行処理の密度をあげることを狙いとしている
    参考:ForkJoinPool
    task
    sub-task 1
    sub-task 2 sub-task 3
    ・・・
    ・・・
    result
    fork
    join
    ワーカースレッド ワーカースレッド
    fork
    join
    steal
    タスクキュー タスクキュー
    タスクキューが空なら
    別のワーカーのタスクキュー
    からタスクを盗む(steal)
    work-stealing の概要イメージ Fork/Join の概要イメージ

    View Slide

  10. Copyright © 2023, Oracle and/or its affiliates
    10
    1. java.lang.Thread, java.lang.Runnable を使う
    2. java.util.concurrent.* を使う
    Demo1: Java でスレッドを扱う

    View Slide

  11. Copyright © 2023, Oracle and/or its affiliates
    11
    • Java 5 で追加された Concurrency Utilities を拡張する形で策定
    • Java/Jakarta EE のコンテナがスレッドを含む各種リソースを管理する関係上、アプリケーションから Thread,
    Concurrency Utilities を直接使うことは非推奨
    • → 生成するスレッドを Java/Jakarta EE コンテナ、アプリケーションサーバーの管理下にするために拡張
    • Java/Jakarta EE アプリケーション実行環境から非同期に複数の処理を並行実行することを可能にする機能
    • Java SE で利用できる ExecutorService, ScheduledExecutorService を拡張したスレッド管理機能を提供
    • ManagedExecutorService: 標準的なスレッドプールを提供
    • ManagedScheduledExecutorService: タスクの繰り返しやタイマー実行が可能なスレッドプールを提供
    • ManagedThreadFactory: コンテナ管理用のスレッドを生成するファクトリー
    • ContextService: 並行タスクにコンテナの情報を設定するためのユーティリティ
    参考:https://jakarta.ee/specifications/concurrency/2.0/concurrency-spec-2.0.html#goals-of-this-specification
    Jakarta Concurrency/Concurrency Utilities for Java EE

    View Slide

  12. Copyright © 2023, Oracle and/or its affiliates
    12
    初期の Solaris における Java のスレッドの仕組み
    • 複数の JVM スレッドが 1 OS スレッドに紐づく
    • = グリーンスレッド
    • JVM スレッド:OS スレッド= M:1 の関係
    • シングルコアの時代にマルチスレッドを扱うための仕
    組み
    Java 18 までの Java のスレッドの仕組み
    • 1 つの JVM スレッドが 1 OS スレッドに対して厳密に
    紐づく
    • = プラットフォームスレッド
    • JVM スレッド:OS スレッド= 1:1 の関係
    Java のスレッド事情 – ざっくり歴史
    OS スレッド
    JVM スレッド ・・・
    JVM スレッド
    OS スレッド
    ・・・
    OS スレッド
    JVM スレッド JVM スレッド
    1
    1
    M
    1

    View Slide

  13. Copyright © 2023, Oracle and/or its affiliates
    13
    • (初期の Solaris は厳密には違うが)1 つの Java スレッドは、1 つの OS スレッドの薄いラッパー
    • OS スレッドの生成は、CPU、メモリ、等のコストが高い
    • スレッド間の切り替え(= コンテキスト・スイッチ)もコストが高い
    • 利用可能なスレッドの数を制限している
    • 事前に一定数作成したスレッドを効率的に使いまわすための仕組み(= スレッドプール)を用いてきた
    Java でスレッドを扱う際の問題点(~Java 18)とその対応

    View Slide

  14. Copyright © 2023, Oracle and/or its affiliates
    14
    Virtual Threads Overview

    View Slide

  15. Copyright © 2023, Oracle and/or its affiliates
    15
    JEP(JDK Enhancement-Proposal)
    • JDK に対する重要な変更を設計および実装するための提案
    Projects
    • 大きなインパクトのある機能については、JEP だけではなく OpenJDK のサブプロジェクトを発足して開発を行う
    • Project Amber, Loom, Panama, Valhalla, etc.
    前提知識

    View Slide

  16. Copyright © 2023, Oracle and/or its affiliates
    16
    Project Loom
    • Java プラットフォーム上で動作し、使いやすくスループットの高い軽量並行処理と新しいプログラミングモデルを実現する
    ことを目的としたプロジェクト
    • 新しい構成要素を追加することで対応
    • 仮想スレッド ← 今回のテーマ
    • 限定継続
    • 末尾呼出しの削除
    Project Loom

    View Slide

  17. Copyright © 2023, Oracle and/or its affiliates
    17
    • JVM 上に仮想的なスレッド(Virtual Threads)を導入すること
    • Java でも 言語のスレッド:OS のスレッド = M(:N):N な関係を作れるようにする!
    • 他の言語でいうところの Fiber, Coroutine, SemiCoroutine, …
    • java.lang.Thread の API を使用する既存のコードに対して、最小限の変更で仮想スレッドを利用できるようにすること
    • 既存の JDK ツールを用いたトラブルシューティング、デバッグ、プロファイリングは容易に行えるように
    Virtual Threads – JEP 436
    導入の目的 & ゴール
    OS スレッド
    ・・・
    OS スレッド
    JVM スレッド JVM スレッド
    OS スレッド
    ・・・
    OS スレッド
    JVM スレッド JVM スレッド
    JVM
    スレッド
    JVM
    スレッド
    ・・・ JVM
    スレッド
    JVM
    スレッド
    ・・・
    1
    1
    M
    N
    N
    ~ Java 18 までの Java のスレッドの仕組み JEP 425 で追加される仮想スレッドの仕組み

    View Slide

  18. Copyright © 2023, Oracle and/or its affiliates
    18
    使い方
    • プレビュー版の API なので、コンパイルや実行時に --enable-preview のフラグが必要
    • e.g. java --source 19 --enable-preview Main.java, jshell --enable-preview
    • 仮想スレッドの作り方 → 通常は、java.util.concurrent.Executors に新しく追加された API を用いる
    Virtual Threads – JEP 436
    Virtual Threads の使い方
    ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
    // or
    ExecutorService executor = Executors.newThreadPerTaskExecutor(Thread.ofVirtual().factory());

    View Slide

  19. Copyright © 2023, Oracle and/or its affiliates
    19
    {n ∈ N | n ≤ 10,000} に対して、スリープ(1,000 ms)を挟みながら FizzBuzz 問題*を行う
    *FizzBuzz 問題:
    • n が 3 の倍数 → Fizz を出力
    • n が 5 の倍数 → Buzz を出力
    Demo2: Virtual Threads を実際に使ってみる
    vs. Platform Thread
    public static void main(String[] args) {
    long start = System.currentTimeMillis();
    ThreadFactory virtualThreadFactory = Thread.ofVirtual().factory();
    createThreadPerExecFizzBuzz(virtualThreadFactory);
    long end = System.currentTimeMillis();
    logger.info("Execution time: " + Long.toString(end - start) + "[ms]");
    }
    public static void createThreadPerExecFizzBuzz(ThreadFactory factory) {
    FizzBuzzTask task = new FizzBuzzTask();
    try (ExecutorService exector = Executors.newThreadPerTaskExecutor(factory)) {
    IntStream.rangeClosed(1, 10_000).forEach(i -> {
    exector.submit(() -> {
    task.execWithSleep(i, 1_000);
    Utils.log(i + “: ” + task.exec(i)); // スレッド名と併せてログ出力
    });
    });
    }
    }
    public static void main(String[] args) {
    long start = System.currentTimeMillis();
    ThreadFactory platformThreadFactory = Thread.ofPlatform().factory();
    createThreadPerExecFizzBuzz(platformThreadFactory);
    long end = System.currentTimeMillis();
    logger.info("Execution time: " + Long.toString(end - start) + "[ms]");
    }
    public static void createThreadPerExecFizzBuzz(ThreadFactory factory) {
    FizzBuzzTask task = new FizzBuzzTask();
    try (ExecutorService exector = Executors.newThreadPerTaskExecutor(factory)) {
    IntStream.rangeClosed(1, 10_000).forEach(i -> {
    exector.submit(() -> {
    task.execWithSleep(i, 1_000);
    Utils.log(i + “: ” + task.exec(i)); // スレッド名と併せてログ出力
    });
    });
    }
    }
    Virtual Thread Platform Thread

    View Slide

  20. Copyright © 2023, Oracle and/or its affiliates
    20
    • .oO そういえば、 java.util.concurrent.Executors には、固定長のスレッドプール(Single/FixedThreadPool)を
    作る API や上限(Integer.MAX_VALUE)を設けたうえで、キャッシュしながら必要な数分のスレッドを作るスレッド
    プール(CachedThreadPool)が提供されているが、それらを使うと何か問題になるのだろうか…?
    • 仮想スレッドはプールせずに使うこと!
    • 生成コストが高価な OS のスレッドを必要以上に作成しないために、今まではスレッドプールを使っていた
    • そもそも仮想スレッドの生成は高価ではないので、プールする必要がない
    • プールする代わりに、スレッドの生成に制約を設けないようなモデル(= タスクの実行毎に仮想スレッドを作成するモ
    デル)を採用
    • Executors.newThreadPerTaskExecutor(Thread.ofVirtual().factory())
    • Executors.newVirtualThreadTaskExecutor()
    • リソースへのアクセス数を制限したい場合は、java.util.concurrent.Semaphore を使用する
    Virtual Threads – JEP 436
    仮想スレッドはプールせずに使用する
    実現するための API が追加されています!

    View Slide

  21. Copyright © 2023, Oracle and/or its affiliates
    21
    • 従来 JDK が提供してきたデバッグや監視用途のツールも同様に使用可能
    • Debugger
    • 所謂、デバッガー
    • 仮想スレッドのステップ実行やコールスタックの表示、スタックフレーム内の変数の検査が可能
    • JFR(JDK Flight Recorder)
    • 実行中の Java アプリケーションに関する診断およびプロファイリングのデータを低オーバーヘッドで収集するツール
    • アプリケーションコードからのイベント(オブジェクトの割り当て、I/O 操作、etc.)を正しく仮想スレッドに割り当て可能
    • スレッドダンプ(プロセスの一部となっているすべてのスレッドの状態のスナップショット)
    • jcmd や jstack で取得可能
    • スレッドの数が莫大に増えることを考慮し、従来のフラットな構造に加え、JSON 形式の出力をサポート
    Virtual Threads – JEP 436
    仮想スレッドの監視
    仮想スレッドは、JDK に実装されており、特定の OS スレッドに紐づけられていないため、
    監視の際は OS レベルの監視ツールではなく、上記のようなツールを用いることが重要!

    View Slide

  22. Copyright © 2023, Oracle and/or its affiliates
    22
    1. Debugger
    • 仮想スレッドのステップ実行やコールスタックの表示、スタックフレーム内の変数の検査をしてみる
    2. JFR, JDK Mission Control を用いてメトリクスを分析してみる
    3. jcmd を用いてスレッドダンプを確認してみる
    Demo3: Virtual Threads の監視
    Debugger/JFR(JDK Flight Recoder) + JDK Mission Control/スレッドダンプ
    public static void createThreadPerExecFizzBuzz(ThreadFactory factory) {
    FizzBuzzTask task = new FizzBuzzTask();
    try (ExecutorService exector = Executors.newThreadPerTaskExecutor(factory)) {
    IntStream.rangeClosed(1, 10_000).forEach(i -> {
    exector.submit(() -> {
    task.execWithSleep(i, 1_000);
    Utils.log(i + “: ” + task.exec(i));
    });
    });
    }
    }
    デバッグ実行
    $ jcmd JFR.start duration=1m filename=oochacafe.jfr
    $ jcmd Thread.dump_to_file -format=json ochacafe.json
    JMC

    View Slide

  23. Copyright © 2023, Oracle and/or its affiliates
    23
    • スレッドを有効的に使うためには、スケジューリングが必要
    • プラットフォームスレッド(OS スレッドの薄いラッパー)
    • OS 内のスケジューラーによってスケジューリングされる
    • 仮想スレッド
    • JDK 独自のスケジューラー(work-stearing ForkJoinPool)によってスケジューリングされる
    • 仮想スレッドをプラットフォームスレッドに割り当てた後、OS 内のスケジューラーによってスケジューリングされる
    • 仮想スレッドは、ライフサイクル中で異なるキャリアにスケジューリングされる可能性がある
    Virtual Threads – JEP 436
    仮想スレッドのスケジューリング
    プラットフォームスレッド 1
    仮想スレッド
    タスク
    マウント
    プラットフォームスレッド 1
    仮想スレッド
    タスク
    プラットフォームスレッド 1
    仮想スレッド
    タスク
    アンマウント
    プラットフォームスレッド 2
    仮想スレッド
    タスク
    マウント
    ブロック操作
    完了準備
    OK
    ブロック
    操作

    View Slide

  24. Copyright © 2023, Oracle and/or its affiliates
    24
    • キャリアと仮想スレッドのスタックトレースは別もの
    • 仮想スレッドで投げられた例外は、キャリアのスタックフレームを含まない(※逆も同様)
    • スレッドダンプでは、仮想スレッドのスタックにキャリアのスタックフレームは表示されない(※逆も同様)
    • キャリアのスレッドローカル変数は、仮想スレッドでは使用できない
    • スレッドローカル変数の使用は慎重に検討する
    • → 膨大な数のスレッドで実行されるときのメモリのフットプリントを考慮すること
    Virtual Threads – JEP 436
    仮想スレッドを使用する上での諸注意

    View Slide

  25. Copyright © 2023, Oracle and/or its affiliates
    25
    • 同時実行のタスク数が多い(数千以上)
    • 作業負荷が CPU バウンドではないこと
    • 長い時間計算を行うような場合には、効果がない
    • e.g. 巨大な配列をソートする、etc.
    • 高速化(低レイテンシー)ではなく、高スループットを実現するための技術
    Virtual Threads – JEP 436
    仮想スレッドが有効な場面

    View Slide

  26. Copyright © 2023, Oracle and/or its affiliates
    26
    • 計算処理の時間 << 通信、DB アクセス等の I/O 処理にかかる時間(待ち時間含む)
    • I/O 処理の待ち時間に別の処理を行いたい…
    e.g. 一般的なサーバーサイドアプリケーション
    client trip-manager hotel-booking flight-booking
    POST /trip
    POST /hotel
    book()
    book()
    POST /flight
    待ち
    待ち
    待ち
    待ち
    仮想スレッドが
    有効的に使えるのでは?

    View Slide

  27. Copyright © 2023, Oracle and/or its affiliates
    27
    • Java でも OS のスレッド:言語のスレッド = M(:N):N な関係が作れるようになる
    • 2023 年 2 月現在は、プレビュー機能なので、使用する際は --enable-preview のフラグが必要
    • 順調にいけば、次の LTS である Java 21 に導入か…?
    • 高速化(低レイテンシー)ではなく、高スループットを実現するための技術
    • Java を使う開発者にとっては、慣れ親しんだ方法で仮想スレッドを使うことができる
    • スレッドの作成、JDK ツールを用いた監視、etc.
    • 仮想スレッドを使う場合、今までのスレッドに対する常識は注意が必要なものも…
    • スレッドプール、(場合によっては)スレッドローカル変数、etc.
    ここまでのまとめ

    View Slide

  28. Copyright © 2023, Oracle and/or its affiliates
    28
    Helidon & Helidon Níma

    View Slide

  29. Copyright © 2023, Oracle and/or its affiliates
    29
    Oracle がホストする OSS プロジェクト
    • GitHub でソースコードを公開:https://github.com/oracle/helidon
    • Helidon の商用サポートは WebLogic Server/Coherence/Verrazzano のサポート契約に含まれる
    マイクロサービスアプリケーションが必要とする機能を提供する Java ライブラリの集合体
    • 単体の JVM として動作し、アプリケーションサーバ不要、容易なコンテナ化
    • 必要なコンポーネントを追加して拡張することも可能
    マイクロサービスの開発・運用を支援する機能を提供
    • OpenMetrics(監視)、OpenTracing(追跡)、OpenAPI(API 公開)
    • 耐障害性/回復性: ヘルスチェック、サーキット・ブレーカ
    2つのプログラミングモデルを提供
    • Helidon MP:宣言的記法(Java/Jakarta EE 開発者フレンドリー)
    • Helidon SE:関数的型記法
    Project Helidon
    クラウドネイティブなマイクロサービスを開発するための Java アプリケーションフレームワーク

    View Slide

  30. Copyright © 2023, Oracle and/or its affiliates
    30
    Helidon SE と MP
    • Eclipse MicroProfile 準拠
    • 軽量フットプリント
    • 宣言型
    • Java EE サブセット +
    マイクロサービス関連機能
    • マイクロ・フレームワーク
    • 超軽量フットプリント
    • 関数型
    • Reactive, non-blocking
    Helidon MP Helidon SE
    ≒ + Eclipse
    MicroProfile
    + 拡張機能
    フットプリント重視
    Polyglot 言語開発者向け
    機能性・互換性重視
    Java/Jakarta EE 開発経験者向け

    View Slide

  31. Copyright © 2023, Oracle and/or its affiliates
    31
    • Helidon はライブラリをパッケージングした Java SE アプリケーションとして実行される(= Executable JAR)
    • Helidon アプリケーションは個々の JVM 上で実行
    • 複数のパッケージング・オプション、Docker にも対応 – ビルド・ツールを使って簡単に作成
    多彩なパッケージング方法を提供
    Executable JAR Jlink ランタイム・イメージ GraalVM ネイティブ・イメージ
    Container
    Application
    Java Runtime
    Linux
    Container
    Custom
    Java Runtime
    Linux
    Container
    Native Application
    Linux
    Application

    View Slide

  32. Copyright © 2023, Oracle and/or its affiliates
    32
    2018 2020 2022 2023
    Helidon の生い立ちとこれから
    Helidon 0.x – 1.x Helidon 2.x Helidon 3.x Helidon 4.x
    • Java 8
    • MicroProfile 3.2
    • Java 11
    • MicroProfile 3.3
    • Java 17
    • MicroProfile 5.0
    • Java 19 (Java 21)
    • MicroProfile Next

    View Slide

  33. Copyright © 2023, Oracle and/or its affiliates
    33
    アプローチ 1 – Reactive Programming
    • ノンブロッキング
    • イベントループの使用
    • 少数のスレッドですべてのリクエストを処理する
    アプローチ 2 – Virtual Threads // NEW!!
    • ブロッキング
    • 安価にスレッド(仮想スレッド)を作成することで高いスループットを実現
    高スループットを実現するための “Helidon” のアプローチ
    Reactive プログラミングの詳細はこちらから

    View Slide

  34. Copyright © 2023, Oracle and/or its affiliates
    34
    • https://helidon.io/nima
    • νήμα(nima)は、ギリシャ語で「糸、毛糸、編み糸」という意味
    • 仮想スレッド(Virtual Threads)ベースの Java のマイクロサービス・フレームワーク
    • Helidon のエコシステムにおける Netty* の置き換えがゴール
    • アプリケーションをブロッキングでシンプルに実装可能
    • ブロッキングな実装でも高いスループットが実現可能
    • 2023 年 2 月現在:テクノロジープレビュー版を Helidon 4.0.0-ALPHA4で公開中
    • https://github.com/helidon-io/helidon/tree/4.0.0-ALPHA4
    • 提供機能:
    • HTTP/1, HTTP/2, gRPC, Metrics, Health Checks, Tracing, Fault Tolerance, Testing Integration
    *: イベントドリブンな非同期通信を行うアプリケーションを開発するためのフレームワーク
    Helidon Níma
    Virtual Threads によるブロッキング・スレッドモデルの採用

    View Slide

  35. Copyright © 2023, Oracle and/or its affiliates
    35
    Níma vs. other servers
    0
    100000
    200000
    300000
    400000
    500000
    600000
    700000
    800000
    900000
    JSON HTTP/2 TLS
    Requests/second
    Netty
    Níma
    Helidon MP (Níma)
    Dropwizard
    https://medium.com/helidon/helidon-n%C3%ADma-helidon-on-virtual-threads-130bb2ea2088

    View Slide

  36. Copyright © 2023, Oracle and/or its affiliates
    36
    Helidon MP on Níma
    Virtual Threads ベースの Helidon によるスループットの向上
    0
    50000
    100000
    150000
    200000
    250000
    300000
    350000
    400000
    JSON HTTP/2 TLS
    Requests/second
    Platform threads
    Virtual threads

    View Slide

  37. Copyright © 2023, Oracle and/or its affiliates
    37
    対象のアプリケーション:
    • Helidon MP on Níma
    • 4.0.0-ALPHA4
    • Helidon MP/SE
    • 3.1.0
    • Spring Boot
    • 3.0.2
    Demo4: Helidon Níma のスループットを体験してみる
    シンプルな文字列を返却するアプリケーションに負荷をかけてスループットを体験する
    --vus 50
    --duration 15s
    /cowsay/say

    View Slide

  38. Copyright © 2023, Oracle and/or its affiliates
    38
    仮想スレッド(Virtual Threads)
    • Java でも OS のスレッド:言語のスレッド = M(:N):N な関係を作れるように
    • 高速化(低レイテンシー)ではなく、高スループットを実現するための技術
    • 慣れ親しんだ方法で仮想スレッドを使うことができるが、一部使い方には注意が必要
    • スレッドプール、(場合によっては)スレッドローカル変数、etc.
    Helidon Níma
    • 仮想スレッド(Virtual Threads)ベースの Java のマイクロサービス・フレームワーク
    • 仮想スレッドを前提とした HTTP、gRPC、WebSocket のブロッキング・モデルの実装を提供
    • ブロッキング・モデル実装でも高いスループットを実現
    まとめ

    View Slide

  39. Copyright © 2023, Oracle and/or its affiliates
    39
    • JEP 436: Virtual Threads (Second Preview)
    • https://openjdk.org/jeps/436
    • Loom – Fibers, Continuations and Tail-Calls for the JVM
    • https://openjdk.org/projects/loom/
    • JavaのProject Loomと仮想スレッドの内部
    • https://blogs.oracle.com/oracle4engineer/post/going-inside-javas-project-loom-and-virtual-
    threads-ja
    • Helidon Níma
    • https://helidon.io/nima
    • Helidon Níma – Helidon on Virtual Thread
    • https://medium.com/helidon/helidon-n%C3%ADma-helidon-on-virtual-threads-130bb2ea2088
    • oracle-japan/ochacafe-concurrent-programming
    • https://github.com/oracle-japan/ochacafe-concurrent-programming
    参考情報

    View Slide

  40. Thank you
    Copyright © 2023, Oracle and/or its affiliates
    40

    View Slide