Google Benchmarkを使用してC++コードをベンチマークする方法

Everett Pompeii

Everett Pompeii


ベンチマークとは?

ベンチマークとは、コードの性能をテストして、その処理速度(レイテンシ)や処理量(スループット)を確認することを指します。 この、ソフトウェア開発において見落とされがちなステップは、高速で高性能なコードを作成および維持するために重要です。 ベンチマークは開発者がコードがさまざまな作業負荷や条件下でどれだけうまく動作するかを理解するために必要な指標を提供します。 機能のリグレッションを防ぐためにユニットテストや統合テストを書くのと同様に、 パフォーマンスのリグレッションを防ぐためにもベンチマークを書くべきです。 パフォーマンスのバグもバグです!

C++でFizzBuzzを書く

ベンチマークを書くためには、ベンチマークするソースコードが必要です。 まず、非常にシンプルなプログラム、 FizzBuzz を書いてみましょう。

FizzBuzzのルールは以下の通りです:

1から100までの整数を印刷するプログラムを書く:

  • 三の倍数の場合は、Fizzを印刷します
  • 五の倍数の場合は、Buzzを印刷します
  • 三と五の両方の倍数の場合は、FizzBuzzを印刷します
  • それ以外の場合は、数字を印刷します

FizzBuzzは多くの方法で書くことができます。 なので、私のお気に入りの方法で進めることにしましょう。

#include <iostream>
int main()
{
for (int i = 1; i <= 100; i++)
{
if ((i % 15) == 0)
std::cout << "FizzBuzz\n";
else if ((i % 3) == 0)
std::cout << "Fizz\n";
else if ((i % 5) == 0)
std::cout << "Buzz\n";
else
std::cout << i << "\n";
}
return 0;
}
  • 1から100まで繰り返し、各繰り返し後にインクリメントします。
  • 各数値について、剰余(割り算の余り)を計算します。
  • 余りが0の場合、その数は指定された因数の倍数です:
    • 15の余りが0の場合は、FizzBuzzを出力します。
    • 3の余りが0の場合は、Fizzを出力します。
    • 5の余りが0の場合は、Buzzを出力します。
  • それ以外の場合は、その数をそのまま出力します。

手順を追って従う

このステップバイステップのチュートリアルに従うためには、gitをインストールし、cmakeをインストールし、またGNUコンパイラコレクション(GCC)のg++インストールする必要があります。

🐰 この投稿のソースコードはGitHubで入手可能です。

game.cppという名前のC++ファイルを作成し、その内容を上述のFizzBuzz実装に設定します。

g++を使用してgameという名前の実行可能ファイルをビルドし、それを実行します。 出力は以下のようになるはずです:

$ g++ -std=c++11 game.cpp -o game && ./game
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
...
97
98
Fizz
Buzz

🐰 よっしゃ!コーディング面接を突破していますね!

さらに進む前に、マイクロベンチマークとマクロベンチマークの違いを議論することが重要です。

マイクロベンチマークとマクロベンチマーク

ソフトウェアベンチマークには、マイクロベンチマークとマクロベンチマークの2つの主要なカテゴリーがあります。 マイクロベンチマークは、ユニットテストと同様のレベルで動作します。 例えば、単一の数値に対してFizzBuzz、またはFizzBuzzを決定する関数のベンチマークはマイクロベンチマークになります。 一方、マクロベンチマークは、統合テストと同様のレベルで動作します。 例えば、1から100までの全ゲームをプレイするFizzBuzzの関数のベンチマークは、マクロベンチマークになります。

一般的に、可能な限り低い抽象レベルでテストすることが最善です。 ベンチマークの場合、これにより保守性が向上し、測定値のノイズを減らすことに役立ちます。 しかし、エンドツーエンドテストがシステム全体が予想通りに組み合わさるかのサニチェックに非常に役立つように、 マクロベンチマークがあると、ソフトウェアを通る重要なパスが性能を維持するために非常に役立ちます。

C++におけるベンチマーク

C++でのベンチマークの一般的な選択肢は以下の2つです: Google BenchmarkCatch2

Google Benchmarkは、C++用の堅牢で多用途なベンチマークライブラリであり、開発者が自分のコードの性能を高精度で測定できるようにします。その主要な利点の一つは、既存のプロジェクト、特にすでにGoogleTestを使用しているプロジェクトへの統合が容易であることです。Google Benchmarkは、CPU時間、実時間、メモリ使用量の測定能力を含む詳細な性能指標を提供します。簡単な関数ベンチマークから複雑なパラメータ化テストまで、広範囲のベンチマークシナリオをサポートしています。

Catch2は、C++用のモダンなヘッダーオンリーのテストフレームワークであり、テストの記述と実行のプロセスを簡素化します。その主要な利点の一つは、直感的で表現力豊かな構文であり、開発者が迅速かつ明確にテストを書くことができることです。Catch2は、単体テスト、統合テスト、振る舞い駆動開発(BDD)スタイルのテスト、および基本的なマイクロベンチマーク機能を含む広範囲のテストタイプをサポートしています。

両方ともBencherによってサポートされています。 では、なぜGoogle Benchmarkを選ぶのか? Google BenchmarkはGoogleTestとシームレスに統合され、 これはC++エコシステムで事実上の標準的なユニットテストハーネスです。 すでにGoogleTestを使用している場合、コードのレイテンシをベンチマークするにはGoogle Benchmarkを使用することをお勧めします。 つまり、Google Benchmarkは経過時間を計測するのに優れています。

FizzBuzzのリファクタリング

FizzBuzzアプリケーションをテストするためには、ロジックをプログラムのmain関数から分離する必要があります。ベンチマークハーネスはmain関数をベンチマークできません。これを実現するために、いくつかの変更を行う必要があります。

FizzBuzzのロジックを、新しいファイルplay_game.cpp内のいくつかの関数にリファクタリングしましょう:

play_game.cpp
#include <iostream>
#include <string>
std::string fizz_buzz(int n) {
if (n % 15 == 0) {
return "FizzBuzz";
} else if (n % 3 == 0) {
return "Fizz";
} else if (n % 5 == 0) {
return "Buzz";
} else {
return std::to_string(n);
}
}
void play_game(int n, bool should_print) {
std::string result = fizz_buzz(n);
if (should_print) {
std::cout << result << std::endl;
}
}
  • fizz_buzz: 整数nを受け取り、FizzBuzzFizzBuzz、または数値ロジックを実行して結果を文字列として返します。
  • play_game: 整数nを受け取り、その数を使ってfizz_buzzを呼び出し、should_printtrueの場合は結果を出力します。

次に、play_game.hという名前のヘッダーファイルを作成し、そこにplay_game関数の宣言を追加します:

play_game.h
#ifndef GAME_H
#define GAME_H
#include <string>
void play_game(int n, bool should_print);
#endif // GAME_H

次に、main関数をgame.cppで更新し、ヘッダーファイルからplay_game関数定義を使用します:

game.cpp
#include "play_game.h"
int main()
{
for (int i = 1; i <= 100; i++)
{
play_game(i, true);
}
}

プログラムのmain関数は、1から100までの数値を反復処理し、各数値に対してplay_gameを呼び出し、should_printtrueに設定します。

FizzBuzzのベンチマーク

コードをベンチマークするために、まずGoogle Benchmarkをインストールする必要があります。

ライブラリをクローンします。

$ git clone https://github.com/google/benchmark.git

クローンしたばかりのディレクトリに入ります。

$ cd benchmark

cmakeを使って、ビルド出力を配置するためのビルドディレクトリを作成します。

$ cmake -E make_directory "build"

ビルドシステムファイルを生成し、必要な依存関係をダウンロードするためにcmakeを使用します。

$ cmake -E chdir "build" cmake -DBENCHMARK_DOWNLOAD_DEPENDENCIES=on -DCMAKE_BUILD_TYPE=Release ../

最後に、ライブラリをビルドします。

$ cmake --build "build" --config Release

親ディレクトリに戻ります。

cd ..

次に、新しいファイルbenchmark_game.cppを作成します。

benchmark_game.cpp
#include "play_game.h"
#include <benchmark/benchmark.h>
#include <iostream>
static void BENCHMARK_game(benchmark::State &state)
{
for (auto _ : state)
{
for (int i = 1; i <= 100; i++)
{
play_game(i, false);
}
}
}
BENCHMARK(BENCHMARK_game);
BENCHMARK_MAIN();
  • play_game.hから関数定義をインポートします。
  • Google benchmarkライブラリのヘッダをインポートします。
  • benchmark::Stateへの参照を受け取るBENCHMARK_game関数を作成します。
  • benchmark::Stateオブジェクトを反復処理します。
  • 各イテレーションごとに、1から100までを含めて反復処理します。
    • 現在の数値とshould_printfalseに設定してplay_gameを呼び出します。
  • BENCHMARK_game関数をBENCHMARKランナーに渡します。
  • BENCHMARK_MAINを使用してベンチマークを実行します。

これでコードをベンチマークする準備が整いました。

$ g++ -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread play_game.cpp benchmark_game.cpp -o benchmark_game && ./benchmark_game
2023-10-16T14:00:00-04:00
Running ./benchmark_game
Run on (8 X 24 MHz CPU s)
CPU Caches:
L1 Data 64 KiB
L1 Instruction 128 KiB
L2 Unified 4096 KiB (x8)
Load Average: 5.55, 4.62, 4.69
---------------------------------------------------------
Benchmark Time CPU Iterations
---------------------------------------------------------
BENCHMARK_game 1698 ns 1688 ns 419979

🐰 レタスが跳ねる!初めてのベンチマークメトリクスを取得しました!

最後に、我々の疲れた開発者たちの頭を休めることができます… 冗談です、ユーザーは新しい機能を求めています!

C++でFizzBuzzFibonacciを作成する

私たちの主要業績評価指標(KPI)が低下しているので、プロダクトマネージャー(PM)が新機能を追加したいと考えています。多くのブレインストーミングと多数のユーザーインタビューの結果、古き良きFizzBuzzでは不十分であると決定されました。最近の子供たちは新しいゲーム、FizzBuzzFibonacciを求めています。

FizzBuzzFibonacciの規則は以下の通りです:

1から100までの整数を印刷するプログラムを書く:

  • 3の倍数にはFizzを印刷
  • 5の倍数にはBuzzを印刷
  • 三と五の倍数にはFizzBuzzを印刷
  • フィボナッチ数列の一部である数には、Fibonacciだけを印刷
  • それ以外のすべてには、その数値を印刷

フィボナッチ数列は、それぞれの数が前の二つの数の和である数列です。 例えば、01から始めると、フィボナッチ数列の次の数は1になります。 そして、それに続く数は:2, 3, 5, 8 と続きます。 フィボナッチ数列の一部である数はフィボナッチ数として知られています。なので、フィボナッチ数を検出する関数を書く必要があります。

フィボナッチ数列を書く方法はたくさんありますし、同様にフィボナッチ数を検出する方法もたくさんあります。 だから私のお気に入りを選びます:

play_game.cpp
bool is_fibonacci_number(int n)
{
for (int i = 0; i <= n; ++i)
{
int previous = 0, current = 1;
while (current < i)
{
int next = previous + current;
previous = current;
current = next;
}
if (current == n)
{
return true;
}
}
return false;
}
  • 整数を受け取り、真偽値を返す関数 is_fibonacci_number を作成します。
  • すべての数値 0 から与えられた数値 n まで(含む)を反復します。
  • フィボナッチ数列を 01previouscurrent の数として始めます。
  • current の数が現在の反復 i より小さい間、繰り返します。
  • previouscurrent の数を加算して next の数を得ます。
  • previous の数を current の数に更新します。
  • current の数を next の数に更新します。
  • current が指定された数 n 以上になったら、ループを抜けます。
  • current の数が指定された数 n と等しいか確認し、もしそうなら true を返します。
  • そうでない場合は、false を返します。

次に、fizz_buzz 関数を更新する必要があります:

play_game.cpp
std::string fizz_buzz_fibonacci(int n)
{
if (is_fibonacci_number(n))
{
return "Fibonacci";
}
else if (n % 15 == 0)
{
return "FizzBuzz";
}
else if (n % 3 == 0)
{
return "Fizz";
}
else if (n % 5 == 0)
{
return "Buzz";
}
else
{
return std::to_string(n);
}
}
  • fizz_buzz 関数をよりわかりやすくするために fizz_buzz_fibonacci に名前を変更します。
  • is_fibonacci_number のヘルパー関数を呼び出します。
  • is_fibonacci_number の結果が true であれば、Fibonacci を返します。
  • is_fibonacci_number の結果が false であれば、同様に FizzBuzzFizzBuzz、または数値ロジックを実行しその結果を返します。

fizz_buzzfizz_buzz_fibonacci に名前を変更したため、play_game 関数を更新する必要もあります。

play_game.cpp
void play_game(int n, bool should_print) {
std::string result = fizz_buzz_fibonacci(n);
if (should_print) {
std::cout << result << std::endl;
}
}

私たちの main 関数と BENCHMARK_game 関数はそのままで問題ありません。

フィズバズフィボナッチのベンチマーク

ベンチマークを再度実行できます:

$ g++ -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread play_game.cpp benchmark_game.cpp -o benchmark_game && ./benchmark_game
2023-10-16T15:00:00-04:00
Running ./benchmark_game
Run on (8 X 24 MHz CPU s)
CPU Caches:
L1 Data 64 KiB
L1 Instruction 128 KiB
L2 Unified 4096 KiB (x8)
Load Average: 4.34, 5.75, 4.71
---------------------------------------------------------
Benchmark Time CPU Iterations
---------------------------------------------------------
BENCHMARK_game 56190 ns 56054 ns 12280

ターミナルの履歴を戻ってスクロールすると、フィズバズゲームとフィズバズフィボナッチゲームのパフォーマンスをざっと比較できます: 1698 ns vs 56190 ns。 あなたの数値は私のとは少し異なるでしょう。 しかし、両ゲームの違いはおそらく50倍程度でしょう。 それは素晴らしいことです!特に、ゲームに派手な響きのある フィボナッチ という機能を追加するのに。 子供たちはそれを気に入るでしょう!

C++ での FizzBuzzFibonacci の拡張

私たちのゲームは大ヒットしています!子供たちは本当に FizzBuzzFibonacci を楽しんでいます。 そのため、経営陣から続編を求められるほどです。 しかし、これは現代の世界です。我々は1回きりの購入ではなく、毎年の定期収益(ARR)が必要です! 我々の新しいビジョンは、ゲームがオープンエンドであることです。1100 の間の制約にとらわれることはありません(たとえそれが包括的であっても)。 いいえ、我々は新たなフロンティアへと進んでいます!

Open World FizzBuzzFibonacciのルールは次のとおりです:

以下のように、任意の 正の整数を受け取って印刷するプログラムを書きます:

  • 3の倍数の場合、Fizzを出力する
  • 5の倍数の場合、Buzzを出力する
  • 3と5の両方の倍数の場合、FizzBuzzを出力する
  • フィボナッチ数列の一部である数値は、Fibonacciのみを出力する
  • それ以外の場合は、数値を出力する

ゲームをどの数字でもプレイできるようにするためには、コマンドライン引数を受け入れなければなりません。 main 関数を以下のように更新します:

game.cpp
#include "play_game.h"
#include <iostream>
#include <cstdlib>
int main(int argc, char *argv[])
{
if (argc > 1 && std::isdigit(argv[1][0]))
{
int i = std::atoi(argv[1]);
play_game(i, true);
}
else
{
std::cout << "Please, enter a positive integer to play..." << std::endl;
}
return 0;
}
  • argcargv を取るように main 関数を更新します。
  • ゲームに渡された最初の引数を取得し、それが数字であるかどうかを確認します。
    • もしそうであれば、最初の引数を整数 i としてパースします。
    • 新しくパースした整数 i でゲームをプレイします。
  • パースに失敗するか、引数が渡されていない場合、デフォルトで有効な入力を促します。

これで、どの数字でもゲームをプレイできるようになります! game 実行ファイルを再コンパイルし、ゲームをプレイするために整数を続けて実行します:

$ g++ -std=c++11 game.cpp play_game.cpp -o game
$ ./game 9
Fizz
$ ./game 10
Buzz
$ ./game 13
Fibonacci

無効な数字を省略または提供した場合:

$ ./game
Please, enter a positive integer to play...
$ ./game bad
Please, enter a positive integer to play...

わあ、これはかなり徹底したテストでした!CI が通過しました。上司たちは大喜びです。 それではリリースしましょう!🚀

終わり


SpongeBob SquarePants Three Weeks Later
This is Fine meme

🐰 … あなたのキャリアの終わりかもしれない?


冗談じゃない!全てが炎上しています!🔥

最初は全てうまく行っているように見えました。 しかし、土曜日の午前2時07分に僕のページャーが鳴った:

📟 あなたのゲームが炎上しています!🔥

ベッドから飛び起き、何が起こっているのかを理解しようとしました。 ログを検索しようと試みましたが、何もかもがクラッシュし続けていて困難でした。 最終的に、問題を見つけました。その子供たち! 彼らは私たちのゲームが大好きで、最大百万までプレイしていました! ひらめきの一瞬で、新たに2つのベンチマークを追加しました:

benchmark_game.cpp
static void BENCHMARK_game_100(benchmark::State &state)
{
for (auto _ : state)
{
play_game(100, false);
}
}
static void BENCHMARK_game_1_000_000(benchmark::State &state)
{
for (auto _ : state)
{
play_game(1000000, false);
}
}
BENCHMARK(BENCHMARK_game_100);
BENCHMARK(BENCHMARK_game_1_000_000);
  • 数字100(100)でゲームをプレイするためのマイクロベンチマークBENCHMARK_game_100
  • 数字1,000,000(1_000_000)でゲームをプレイするためのマイクロベンチマークBENCHMARK_game_1_000_000

私が実行したとき、次のようになりました:

$ g++ -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread play_game.cpp benchmark_game.cpp -o benchmark_game && ./benchmark_game
2023-11-04T03:00:00-04:00
Running ./benchmark_game
Run on (8 X 24 MHz CPU s)
CPU Caches:
L1 Data 64 KiB
L1 Instruction 128 KiB
L2 Unified 4096 KiB (x8)
Load Average: 4.98, 5.75, 4.96
-------------------------------------------------------------------
Benchmark Time CPU Iterations
-------------------------------------------------------------------
BENCHMARK_game 75547 ns 59280 ns 12560
BENCHMARK_game_100 1249 ns 1243 ns 564689

待ってください…待ってください…

BENCHMARK_game_1_000_000 110879642 ns 43628118 ns 17

なんと! 1,249 ns x 10,00012,490,000 nsのはずなのに110,879,642 ns 🤯 フィボナッチ数列のコードは機能的に正しいはずですが、どこかにパフォーマンスの問題があります。

C++でのFizzBuzzFibonacciを修正

is_fibonacci_number 関数をもう一度見てみましょう:

play_game.cpp
bool is_fibonacci_number(int n)
{
for (int i = 0; i <= n; ++i)
{
int previous = 0, current = 1;
while (current < i)
{
int next = previous + current;
previous = current;
current = next;
}
if (current == n)
{
return true;
}
}
return false;
}

パフォーマンスを考えてみると、不必要なループがひとつあることに気付きます。 for (int i = 0; i <= n; ++i) ループは完全に取り除いて、 current の値を指定された数(n)と比較するだけで済みます 🤦

play_game.cpp
bool is_fibonacci_number(int n)
{
int previous = 0, current = 1;
while (current < n)
{
int next = previous + current;
previous = current;
current = next;
}
return current == n;
}
  • is_fibonacci_number 関数を更新します。
  • 01 をそれぞれ previouscurrent の数字としてフィボナッチ数列を初期化します。
  • current の数が指定された数 n より小さい間、繰り返し処理を行います。
  • previouscurrent の数を足して next の数を得ます。
  • previous の数を current の数に更新します。
  • current の数を next の数に更新します。
  • current が指定された数 n 以上になったら、ループを終了します。
  • current の数が指定された数 n と等しいかどうかを確認し、その結果を返します。

それでは、もう一度これらのベンチマークを実行し、結果を見てみましょう:

$ g++ -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread play_game.cpp benchmark_game.cpp -o benchmark_game && ./benchmark_game
2023-11-04T05:00:00-04:00
Running ./benchmark_game
Run on (8 X 24 MHz CPU s)
CPU Caches:
L1 Data 64 KiB
L1 Instruction 128 KiB
L2 Unified 4096 KiB (x8)
Load Average: 4.69, 5.02, 4.78
-------------------------------------------------------------------
Benchmark Time CPU Iterations
-------------------------------------------------------------------
BENCHMARK_game 2914 ns 2913 ns 242382
BENCHMARK_game_100 34.4 ns 34.3 ns 20322076
BENCHMARK_game_1_000_000 61.6 ns 61.6 ns 11346874

おお、なんと! BENCHMARK_gameベンチマークは元のFizzBuzzに戻ってきましたね。 そのスコアが正確にはどのくらいだったのか思い出せませんが。 3週間も前のことで、私のターミナル履歴はそんなに遡れず、Google Benchmarkは結果を保存しません。 でも、近いと思います!

BENCHMARK_game_100ベンチマークは約50倍に減少して34.4 nsです。 そして、BENCHMARK_game_1_000_000ベンチマークは1,500,000倍以上の削減! 110,879,642 nsから61.6 nsに!

🐰 まあ、少なくともこの性能問題をプロダクションに持ち込む前に見つけたのは良かったですね…あ、そうだね。冗談はさておき…

CIでパフォーマンスの後退を捕捉する

私のちょっとしたパフォーマンスのバグが原因で我々のゲームが大量の否定的なレビューを受けたことに、エクゼクティブたちは不満を持っていました。 彼らは再びそれを起こさないようにと言い、どうすれば良いのか尋ねると、ただ再びやらないようにと言われるだけでした。 どうすればそれを管理することができるのでしょうか‽

幸運なことに、Bencherという素晴らしいオープンソースツールを見つけました。 超大盤振る舞いの無料枠があるので、私の個人的なプロジェクトではBencherクラウドをただ使うことができます。 そして、仕事では全てが私たちのプライベートクラウド内にある必要があるので、Bencher Self-Hostedを使い始めました。

Bencherには組み込みのアダプターがあり、 そのためCIに簡単に統合することができます。クイックスタートガイドをフォローした後、 私は私のベンチマークを実行し、それらをBencherで追跡することができます。

$ g++ -std=c++11 -isystem benchmark/include -Lbenchmark/build/src -lbenchmark -lpthread play_game.cpp benchmark_game.cpp -o benchmark_game
$ bencher run --adapter cpp_google "./benchmark_game --benchmark_format=json"
{
"context": {
"date": "2023-10-16T16:00:00-04:00",
"host_name": "bencher",
"executable": "./benchmark_game",
"num_cpus": 8,
"mhz_per_cpu": 24,
"cpu_scaling_enabled": false,
...
View results:
- BENCHMARK_game (Latency): https://bencher.dev/console/projects/game/perf?measures=52507e04-ffd9-4021-b141-7d4b9f1e9194&branches=3a27b3ce-225c-4076-af7c-75adbc34ef9a&testbeds=bc05ed88-74c1-430d-b96a-5394fdd18bb0&benchmarks=077449e5-5b45-4c00-bdfb-3a277413180d&start_time=1697224006000&end_time=1699816009000&upper_boundary=true
- BENCHMARK_game_100 (Latency): https://bencher.dev/console/projects/game/perf?measures=52507e04-ffd9-4021-b141-7d4b9f1e9194&branches=3a27b3ce-225c-4076-af7c-75adbc34ef9a&testbeds=bc05ed88-74c1-430d-b96a-5394fdd18bb0&benchmarks=96508869-4fa2-44ac-8e60-b635b83a17b7&start_time=1697224006000&end_time=1699816009000&upper_boundary=true
- BENCHMARK_game_1_000_000 (Latency): https://bencher.dev/console/projects/game/perf?measures=52507e04-ffd9-4021-b141-7d4b9f1e9194&branches=3a27b3ce-225c-4076-af7c-75adbc34ef9a&testbeds=bc05ed88-74c1-430d-b96a-5394fdd18bb0&benchmarks=ff014217-4570-42ea-8813-6ed0284500a4&start_time=1697224006000&end_time=1699816009000&upper_boundary=true

この素敵なウサギが私にくれた便利なタイムマシンを使って、私たちがずっとBencherを使っていたらどうなっていたかを時間を遡って再現しました。 最初にバギーなFizzBuzzFibonacciの実装をプッシュしたところを見ることができます。 私のプルリクエストに対するコメントとしてCIで直ちに失敗が出ました。 その同じ日に、私はその無駄な、余分なループを取り除くことでパフォーマンスのバグを修正しました。 火事はありません。ただ幸せなユーザーたちだけです。

Bencher: 連続ベンチマーキング

🐰 Bencher

Bencherは、連続ベンチマーキングツールのスイートです。 パフォーマンスの後退があなたのユーザーに影響を与えたことはありますか? Bencherなら、それが起こるのを防げた可能性があります。 Bencherは、パフォーマンスの低下を_productionに到達する_前に検出し、防止することを可能にします。

  • 実行: お気に入りのベンチマーキングツールを使用してベンチマークをローカルまたはCIで実行します。 bencher CLIは単にあなたの既存のベンチマークハーネスをラップし、その結果を保存します。
  • 追跡: ベンチマークの結果を時間と共に追跡します。ソースブランチ、テストベッド、測定基準に基づいてBencherのWebコンソールを使用して結果を監視、クエリ、グラフ化します。
  • キャッチ: CIでパフォーマンスの後退をキャッチします。Bencherは最先端のカスタマイズ可能な分析を使用して、パフォーマンスの後退がProductionに到達する前にそれを検出します。

機能の後退を防ぐためにユニットテストがCIで実行されるのと同じ理由で、Bencherを使用してCIでベンチマークを実行してパフォーマンスの後退を防ぐべきです。パフォーマンスのバグはバグです!

CIでパフォーマンスの回帰を捉えるのを開始してください - Bencher Cloudを無料で試す

🤖 このドキュメントは OpenAI GPT-4 によって自動的に生成されました。 正確ではない可能性があり、間違いが含まれている可能性があります。 エラーを見つけた場合は、GitHub で問題を開いてください。.