BencherでCIのベンチマークを追跡する方法
ほとんどのベンチマーク結果は短命です。 それらは、ターミナルのスクロールバック制限に達するとすぐに消えてしまいます。 一部のベンチマークハーネスは結果をキャッシュすることができますが、大部分はローカルにしかできません。 Bencherを使用すると、ローカルおよびCIの実行からベンチマークを追跡し、結果を比較し、 お気に入りのベンチマークハーネスを使い続けることができます。
CIでベンチマークを行う場合、つまり継続的ベンチマークの場合に、 ベンチマーク結果を比較するには、3つの一般的な方法があります:
- 統計的継続ベンチマーク
- ベンチマーク結果を長期間追跡してベースラインを作成する
- このベースラインを統計的しきい値と組み合わせて、統計的境界を作成する
- この統計的境界と新しい結果を比較して、パフォーマンスの退行を検出する
- 相対的継続ベンチマーク
- 現在のベースラインコードのためのベンチマークを実行する
- コードを新しいバージョンに切り替える
- パーセンテージしきい値を用いてベースラインコードの境界を作成する
- 新しいバージョンのコードのためのベンチマークを実行する
- 新しいバージョンのコード結果とベースラインコード結果を比較し、パフォーマンスの退行を検出する
- 変化点検出
- 定期的に新しいバージョンのコードのためのベンチマークを実行する
- 変化点検出アルゴリズムを使用してパフォーマンスの退行を検出する
- パフォーマンスの退行を引き起こしたコミットを見つけるためにバイセクトする
統計的連続ベンチマーク
クイックスタートおよびDockerセルフホストチュートリアルの続きとして、
claimedプロジェクトに統計的連続ベンチマークを追加しましょう。
🐰 続行する前に APIトークンを作成して
BENCHER_API_TOKEN環境変数として設定したことを確認してください!
これで、CIでベンチマークを実行する準備が整いました。 すべてのCI環境は少しずつ異なるため、次の例は実用性よりも説明的なものになっています。 より具体的な例については、GitHub Actionsでの連続ベンチマークおよび GitLab CI/CDでの連続ベンチマークを参照してください。
まず、CIでの変更ごとにmainブランチの履歴ベースラインを作成および維持する必要があります:
bencher run \--project project-abc4567-wxyz123456789 \--branch main \--testbed ci-runner \--threshold-measure latency \--threshold-test t_test \--threshold-max-sample-size 64 \--threshold-upper-boundary 0.99 \--thresholds-reset \--err \--adapter json \bencher mockbencher runCLIサブコマンドを使用して、mainブランチのベンチマークを実行します。 詳細についてはbencher run CLIサブコマンドを参照してください。 (例:bencher run)--projectオプションをプロジェクトslugに設定します。 詳細についてはプロジェクトオプションを参照してください。 (例:--project project-abc4567-wxyz123456789)--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 \--project project-abc4567-wxyz123456789 \--branch feature-branch \--start-point main \--start-point-hash 32aea434d751648726097ed3ac760b57107edd8b \--start-point-clone-thresholds \--start-point-reset \--testbed ci-runner \--err \--adapter json \bencher mockbencher runCLIサブコマンドを使用して、feature-branchブランチのベンチマークを実行します。 詳細についてはbencher run CLIサブコマンドを参照してください。 (例:bencher run)--projectオプションをプロジェクトslugに設定します。 詳細についてはプロジェクトオプションを参照してください。 (例:--project project-abc4567-wxyz123456789)--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 自己ホストチュートリアルから引き継いで、claimedプロジェクトに相対連続ベンチマークを追加してみましょう。
🐰 続ける前に、 APIトークンを作成して、
BENCHER_API_TOKEN環境変数として設定します !
相対連続ベンチマークは、コードの2つのバージョンを並べて比較します。
これは、利用可能なリソースが実行ごとに大きく変動する可能性がある、ノイズの多いCI/CD環境で役立つことがあります。
この例では、mainブランチでの実行結果と、適切に命名されたfeature-branchという機能ブランチでの結果を比較します。
すべてのCI環境は少しずつ異なるため、以下の例は実際的というよりも説明的なものです。
より具体的な例については、GitHub Actionsで連続ベンチマークとGitLab CI/CDで連続ベンチマークを参照してください。
まず、CIでgitを使用してmainブランチをチェックアウトする必要があります:
git checkout main次に、CIでmainブランチのベンチマークを実行する必要があります:
bencher run \--project project-abc4567-wxyz123456789 \--branch main \--start-point-reset \--testbed ci-runner \--adapter json \bencher mockbencher runCLIサブコマンドを使用してmainブランチのベンチマークを実行します。 詳細な情報はbencher runCLIサブコマンドを参照してください。 (例:bencher run)--projectオプションをプロジェクトスラッグに設定します。 詳細は--projectドキュメントをご覧ください。 (例:--project project-abc4567-wxyz123456789)--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ブランチをチェックアウトする必要があります:
git checkout feature-branch最後に、CIでfeature-branchのベンチマークを実行する準備が整いました:
bencher run \--project project-abc4567-wxyz123456789 \--branch feature-branch \--start-point main \--start-point-reset \--testbed ci-runner \--threshold-measure latency \--threshold-test percentage \--threshold-upper-boundary 0.25 \--thresholds-reset \--err \--adapter json \bencher mockbencher runCLIサブコマンドを使用してfeature-branchベンチマークを実行します。 詳細な情報はbencher runCLIサブコマンドを参照してください。 (例:bencher run)--projectオプションをプロジェクトスラッグに設定します。 詳細は--projectドキュメントをご覧ください。 (例:--project project-abc4567-wxyz123456789)--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でベンチマークを追跡する方法を学びました! 🎉