GrantForge

    アーキテクチャとセキュリティ

    性能とベンチマーク

    アカウント 100 万件規模の性能目標、ベンチマークのデータと方法、ローカルで実行する方法。

    GrantForge の性能目標は大規模組織を想定しています。アカウント 100 万件、ロール 1 万件、リソース 10 万件。システムベンチマークは毎晩 PostgreSQL 17 上で実行され、いずれかの指標が上限を超えるとビルドが失敗します。

    目標

    指標 意味 上限
    authz.snapshot.hit キャッシュ済みの権限スナップショット(インターフェースを呼ぶたびに使用) p99 1 ms
    authz.snapshot.build あるアカウントのコンソールスナップショットを初めて計算 p95 50 ms
    authz.snapshot.app リソースツリーが大きいアプリケーションでスナップショットを計算 p95 50 ms
    api.users.page ユーザー一覧の 1 ページ(先頭 500 ページ以内) p95 200 ms
    api.users.search 名前でユーザーを検索 p95 200 ms
    api.groups.page ユーザーグループ一覧の 1 ページ p95 200 ms
    api.roles.list ロール一覧(ページングなし) p95 200 ms
    api.me.authorization 現在のアカウントの権限 p95 200 ms
    api.member.groups ページ権限が 1 つしかないアカウントが保護された一覧にアクセス p95 200 ms
    jmh.derivation.* 大きなリソースツリーに対する導出の準備、権限付与 20 件の導出(JMH) 平均 50 / 5 ms

    上限は引き下げる場合のみ許可されます。いずれかを緩和するには、記録に残された判定が必要です。

    データ

    ベンチマークは実際のサービスを起動し、初期化を完了させてから、アプリケーション自身のエンティティを通じてデータを書き込みます。

    • 部門 100 個、アカウント 1000 件ごとにユーザーグループ 1 個、職位 100 個とし、
    • 各アカウントは 1 つの部門と 1 つのユーザーグループに属し、10 件のアカウントごとに 1 件は職位を持ち、20 件のアカウントごとに 1 件は直接割り当てられたロールを持ちます。
    • 10 件のロールごとに 1 件は、先頭 100 件のロールのいずれかを継承します。ユーザーグループごとにロール 3 件、部門ごとに 2 件、職位ごとに 1 件を割り当て、各ロールはコンソールページ 5 件を許可されます。
    • アプリケーションは 1 つで、複数のモジュールの下にページ 100 件、各ページに操作 9 件を置き、ロールの 10 分の 1 にそのうちページと操作を 20 件ずつ許可します。

    各指標はウォームアップの後、呼び出し単位で 1 件ずつ測定します。

    ローカルで実行

    bash script/ci/perf_benchmark.sh full            # 目標規模、postgres:17(Docker が必要)、上限を検査
    bash script/ci/perf_benchmark.sh smoke           # H2 上の小規模で、ベンチマークが動作することのみ確認
    bash script/ci/perf_benchmark.sh full mysql:8.4  # 他のデータベース

    レポートは perf/target/perf-report.json に書き込まれ、ログには表形式でも出力されます。PERF_OPTS で追加のパラメータを渡せます。

    パラメータ デフォルト値 意味
    perf.database postgres:17 h2 または <エンジン>:<バージョン>
    perf.users / perf.roles / perf.resources 1000000 / 10000 / 100000 データ規模
    perf.samples / perf.warmup 1000 / 200 各指標の測定回数とウォームアップ回数
    perf.jmh true JMH ベンチマークも併せて実行
    perf.enforce true 上限超過時に終了コード 1 で終了

    なぜ高速なのか

    • 権限スナップショットはアカウントごとにキャッシュし、カタログとテナントのバージョン番号に応じて一括で無効化されるため、キャッシュに当たればメモリ読み取り 1 回で済みます。
    • 導出はメモリ上で行われます。リソースツリー、継承関係、割り当てをあらかじめコンパクトな構造として読み込んでおくことで、1 件ずつクエリすることを避けています。
    • 一覧インターフェースはすべてページングし、並び替えとフィルターはインデックスのある列に対してのみ行われます。遅延読み込みした関連は 64 件単位で読み込み、書き込みは 50 件単位でコミットします(ID はアプリケーションが生成するため、一括挿入が可能です)。

    GitHub でこのページを編集