Skip to content

Decision Record: RhinoからGraalJSに切り替えることによる著しい性能低下のためGraalJS化は見送り。 (2026-04-25) #133

Description

@mitonize

背景

GraalJS への切り替え可否を判断するため、同一条件で Rhino と GraalJS の性能比較を実施した。

計測条件

  • 実行スクリプト: test-war/run-jmeter-with-jfr.sh
  • シナリオ: Mayaa-Cold(PERF_MIX_MAYAA_COLD=6
  • 負荷条件: 24 threads / rampup 10s / duration 45s / delay 10s
  • 計測日時: 2026-04-25

参考値(今回の実測)

  • Rhino
    • Throughput: 27,625 req/s
    • Avg: 0.624 ms
    • P95: 1 ms
    • Errors: 0
  • GraalJS
    • Throughput: 608 req/s
    • Avg: 28.9 ms
    • P95: 59 ms
    • Errors: 0

判断

現時点では GraalJS をデフォルトへ切り替えない(Rhino 継続)。

判断理由

  • スループットが大幅に低下(参考値ベースで約 -97.8%)
  • 平均・p95 レイテンシが数十倍悪化
  • 機能互換よりも運用性能リスクが大きい

想定される主因(仮説)

  1. with + ProxyObject による動的スコープ解決コスト
  2. Java <-> JavaScript 境界の変換コスト
  3. スレッド単位コンテキスト運用に伴うウォームアップ分散
  4. JSR-223 の Bindings / eval オーバーヘッド

再評価条件

  • スコープ解決方式の見直し(with 依存の低減)
  • 境界変換回数の削減
  • 同条件ベンチマークで有意な性能改善が確認できた場合

各要因の詳細

  1. with + ProxyObject の動的解決コスト
    with は識別子解決を動的にしてしまうため、エンジンが「この変数は常にこの場所」と固定最適化しにくくなります。
    さらに ProxyObject を挟むと、プロパティアクセスごとにホスト側コールバック(getMember/hasMember/putMember)が発生し、JS内の単純参照より重くなります。
    テンプレート実行は参照回数が多いので、1回あたりの小さい差が総和で大きくなります。

  2. Java <-> JS 境界往復コスト
    GraalVMでは、JavaオブジェクトをJSから触るたびに相互運用レイヤが介在します。
    今回の構造だと、AttributeScopeアクセス、値変換、同期処理で境界を何度も跨ぐため、CPU時間と割り当てが増えやすいです。
    特に「大量の小アクセス」を繰り返すワークロードで効きます。

  3. スレッドごとのコンテキスト分散
    Tomcatのワーカースレッドごとに実行状態が分散すると、ウォームアップがスレッド単位で進みます。
    結果として、単一スレッド長時間実行ほど最適化が乗らず、全体では「常に半分温まった状態」になりやすいです。
    短い処理を多数回さばくWeb処理だと不利です。

  4. JSR-223 オーバーヘッド
    Bindings生成、eval経路、型変換は純粋な埋め込みAPIより不利です。
    ただしこれ単体で数十倍差の主因にはなりにくく、上の1〜3と掛け算で効いていると見るのが自然です。

  5. Rhino 側の適合度
    Rhinoは既存実装で Scriptable スコープチェーンと密接に統合され、現在のMayaa実装に対して極めて低オーバーヘッドです。
    つまり「今のアーキテクチャ前提では最短経路に近い」ため、移植直後のGraalJS実装が同じ土俵で勝ちにくいのは合理的です。

要するに、今回の差は「GraalJSが遅い」というより、
「現在のMayaaスコープモデルをGraalJSの相互運用層で再現したときのコスト構造が重い」が主要因です。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions