C ++のパフォーマンステストツール:ベンチマークエントリ(B)をグーグル

前の投稿 Googleのベンチマークを使用して我々の予備の経験では、この記事では、我々は一般的な方法のGoogleのベンチマークの理解を促進します。

引用

例をテストするためにパラメータを渡します

我々は例をテストする前にのみ受け入れbenchmark::State&、我々はそれをテストするための追加のパラメータを渡す必要がある場合は、型のパラメータを?

私たちはキューを実装する必要がある場合たとえば、リストと2つの実装オプションリンクリングバッファが存在し、そして今、私たちは、さまざまな状況での二つのプログラムのパフォーマンスをテストします:

// 必要的数据结构
#include "ring.h"
#include "linked_ring.h"

// ring buffer的测试
static void bench_array_ring_insert_int_10(benchmark::State& state)
{
    auto ring = ArrayRing<int>(10);
    for (auto _: state) {
        for (int i = 1; i <= 10; ++i) {
            ring.insert(i);
        }
        state.PauseTiming(); // 暂停计时
        ring.clear();
        state.ResumeTiming(); // 恢复计时
    }
}
BENCHMARK(bench_array_ring_insert_int_10);

// linked list的测试
static void bench_linked_queue_insert_int_10(benchmark::State &state)
{
    auto ring = LinkedRing<int>{};
    for (auto _:state) {
        for (int i = 0; i < 10; ++i) {
            ring.insert(i);
        }
        state.PauseTiming();
        ring.clear();
        state.ResumeTiming();
    }
}
BENCHMARK(bench_linked_queue_insert_int_10);

// 还有针对删除的测试,以及针对string的测试,都是高度重复的代码,这里不再罗列

明らかに、任意の区別なしに挿入するデータの種類と量を試験するために、上記試験に加えて、多数のパラメータを渡すことによって制御することができればより少ない反復コードを書くことができます。

時間の無駄であり、多くの場合、あなたは愚かな何かをやっている意味が重複コードを記述し、Googleのエンジニアは確かにそれに気づいているだろう。テストは受け入れることができますが、benchmark::State&型のパラメータを、私たちは状態オブジェクトに引数を渡し、そのテストケースに取得することができます:

static void bench_array_ring_insert_int(benchmark::State& state)
{
    auto length = state.range(0);
    auto ring = ArrayRing<int>(length);
    for (auto _: state) {
        for (int i = 1; i <= length; ++i) {
            ring.insert(i);
        }
        state.PauseTiming();
        ring.clear();
        state.ResumeTiming();
    }
}
BENCHMARK(bench_array_ring_insert_int)->Arg(10);

上記の例では、パラメータを転送して取得する方法を示しています。

  1. 使用渡すパラメータBENCHMARK生成対象マクロブロックArg
  2. オブジェクトに渡されたパラメータは、内部状態にすることにより、記憶されたrange取得方法、パラメーター0に対応する第一パラメータ、必要なパラメータへの着信であります

Arg方法は一つだけで複数のパラメータを渡すしたい場合は、パラメータを渡すことができますか?また、非常に簡単です:

static void bench_array_ring_insert_int(benchmark::State& state)
{
    auto ring = ArrayRing<int>(state.range(0));
    for (auto _: state) {
        for (int i = 1; i <= state.range(1); ++i) {
            ring.insert(i);
        }
        state.PauseTiming();
        ring.clear();
        state.ResumeTiming();
    }
}
BENCHMARK(bench_array_ring_insert_int)->Args({10, 10});

ない実用的な意義上記の例では、単に複数のパラメータを渡す方法を示すために、Args方法は、ベクトルオブジェクトを受け付けるので、我々は++ 11cを使用することができるブレースを提供する初期化コードのパラメータは依然としてを介して取得簡素化state.range、メソッドに渡された1つの対応します二番目のパラメータ。

それはあなたが追加のパラメータの他のタイプを使用したい場合は、あなたが他のいくつかの方法を見つける必要がある、我々は唯一の整数パラメータが渡され受け入れることができ、注目に値します。

テストケース同様の単純化を複数生成します

あなたが書くかもしれないパラメータを渡す方法を知った後、重複したコードを書くことなく、より多くのテストケースを生成するために、例をテストするためにパラメータを渡すの究極の目標:

static void bench_array_ring_insert_int(benchmark::State& state)
{
    auto length = state.range(0);
    auto ring = ArrayRing<int>(length);
    for (auto _: state) {
        for (int i = 1; i <= length; ++i) {
            ring.insert(i);
        }
        state.PauseTiming();
        ring.clear();
        state.ResumeTiming();
    }
}
// 下面我们生成测试插入10,100,1000次的测试用例
BENCHMARK(bench_array_ring_insert_int)->Arg(10);
BENCHMARK(bench_array_ring_insert_int)->Arg(100);
BENCHMARK(bench_array_ring_insert_int)->Arg(1000);

ここでは、3つの例を生成し、次のような結果が生成されます。

引数を渡します

それは、良い仕事をしていません見えますか?

はい、結果は正しいですが、我々はそれが前に言った覚えている- 重複したコードを記述しないでくださいはい、私たちは手動でユースケースを生成する上で書かれた、重複を避けるように見えました。

幸い、ArgおよびArgsテストケースのパラメータを、我々は生成するために登録するために使用する用例名/参数新しいテストケースを、およびへのポインタを返すBENCHMARKだけにして、私たちはさまざまなパラメータをテストするよりも多くを生成する場合は、他の言葉で、ポインタマクロオブジェクトを生成し、チェーンは、呼び出す必要があるArgArgs次のことができます。

BENCHMARK(bench_array_ring_insert_int)->Arg(10)->Arg(100)->Arg(1000);

結果及び上記と同じ。

しかし、これが最適なソリューションではありません、我々はより多くのユースケースは、作業の重複をしなければならなかっただろう必要がある場合はargはまだ、メソッドを繰り返し呼ばれます。

この点では、Googleのベンチマークはまた、溶液があります。我々は、使用することができRange、自動的にパラメータの範囲を生成する方法を。

プロトタイプの範囲を見てみましょう:

BENCHMAEK(func)->Range(int64_t start, int64_t limit);

スタートパラメータ範囲の開始値、範囲の終了を示す限界値を示し、範囲は閉区間_ _のために作られています。

私たちは、このコードを書き換える場合でも、偽のテスト結果を取得する予定です。

BENCHMARK(bench_array_ring_insert_int)->Range(10, 1000);

エラー

なぜこれがそうですか?デフォルトに加えて、一方の基板(ベース)、デフォルトでベース8の力になり、残りのパラメータの途中で、起動して、制限範囲からだので、我々は、正方形や立方体8ある64と512を、表示されます。

この動作は、使用している限り基板をリセットすることができるよう、また、非常にシンプルで変更するRangeMultiplier方法を:

BENCHMARK(bench_array_ring_insert_int)->RangeMultiplier(10)->Range(10, 1000);

結果は今、これまでのように復元されます。

範囲は、複数のパラメータケースを用いて処理することができます。

BENCHMARK(func)->RangeMultiplier(10)->Ranges({{10, 1000}, {128, 256}});

第2のパラメータの可能な値の第2の所定範囲(この範囲ではないことに注意)を通過しながら、最初のパラメータの指定された範囲の第1の範囲は、テストに合格しました。

次のコードと同等です:

BENCHMARK(func)->Args({10, 128})
               ->Args({100, 128})
               ->Args({1000, 128})
               ->Args({10, 256})
               ->Args({100, 256})
               ->Args({1000, 256})

実際直積背後からなるパラメータで生成された最初の範囲パラメータの内容で指定されました。

パラメータジェネレータを使用します

私は、より複雑なパラメータをカスタマイズしたい場合は、それを否定しませんでしたか?その後、カスタムパラメータジェネレータaを実装する必要があります。

次のように署名パラメータジェネレータ

void CustomArguments(benchmark::internal::Benchmark* b);

当社は、発電機のパラメータを計算し、次に呼び出すbenchmark::internal::BenchmarkArgまたはArgsのは2にパラメータとして渡さとして、オブジェクトのメソッドを。

その後、我々は、使用しApply、発電機のテストケースに適用する方法を:

BENCHMARK(func)->Apply(CustomArguments);

実際には、このプロセスの原理は複雑ではありません、私は簡単な説明を行います。

  1. BENCHMARKこれは、マクロ生成されbenchmark::internal::Benchmarkたオブジェクトと、それへのポインタを返します
  2. するにはbenchmark::internal::BenchmarkArgのオブジェクトなどのArgs必要なパラメータを渡します
  3. Applyこの方法の適用は、パラメータ自体に機能します
  4. 当社は、ジェネレータを使用benchmark::internal::Benchmarkこの時刻b実際には、我々のテストケースでは、ポインタオブジェクトArgsのB通過パラメータなどを

これまでのところBuilderは上記の結論に由来し、もちろん、それがどのように動作するか、すでに明らかである、我々はより多くのことを行うために適用させることができます。

具体的な使用下記をご覧適用します。

// 这次我们生成100,200,...,1000的测试用例,用range是无法生成这些参数的
static void custom_args(benchmark::internal::Benchmark* b)
{
    for (int i = 100; i <= 1000; i += 100) {
        b->Arg(i);
    }
}

BENCHMARK(bench_array_ring_insert_int)->RangeMultiplier(10)->Apply(custom_args);

テスト結果のカスタムパラメータ:

custom_args

以上導入されたすべてのケースをテストするためにパラメータを渡すのこれまでの方法。

次に、私は非常に私たちの不必要な作業を削減するテンプレートを使用して、唯一の方法と同様の方法でテストケースであることをテストのさまざまな種類のコードの重複の一部を解決することができるパラメータを渡し、テストケースのテンプレートを作成する方法を説明します。

おすすめ

転載: www.cnblogs.com/apocelipes/p/11067594.html