1

给定以下代码

#include <benchmark/benchmark.h>
#include <iostream>

static void BM_foo(benchmark::State& state) {
  std::cout << "Foo "<< std::endl;
  for (auto _: state) {
    std::cout <<  state.iterations()  << " In loop " <<std::endl;
  }
}

BENCHMARK(BM_foo);

BENCHMARK_MAIN();

我以为 std::cout << "Foo "<< std::endl; 只会执行一次,但在我的测试期间,它运行了 7 次。

所以我的问题是:

  1. 如何在基准测试之前只运行一次设置代码,例如“std::cout << "Foo "<< std::endl"?
  2. 当我使用“state.iterations()”时,我想一个一个地得到“1、2、3 ..”,但我却得到0。我怎样才能得到迭代器的seq数?

在我的真实案例中,我想在多线程场景中运行一些与存储引擎相关的代码。像这样的步骤:

  1. 打开与存储引擎的连接。让我们假设连接对象可以在不同的线程之间共享。
  2. 基于连接打开会话。让我们假设会话对象不能在线程之间共享。
  3. 运行许多 db_related 操作,这是我想要进行基准测试的唯一代码。
  4. 关闭会话,连接。

我有以下伪代码,但我认为它至少有 2 个问题。

DBConnection* conn; // global variables, so that each thread can run access it.

static void BM_db_insert(benchmark::State& state) {
  if (state.thread_index == 0) {
    # only let 1 thread to setup the DBConnections
    conn = openDBConn();
  }
  DBSession* session = conn.openSession();
  for (auto _ : state) {
    session.insertOp(id, ..); 
  }
  session.close();
  if (state.thread_index == 0) {
    conn.close();
  }
}

问题:

  1. 我是否必须在这里使用全局变量 DBConnection 以便每个线程都可以访问它?
  2. 假设“DBSession* session = conn.openSession();” 可以在“真正设置好conn”之前执行,而且我也不想每次都对openSession进行基准测试,我该如何解决这个问题?

所以我总共有 2 个部分的 4 个问题,如果你对我的代码有更多的建议,那就更好了。谢谢!

4

1 回答 1

1
  1. 我们多次运行整个基准测试以找到要运行的最佳迭代次数,但是每次基准运行只运行一次序言。你这样做是对的。

  2. 如果需要,您需要自己跟踪迭代计数。但是,如果您这样做了,那么您所进行的基准测试可能与迭代次数无关,而迭代次数是动态确定的。如果您想要固定数量的迭代,您应该查看State::KeepRunningBatch.


  1. 具有连接全局工作,或夹具的静态成员。

  2. 我会添加一个显式等待在每个线程上建立连接。conn.IsReady()在您打开会话之前,某种循环。

于 2018-05-25T10:09:48.177 回答