【发布时间】:2022-08-19 06:22:40
【问题描述】:
我有一个用 node.js 编写的优化算法,它使用 cpu 时间(用performance.now() 测量)作为启发式算法。
但是,我注意到有时一些琐碎的代码行会比平时花费更多。
于是我写了一个测试程序:
const timings = [];
while (true) {
const start = performance.now();
// can add any trivial line of code here, or just nothing
const end = performance.now();
const dur = end - start;
if (dur > 1) {
throw [
\"dur > 1\",
{
start,
end,
dur,
timings,
avg: _.mean(timings),
max: _.max(timings),
min: _.min(timings),
last: timings.slice(-10),
},
];
}
timings.push(dur);
}
测量结果显示平均值为 0.00003 毫秒,峰值 > 1 毫秒(第二高的 < 1 毫秒,但数量级相同)。
我能想到的可能原因有:
- 平均时间不是执行代码的实际时间(一些编译器优化)
- performance.now 不知何故不准确
- cpu 调度相关 - 进程未正常运行但仍计入性能。现在
- 偶尔节点在幕后做一些额外的事情(GC等)
- 硬件/操作系统级别发生的事情 - 缓存/页面错误等
这些是可能的原因,还是其他原因?
无论原因是什么,有没有办法为算法使用更准确的测量?
当前异常值导致算法行为不端,并且不知道如何解决此问题,最好的选择是使用移动平均成本作为启发式方法,但有其缺点。
提前致谢!
- - - - 编辑
我很欣赏
performance.now()永远不会准确,但有点惊讶它可以跨越 3-4 个数量级(而不是 2 个数量级或理想情况下为 1 个数量级。)有人对
performance.now()的工作原理有任何想法/指针吗?因此可能是错误范围的主要贡献者?很高兴知道原因是否是由于 node/v8 无法控制的某些东西(硬件/操作系统级别)与它确实可以控制的某些东西(与节点错误/选项/gc 相关),所以在考虑使用替代启发式的其他权衡之前,我可以决定是否有办法减少错误范围。
-
您不太可能准确测量一行微不足道的代码的时间。事实上,执行
performance.now()的开销可能比执行一行微不足道的代码的时间要高很多倍。 -
1,3 和 5 也是所有可能性。您不能保证您的代码获得一个不会中断的专用 CPU 内核来服务系统中的其他线程。在我的 Windows 系统中,即使我的 nodejs 是唯一运行的“应用程序”,还有数百个其他线程专门用于各种操作系统服务,这些线程可能会或可能不会在我的 nodejs 应用程序运行时请求一些时间来运行并最终得到一些我的 nodejs 应用程序正在使用的 CPU 内核的时间片。
-
@jfriend00 有没有关于
performance.now()工作原理的文档?它不会不包括不在节点线程上工作的 cpu 时间吗? (nodejs.org/api/perf_hooks.html#performancenow 根本没有解释太多)另外顺便说一句,我对测量单行代码的性能并不是很感兴趣——我只是推断这个例子来证明performance.now()跨越 3-4根据自身的数量级,并希望找到一种解释,并希望能找到一种以某种方式减少测量误差的方法。
标签: node.js performance v8