Google Benchmark, как вызвать код только один раз?

У меня есть фрагмент кода, который мне нужно протестировать, состоящий из 2 частей, сначала состояние нужно установить ровно один раз, затем мне нужно фактически протестировать функцию.

Мой код выглядит так:

static void BM_LoopTime(benchmark::State& state) 
{
    MasterEngine engine;
    for (auto _ : state)
    {
        engine.LoopOnce();
    }
}
BENCHMARK(BM_LoopTime);

В моем выводе я получаю:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Pointer already set                                                             
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

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

Вызов этого кода несколько раз является неопределенным поведением в моей реализации. Как я могу вызвать инициализацию объекта ровно один раз, а затем сказать ей вызвать цикл?


person Makogan    schedule 28.05.2020    source источник
comment
Может быть, вы хотите сделать MasterEngine одноэлементным объектом в своем проекте? Вы можете просто держать флаг, указывающий, был ли объект уже создан. если нет, создайте его. Затем вызовите LoopOnce.   -  person Erix    schedule 28.05.2020
comment
Синглтоны имеют глобальную область видимости, и это основная причина, по которой я не определяю их как синглтоны.   -  person Makogan    schedule 28.05.2020
comment
В этом случае наличие указателя на MasterEngine в глобальной области видимости, вероятно, будет правильным решением. Что-то вроде: static MasterEngine* engine() { static MasterEngine eng; return ŋ } хорошо подойдет для тестов. По сути, это то, что вы делаете с приборами в своем ответе ниже.   -  person dma    schedule 01.06.2020
comment
@dma Да, но в идеале я не хочу переделывать свой код только для того, чтобы заставить его работать с библиотекой эталонного тестирования. Я стараюсь избегать чего-то глобального, насколько это возможно.   -  person Makogan    schedule 02.06.2020


Ответы (1)


Это обходной путь, который я нашел достаточно хорошим для моего варианта использования, но я все еще ищу лучшие решения:

class MyFixture : public benchmark::Fixture 
{
public:
    std::unique_ptr<MasterEngine> engine;

    void SetUp(const ::benchmark::State& state) 
    {
        if(engine.get() == nullptr)
            engine = std::make_unique<MasterEngine>();
    }

    void TearDown(const ::benchmark::State& state) 
    {
    }
};
person Makogan    schedule 28.05.2020