BencherでCIのベンチマークを追跡する方法
ほとんどのベンチマーク結果は短命です。 それらは、ターミナルのスクロールバック制限に達するとすぐに消えてしまいます。 一部のベンチマークハーネスは結果をキャッシュすることができますが、大部分はローカルにしかできません。 Bencherを使用すると、ローカルおよびCIの実行からベンチマークを追跡し、結果を比較し、 お気に入りのベンチマークハーネスを使い続けることができます。
CIでベンチマークを行う場合、つまり継続的ベンチマークの場合に、 ベンチマーク結果を比較するには、3つの一般的な方法があります:
- 統計的継続ベンチマーク
- ベンチマーク結果を長期間追跡してベースラインを作成する
- このベースラインを統計的しきい値と組み合わせて、統計的境界を作成する
- この統計的境界と新しい結果を比較して、パフォーマンスの退行を検出する
- 相対的継続ベンチマーク
- 現在のベースラインコードのためのベンチマークを実行する
- コードを新しいバージョンに切り替える
- 新しいバージョンのコードのためのベンチマークを実行する
- パーセンテージしきい値を用いてベースラインコードの境界を作成する
- 新しいバージョンのコード結果とベースラインコード結果を比較し、パフォーマンスの退行を検出する
- 変化点検出
- 定期的に新しいバージョンのコードのためのベンチマークを実行する
- 変化点検出アルゴリズムを使用してパフォーマンスの退行を検出する
- パフォーマンスの退行を引き起こしたコミットを見つけるためにバイセクトする
統計的連続ベンチマーク
クイックスタートおよびDockerセルフホストチュートリアルの続きとして、
Save Walter White
プロジェクトに統計的連続ベンチマークを追加しましょう。
🐰 続行する前に APIトークンを作成して
BENCHER_API_TOKEN
環境変数として設定したことを確認してください!
これで、CIでベンチマークを実行する準備が整いました。 すべてのCI環境は少しずつ異なるため、次の例は実用性よりも説明的なものになっています。 より具体的な例については、GitHub Actionsでの連続ベンチマークおよび GitLab CI/CDでの連続ベンチマークを参照してください。
まず、CIでの変更ごとにmain
ブランチの履歴ベースラインを作成および維持する必要があります:
bencher run
CLIサブコマンドを使用して、main
ブランチのベンチマークを実行します。 詳細についてはbencher run CLIサブコマンドを参照してください。 (例:bencher run
)--project
オプションをプロジェクトslugに設定します。 詳細についてはプロジェクトオプションを参照してください。 (例:--project save-walter-white-1234abcd
)--branch
オプションを基本ブランチ名に設定します。 詳細についてはブランチオプションを参照してください。 (例:--branch main
)--testbed
オプションをCIランナーテストベッド名に設定します。 詳細についてはテストベッドオプションを参照してください。 (例:--testbed ci-runner
)main
ブランチ、ci-runner
テストベッド、latency
メジャーのしきい値を設定します:--threshold-measure
オプションは、bencher mock
で生成されるビルトインlatency
メジャーに設定します。 詳細についてはしきい値メジャーオプションを参照してください。 (例:--threshold-measure latency
)--threshold-test
オプションをスチューデントのt検定(t_test
)に設定します。 詳細についてはしきい値テストオプションを参照してください。 (例:--threshold-test t_test
)--threshold-max-sample-size
オプションを64
の最大サンプルサイズに設定します。 詳細についてはしきい値最大サンプルサイズを参照してください。 (例:--threshold-max-sample-size 64
)--threshold-upper-boundary
オプションを0.99
の上限に設定します。 詳細についてはしきい値上限を参照してください。 (例:--threshold-upper-boundary 0.99
)--thresholds-reset
フラグを設定し、指定されたしきい値のみを有効にします。 詳細についてはしきい値リセットを参照してください。 (例:--thresholds-reset
)
- アラートが生成された場合にコマンドを失敗させるために
--err
フラグを設定します。 詳細についてはアラートエラーを参照してください。 (例:--err
) bencher mock
で生成されるBencherメトリックフォーマットJSON(json
)を--adapter
オプションに設定します。 完全な概要についてはベンチマークハーネスアダプタを参照してください。 (例:--adapter json
)- ベンチマークコマンド引数を指定します。
詳細についてはベンチマークコマンドを参照してください。
(例:
bencher mock
)
このコマンドがCIで初めて実行されると、
存在しない場合はmain
ブランチが作成されます。
新しいmain
には開始点や既存データはありません。
main
ブランチ、ci-runner
テストベッド、およびlatency
メジャーに対するしきい値が作成されます。
その後の実行では、新しいデータがmain
ブランチに追加されます。
指定されたしきい値が使用されてパフォーマンスの低下を検出します。
これでCIでのパフォーマンス低下をキャッチする準備が整いました。
これは、CIで新しい機能ブランチをfeature-branch
として追跡する方法です:
bencher run
CLIサブコマンドを使用して、feature-branch
ブランチのベンチマークを実行します。 詳細についてはbencher run CLIサブコマンドを参照してください。 (例:bencher run
)--project
オプションをプロジェクトslugに設定します。 詳細についてはプロジェクトオプションを参照してください。 (例:--project save-walter-white-1234abcd
)--branch
オプションを機能ブランチ名に設定します。 詳細についてはブランチオプションを参照してください。 (例:--branch feature-branch
)feature-branch
ブランチの開始点を設定します:--start-point
オプションを機能ブランチの開始点に設定します。 詳細については開始点を参照してください。 (例:--start-point main
)--start-point-hash
オプションを機能ブランチの開始点git
ハッシュに設定します。 詳細については開始点ハッシュを参照してください。 (例:--start-point-hash 32ae...dd8b
)--start-point-clone-thresholds
フラグを設定して、開始点からしきい値をクローンします。 詳細については開始点クローンしきい値を参照してください。 (例:--start-point-clone-thresholds
)--start-point-reset
フラグを設定してブランチを常に開始点にリセットします。 これにより、ベンチマークデータのドリフトを防ぎます。 詳細については開始点リセットを参照してください。 (例:--start-point-reset
)
--testbed
オプションをテストベッド名に設定します。 詳細についてはテストベッドオプションを参照してください。 (例:--testbed ci-runner
)- アラートが生成された場合にコマンドを失敗させるために
--err
フラグを設定します。 詳細についてはアラートエラーを参照してください。 (例:--err
) bencher mock
で生成されるBencherメトリックフォーマットJSON(json
)を--adapter
オプションに設定します。 完全な概要についてはベンチマークハーネスアダプタを参照してください。 (例:--adapter json
)- ベンチマークコマンド引数を指定します。
詳細についてはベンチマークコマンドを参照してください。
(例:
bencher mock
)
このコマンドがCIで初めて実行されると、
Bencherはfeature-branch
ブランチを作成します(まだ存在していないため)。
新しいfeature-branch
は、
ハッシュ32aea434d751648726097ed3ac760b57107edd8b
のmain
ブランチを
開始点として使用します。
これは、feature-branch
がmain
ブランチからすべてのデータとしきい値のコピーを持ちながら、
bencher mock
の結果を比較することを意味します。
その後のすべての実行では、Bencherはfeature-branch
ブランチを開始点にリセットし、
main
ブランチのデータとしきい値を使用してパフォーマンスの低下を検出します。
相対連続ベンチマーク
クイックスタートおよびDocker 自己ホストチュートリアルから引き継いで、Save Walter White
プロジェクトに相対連続ベンチマークを追加してみましょう。
🐰 続ける前に、 APIトークンを作成して、
BENCHER_API_TOKEN
環境変数として設定します !
相対連続ベンチマークは、コードの2つのバージョンを並べて比較します。
これは、利用可能なリソースが実行ごとに大きく変動する可能性がある、ノイズの多いCI/CD環境で役立つことがあります。
この例では、main
ブランチでの実行結果と、適切に命名されたfeature-branch
という機能ブランチでの結果を比較します。
すべてのCI環境は少しずつ異なるため、以下の例は実際的というよりも説明的なものです。
より具体的な例については、GitHub Actionsで連続ベンチマークとGitLab CI/CDで連続ベンチマークを参照してください。
まず、CIでgit
を使用してmain
ブランチをチェックアウトする必要があります:
次に、CIでmain
ブランチのベンチマークを実行する必要があります:
bencher run
CLIサブコマンドを使用してmain
ブランチのベンチマークを実行します。 詳細な情報はbencher run
CLIサブコマンドを参照してください。 (例:bencher run
)--project
オプションをプロジェクトスラッグに設定します。 詳細は--project
ドキュメントをご覧ください。 (例:--project save-walter-white-1234abcd
)--branch
オプションをベースブランチ名に設定します。 詳細は--branch
ドキュメントをご覧ください。 (例:--branch main
)--start-point-reset
フラグを設定して常にベースブランチをリセットします。 この方法で、すべてのベンチマークデータが現在のCIランナーからのものであることを確認します。 詳細は--start-point-reset
ドキュメントをご覧ください。 (例:--start-point-reset
)--testbed
オプションをCIランナーテストベッドの名前に設定します。 詳細は--testbed
ドキュメントをご覧ください。 (例:--testbed ci-runner
)--adapter
オプションをbencher mock
によって生成されたBencher Metric Format JSON (json
)に設定します。 詳細はベンチマーカーアダプターをご覧ください。 (例:--adapter json
)- ベンチマークコマンド引数を指定します。
詳細はベンチマークコマンドをご覧ください。
(例:
bencher mock
)
CIでこのコマンドを初めて実行すると、存在しないためmain
ブランチが作成されます。
新しいmain
には、開始点、既存のデータ、またはスレッショルドがありません。
その後の実行では、古いmain
ヘッドが置き換えられ、新しいmain
ヘッドが開始点、既存のデータ、またはスレッショルドなしで作成されます。
次に、CIでgit
を使用してfeature-branch
ブランチをチェックアウトする必要があります:
最後に、CIでfeature-branch
のベンチマークを実行する準備が整いました:
bencher run
CLIサブコマンドを使用してfeature-branch
ベンチマークを実行します。 詳細な情報はbencher run
CLIサブコマンドを参照してください。 (例:bencher run
)--project
オプションをプロジェクトスラッグに設定します。 詳細は--project
ドキュメントをご覧ください。 (例:--project save-walter-white-1234abcd
)--branch
オプションを機能ブランチ名に設定します。 詳細は--branch
ドキュメントをご覧ください。 (例:--branch feature-branch
)feature-branch
ブランチのスタートポイントを設定します:--start-point
オプションを機能ブランチのスタートポイントに設定します。 詳細は--start-point
ドキュメントをご覧ください。 (例:--start-point main
)--start-point-reset
フラグを設定して、ブランチを常にスタートポイントにリセットします。 これにより、最新の相対ベンチマーク結果のみが使用されます。 詳細は--start-point-reset
ドキュメントをご覧ください。 (例:--start-point-reset
)
--testbed
オプションをCIランナーテストベッドの名前に設定します。 詳細は--testbed
ドキュメントをご覧ください。 (例:--testbed ci-runner
)feature-branch
ブランチ、ci-runner
テストベッド、およびlatency
測定値のスレッショルドを設定します:--threshold-measure
オプションを、bencher mock
によって生成された組み込みlatency
測定値に設定します。 詳細は--threshold-measure
ドキュメントをご覧ください。 (例:--threshold-measure latency
)--threshold-test
オプションを基本的なパーセンテージ(percentage
)に設定します。 詳細は--threshold-test
ドキュメントをご覧ください。 (例:--threshold-test percentage
)--threshold-upper-boundary
オプションを0.25
の上限に設定します。 詳細は--threshold-upper-boundary
ドキュメントをご覧ください。 (例:--threshold-upper-boundary 0.25
)--thresholds-reset
フラグを設定して、指定されたスレッショルドのみがアクティブになるようにします。 詳細は--thresholds-reset
ドキュメントをご覧ください。 (例:--thresholds-reset
)
- アラートが生成された場合にコマンドが失敗するように
--err
フラグを設定します。 詳細は--err
ドキュメントをご覧ください。 (例:--err
) --adapter
オプションをbencher mock
によって生成されたBencher Metric Format JSON (json
)に設定します。 詳細はベンチマーカーアダプターをご覧ください。 (例:--adapter json
)- ベンチマークコマンド引数を指定します。
詳細はベンチマークコマンドをご覧ください。
(例:
bencher mock
)
CIでこのコマンドを実行するたびに、feature-branch
の結果がmain
の最新の結果とだけ比較されます。
指定されたスレッショルドを使用し、パフォーマンスの低下を検出します。
変化点検出
変化点検出は、変化点アルゴリズムを使用して最近の結果の大きなウィンドウを評価します。 これにより、アルゴリズムは外れ値をノイズとして無視し、誤検出を少なくします。 変化点検出は継続的ベンチマークと見なされますが、 CIでのパフォーマンス回帰を検出することはできません。 つまり、機能ブランチがマージされる前に、パフォーマンスの回帰を検出することはできません。 これは「アウト・オブ・バンド」検出と呼ばれることもあります。
例えば、bench_my_critical_path
というベンチマークがあり、
過去のレイテンシーが次のようだったとします: 5 ms
, 6 ms
, 5 ms
, 5ms
, 7ms
。
次のベンチマーク結果が 11 ms
だった場合、統計的な連続ベンチマークのしきい値
と変化点検出アルゴリズムの解釈は非常に異なるでしょう。
しきい値はおそらく超えられ、警告が生成されます。
もしこのベンチマークの実行がプルリクエストに関連付けられていた場合、
この警告のためにビルドは失敗するように設定される可能性が高いです。
しかし、変化点アルゴリズムはまだ何もしないでしょう。
もし次の実行で 5 ms
に戻った場合、おそらく警告は生成されません。
逆に、次の一回か二回の実行で 10 ms
や 12 ms
になった場合、その時に変化点アルゴリズムが警告を発するでしょう。
Bencherで変化点検出を使用したいですか? もしそうなら、トラッキングイシューにコメントを残すか、 直接ご連絡ください。
🐰 おめでとうございます! Bencherを使ってCIでベンチマークを追跡する方法を学びました! 🎉