【问题标题】:Benchmarking with googletest?用 googletest 进行基准测试?
【发布时间】:2012-01-23 20:08:24
【问题描述】:

背景(如果不感兴趣,请跳至下面的问题)

我有一个模拟器,它运行三种状态:

  1. 单线程启动(I/O 正常)
  2. 多线程内存中 CPU 绑定模拟阶段(I/O 不正常)
  3. 模拟后、连接后单线程阶段(I/O 正常)

这到底是怎么回事!在标准测试期间,CPU 使用率从 100% 下降到 20%,总运行时间比正常情况长约 30 倍(130 秒对 4.2 秒)。

当Callgrind 没有发现任何可疑之处时,我的脑袋嗡嗡作响,因为我正处于回滚到最后一次提交的悬崖上,失去了所有错误修复。

气馁地,我在跑步时走进服务器机房并注意到令人讨厌的磨擦声,后来证实是由/proc/PID/fd中的Mysql套接字写入引起的!!!事实证明,Mysql 代码,在第 2 阶段有好几层,导致了问题。

经验教训

  1. 意外的 I/O 对实时应用程序可能是致命的
  2. 单元测试还不够:我还需要基准测试

修复我将在 ReadAllowed() 和 WriteAllowed() 上引入 thread-local-storage IOSentinels 和 asserts() 以确保 Stage 2 线程永远不会进行任何 IO。

问题

任何人都可以使用 googletest 附加/编写基准测试框架吗?

不幸的是,这次我所有的 googletests 都通过了。如果我离开了一会儿,然后在没有注意到运行时的情况下回来,这将是一个灾难性的提交,并且可能更难修复。

如果运行时间是上次运行时间的 2 或 3 倍,我希望 googletest 失败:这最后一部分很棘手,因为对于非常快速的运行,系统状态可能会导致某些事情花费两倍的时间,但仍然可以。但对于长时间的模拟运行/测试,我预计运行时间不会有太大变化(>50% 是不寻常的)。

我对这里的建议持开放态度,但最好有一个低维护检查,它可以与自动化测试一起使用,这样如果系统突然变慢,即使所有输出看起来都很好,也会很明显。

【问题讨论】:

    标签: c++ benchmarking googletest


    【解决方案1】:

    关于这个问题的一些更新(2016 年):

    1. Here 是 Nick Brunn 的一篇关于他的 Hayai 基准测试框架的精彩博文。 (2012)

      • 它不提供指定运行时间要求的可能性。
      • 它与谷歌测试非常相似。语法等
      • 它向用户或持续集成框架提供基准测试结果。还可以查看 MojaveWastelander 的 fork 以获得积极的开发和 MSVC 支持。
    2. Google 在2014 中发布了'Benchmark'。这提供了与上述 Hayai 类似的行为。据我了解,定义需求是不可能的。同样,语法受到 GoogleTest 的启发。

      • 甚至还有一些高级功能,例如测量复杂性 (big-O)。
    3. GoogleTest 在Github 上将此作为一项开放功能。有一个基本的 implementation,但它还不是 GoogleTest 的一部分。

    【讨论】:

      【解决方案2】:

      不就是这么简单吗?

      const clock_t t0 = clock(); // or gettimeofday or whatever
      int res = yourFunction();
      const clock_t t1 = clock();
      const double elapsedSec = (t1 - t0) / (double)CLOCKS_PER_SEC;
      EXPECT_EQ(EXPECTED, res);
      EXPECT_GT(10.0, elapsedSec);
      

      在这里,您需要根据您的任务手动更改10.0。

      当然,您可以通过以下方式走得更远:

      double prev = -1;
      {
        ifstream ifs("/var/tmp/time_record.txt");
        ifs >> prev;
      }
      if (prev < 0) prev = DEFAULT_VALUE;
      // ...
      EXPECT_GT(2 * prev, elapsedSec);
      {
        ofstream ofs("/var/tmp/time_record.txt");
        ofs << elapsedSec << endl;
      }
      

      但我想知道这种额外的复杂性真的是合理的。

      【讨论】:

      • 或者,如果可能,使用 C++11 中的 std::chrono 库。 googletest 库在为 C++11 编译时也能正常工作。
      【解决方案3】:

      我在 v1.5.0 中这样做:

      BENCHMARK(SomeBenchmark);
      BENCHMARK(AnotherBenchmark);
      
      TEST(MyTest, Benchmarks)
      {
          ::benchmark::RunSpecifiedBenchmarks();
      }
      

      也就是说,我只是在其中一个 gtest 测试中直接调用 RunSpecifiedBenchmarks。

      【讨论】:

        【解决方案4】:

        默认情况下,Google 测试框架建议对经过的时间进行度量。它由环境变量GTEST_PRINT_TIME 控制。此变量默认为1。

        那么,为什么不使用 Google 测试平台的这一功能来监控经过的时间呢?

        这是word on elapsed time variable in Google Test。

        【讨论】:

        • +1 这几乎是我正在寻找的——如果我可以在某些验证中实际访问每个测试的结果,那将是完美的:例如EXPECT_LT( TEST_RUNTIME, 1000) 不到一千毫秒...
        猜你喜欢
        • 2012-02-02
        • 1970-01-01
        • 2018-09-12
        • 1970-01-01
        • 2011-04-27
        • 2012-11-11
        • 2014-02-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多