Приспособление бенчмарка Google: повторно использовать векторы в нескольких бенчмарках - PullRequest
1 голос
/ 09 марта 2020

Я хочу запустить несколько тестов с помощью библиотеки тестов Google после загрузки большого файла. Я использую следующий код для этой цели. Функция read_collection() загружает содержимое файла, а бенчмарк Build обрабатывает содержимое из coll.

#define COLLECTION 'w'

class BuildFixture : public ::benchmark::Fixture {
 public:
     std::unique_ptr<Collection> coll;

     BuildFixture() {
        cout << "Constructor\n";
        coll = std::make_unique<Collection>(Collection(COLLECTION));
        coll->read_collection();
     }

     ~BuildFixture() {
         cout << "Destroy collection\n";
         coll.reset();
     }
};

BENCHMARK_DEFINE_F(BuildFixture, Build1)(benchmark::State& state) {
    nrows = static_cast<size_t>(state.range(0));
    for (auto _ : state) {
       // Do something with coll and nrows
    }
}

BENCHMARK_DEFINE_F(BuildFixture, Build2)(benchmark::State& state) {
    nrows = static_cast<size_t>(state.range(0));
    for (auto _ : state) {
       // Something else with coll and nrows
    }
}



BENCHMARK_REGISTER_F(BuildFixture, Build1)->Arg(10);
BENCHMARK_REGISTER_F(BuildFixture, Build2)->Arg(20);

BENCHMARK_MAIN();

Когда я запускаю этот код, каждый бенчмарк с аргументами 10 и 20 выполняет конструктор (в общей сложности два раза), запускает тесты и затем вызывает деструкторы. Таким образом, выходные данные выглядят как

Constructor
Constructor
.. (benchmarking outputs)..
Destroy collection                                                                              
Destroy collection

В итоге это занимает слишком много времени для многократного чтения (одного и того же) файла, а также требует дополнительной памяти для хранения одних и тех же данных для нескольких тестов. Я также волнуюсь, будут ли результаты затронуты ошибками страницы. Поэтому у меня есть два вопроса:

  1. Есть ли способ избежать необходимости читать файл дважды, так как это сэкономило бы некоторое время выполнения (хотя это время не учитывается в тесте производительности).
  2. (Если нет) Как я могу реструктурировать несколько кодов тестов таким образом, чтобы каждый тест вызывал конструктор, выполнял тестирование, разрушал и затем переходил к следующему тесту? (без необходимости использовать несколько main функций, конечно)

Обновление 1

Тесты, которые мне нужно зарегистрировать, отличаются. Я не собираюсь передавать разные аргументы в один и тот же тест. Я обновил вопрос соответственно с Build1 и Build2.

1 Ответ

0 голосов
/ 13 марта 2020

Если вы определите свой собственный main, вы можете создать глобальную коллекцию и ссылаться на нее из каждого эталонного теста.

Однако вы также можете избежать этой проблемы, зарегистрировав эталонный тест только один раз:

BENCHMARK_REGISTER_F(BuildFixture, Build)->Arg(10)->Arg(20)
...