【发布时间】:2022-02-17 20:55:15
【问题描述】:
最初,我有一段代码可以定期执行某些操作。虽然我遇到了奇怪的性能和时间问题。
我在下面自己的脚本中隔离了主循环
let sleepTime = 50 //milliseconds
var sleep = (ms) => new Promise(res => setTimeout(res, ms))
let state = {
stopCalled: false,
countLoops: 0,
lastLoopTime: 0,
loopDuration: 0,
badLoops: [],
badSleeps: []
}
let data = [1, 2, 3, 5, 1, 1, 1, 5, 1, 3, 1, 5, 4]
async function startLoop() {
//necessary for first loopDuration
state.lastLoopTime = Date.now() - 50
while (true) {
if (state.stopCalled) return
state.countLoops++
state.loopDuration = Date.now() - state.lastLoopTime
state.lastLoopTime = Date.now()
if (state.loopDuration > 100) {
state.badLoops.push(state.loopDuration)
console.log(`Bad loop duration: ${state.loopDuration}`)
}
//do some random work
let rand = randomInteger(1, 7)
for (let i = 0; i <data.length; i++) {
if (data[i] === rand) continue
data[i] = randomInteger(1, 7)
}
let initialTime = Date.now()
await sleep(sleepTime)
let actualSleepDuration = Date.now() - initialTime
//sleep duration should be <=50 milliseconds
if (actualSleepDuration > 100) {
state.badSleeps.push(actualSleepDuration)
console.log(`Bad sleep duration: ${actualSleepDuration}`)
}
}
}
function randomInteger(min, max) {
return Math.round((max - min) * Math.random()) + min
}
代码作用的总结: 手动调用 startLoop 后,应该每隔 50ms 周期性地运行一次循环 我预计会有 +/-5ms 的误差,这没关系。
但是,睡眠功能/ setTimeout 功能会变得非常不准确长达 1 分钟,尤其是在运行一段时间后
我理解setTimeout,如果没有阻塞代码更准确,在这种情况下,这是唯一运行的脚本,这对于为什么会有这么多的延迟没有意义。
有没有更准确的方法来运行函数?
做了两个测试来自:
一个来自 Electron 17.0.1
另一个来自 Node JS 17.5.0 REPL 的 .load file.js
- 操作系统:Windows 10
- 内存:16GB
- CPU 使用率:1-10%
【问题讨论】:
-
那么,您实际上需要在这里做什么?确保函数几乎每 N 毫秒执行一次?为什么不使用
setInterval? -
顺便说一句,我现在已经运行了你的脚本一段时间了,
actualSleepDuration始终如预期的那样持续大约 50 到 56 毫秒。 -
@AKX 在我的代码的某些部分是的,但我也注意到,在我只需要睡眠功能的某些区域,setTimeout 有同样的问题(1 分钟滞后)
-
@AKX 我添加了图像,请检查.. 问题在几个小时后出现。大约 3 小时后看到了延迟
-
这看起来像一个浏览器截图。你在哪个版本的 Node.js 上运行它,在哪个操作系统中等等?
标签: javascript node.js electron settimeout setinterval