每次我的基准测试代码为 运行(不仅仅是每个周期)时,如何让 Benchmark.js 执行 setup/teardown?

How to get Benchmark.js to do setup/teardown each time my benchmarked code is run (not just each cycle)?

我正在尝试使用 Benchmark.js 对对象的成员函数进行基准测试。几个因素使测试功能变得困难:

假设它看起来像这样:

class Something {

  constructor(){
    // async ops
    this.expensiveValue = null;
  }

  expensiveOperation () {

    if (this.expensiveValue === null) {
      // Do expensive operation
      this.expensiveValue = result; // a non-null value
    }

  }

}

现在,我想进行基准测试 expensiveOperation。但是由于其限制,我还需要"reset"对象每个运行。

据我所知,benchmark 不支持每 运行 设置。我觉得让 运行 的重置部分也不是最佳实践,因为它污染了我实际尝试进行基准测试的内容。

我查看了 Benchmark.setup,但它只在每个周期执行,而不是每个 运行。

我错过了什么吗?我可以使用另一个 benchmark 选项吗?还是我处理不当?

我不会接受这个答案,因为我对这个问题的了解还不够 100% 肯定,但我确实想分享我的发现。如果这应该移到我的问题或评论中,请给我发评论。

认为 这不可能的原因是 Benchmark.js 执行计时的方式。

从我读过的内容(包括文本和代码)来看,Benchmark 不会计时和汇总单个 运行s,而是计算完成了多少 运行s在指定的时间内(默认 = 5 秒)。这避免了某些问题,例如低精度 timers/timestamps、运行 时间优化和浮点舍入错误。

因此,由于这些原因,它不能简单地减去执行每个 运行 设置函数所需的时间。它也无法暂停其计时器以允许执行每个 运行 设置。

由于这些原因,Benchmark.js 似乎不支持每个 运行 设置函数,因为这样做会在其工作中投入过多的扳手并降低计时精度。

你不能总是得到你想要的...♩

Benchmark.js 不会在您的函数的每次迭代中执行 setup/teardown,而只会针对每个 benchmark.js cycle,这通常是它可以在 5 秒内 运行,这可能是数百到数千到数百万次调用。正如 Bulletproof JavaScript benchmarks.

中 Benchmark.js 的作者所解释的那样,它这样做是有充分理由的

如果您认为这些原因不适用于您,那么我会问您为什么还要使用 Benchmark.js。您可以轻松地编写一个循环并测量每次调用的持续时间,然后自己在几行代码中取平均值。你不需要花哨的图书馆。

你不能总是得到你想要的

如果你找个时间试试,你可能会发现

您得到 ♫ 您需要的。 ♬♪

老实说,是的,您的处理方式不正确。您的 expensiveOperation () 旨在为所有后续调用提供高效,因此一个好的基准当然应该反映这一点。第一次通话的费用分摊到所有后续通话中。 Benchmark.js 将按照设计 尝试衡量您的方法的效率。就是这个意思。

想想你的基本目标,以及你为什么要为每次迭代重置。您不想对 expensiveOperation () 进行基准测试,而只想对方法的这一部分进行基准测试:

      // Do expensive operation
      this.expensiveValue = result; // a non-null value

因此,只需将其分解为一个方法或函数,然后对其进行基准测试。 :)