Google Benchmark Custom Setup и метод сноса - PullRequest
0 голосов
/ 11 октября 2019

Я использую библиотеку benchmark для сравнения некоторых кодов. Я хочу вызвать метод настройки перед тем, как вызывать реальный тестовый код один раз, а не повторять его каждый раз для нескольких вызовов тестовых методов. Например:

static void BM_SomeFunction(benchmark::State& state) {
  // Perform setup here
  for (auto _ : state) {
    // This code gets timed
  }
}

Как мы видим, код установки будетздесь вызывается несколько раз, для указанного диапазона. Я взглянул на тесты приборов. Но мой вопрос: можно ли это сделать, не используя тесты приборов? И если да, то как мы можем это сделать?

1 Ответ

2 голосов
/ 11 октября 2019

Насколько я помню, функция вызывается несколько раз, поскольку benchmark динамически решает, сколько раз необходимо выполнить тест для получения надежных результатов. Если вы не хотите использовать приборы, есть несколько обходных путей. Вы можете использовать глобальный или статический член класса bool, чтобы проверить, была ли уже вызвана функция установки (не забудьте установить ее после запуска процедуры установки). Другая возможность - использовать Singleton, который вызывает метод установки в своем ctor:

class Setup
{
    Setup()
    {
        // call your setup function
        std::cout << "singleton ctor called only once in the whole program" << std::endl;
    }

public:
    static void PerformSetup()
    {
        static Setup setup;
    }
};

static void BM_SomeFunction(benchmark::State& state) {
  Setup::PerformSetup()
  for (auto _ : state) {
    // ...
  }
}

Однако приборы довольно просты в использовании и созданы для таких случаев использования.

Определите класс прибора, который наследуется от benchmark::Fixture:

class MyFixture : public benchmark::Fixture
{
public:
    // add members as needed

    MyFixture()
    {
        std::cout << "Ctor only called once per fixture testcase hat uses it" << std::endl;
        // call whatever setup functions you need in the fixtures ctor 
    }
};

Затем используйте макрос BENCHMARK_F для использования вашего прибора в тесте.

BENCHMARK_F(MyFixture, TestcaseName)(benchmark::State& state)
{
    std::cout << "Benchmark function called more than once" << std::endl;
    for (auto _ : state)
    {
        //run your benchmark
    }
}

Однако, если вы используете прибор в нескольких тестах, ctor будет вызываться несколько раз. Если вам действительно нужно, чтобы определенная функция настройки вызывалась только один раз в течение всего теста, вы можете использовать Singleton или static bool, чтобы обойти это, как описано ранее. Может быть, benchmark также имеет встроенное решение для этого, но я его не знаю.


Альтернатива Singleton

Если вы неКак и в случае синглтон-класса, вы также можете использовать глобальную функцию, подобную этой:

void Setup()
{
    static bool callSetup = true;
    if (callSetup)
    {
        // Call your setup function
    }
    callSetup = false;
}

Greetings

...