Node.js setTimeout 极其不准确
Node.js extremely inaccurate setTimeout
最初,我有一段代码可以定期执行某些操作。虽然我遇到了奇怪的性能和时间问题。
我在下面的脚本中隔离了主循环
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 周期性地循环一次
我预计会有 +/-5 毫秒的误差,这没关系。
但是,睡眠函数/setTimeout 函数变得非常不准确最多 1 整分钟,尤其是在运行宁了一段时间后
我理解 setTimeout,如果没有阻塞代码则更准确,在这种情况下,这是唯一的脚本 运行ning,这对于为什么会有这么多延迟没有意义。
有没有更准确的方法运行一个函数?
完成了两项测试来自:
一个来自 Electron 17.0.1
另一个来自 Node JS 17.5.0 REPL .load file.js
- OS: windows 10
- 内存:16GB
- CPU 使用率:1-10%
经过大量测试,发现chrome throttles background tabs/windows from Chrome 88,这对于笔记本电脑上的网站来说非常省电
但是对于电子应用程序(使用 Chromium 引擎)来说真的很糟糕,不应该被限制。
要解决此问题,您应该将 backgroundThrottling
更改为 false,默认情况下为 true
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
backgroundThrottling: false,
}
})
这会影响所有 non-blocking javascript 计时器的 setInterval 和 setTimeout
最初,我有一段代码可以定期执行某些操作。虽然我遇到了奇怪的性能和时间问题。
我在下面的脚本中隔离了主循环
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 周期性地循环一次 我预计会有 +/-5 毫秒的误差,这没关系。
但是,睡眠函数/setTimeout 函数变得非常不准确最多 1 整分钟,尤其是在运行宁了一段时间后
我理解 setTimeout,如果没有阻塞代码则更准确,在这种情况下,这是唯一的脚本 运行ning,这对于为什么会有这么多延迟没有意义。
有没有更准确的方法运行一个函数?
完成了两项测试来自:
一个来自 Electron 17.0.1
另一个来自 Node JS 17.5.0 REPL .load file.js
- OS: windows 10
- 内存:16GB
- CPU 使用率:1-10%
经过大量测试,发现chrome throttles background tabs/windows from Chrome 88,这对于笔记本电脑上的网站来说非常省电
但是对于电子应用程序(使用 Chromium 引擎)来说真的很糟糕,不应该被限制。
要解决此问题,您应该将 backgroundThrottling
更改为 false,默认情况下为 true
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
backgroundThrottling: false,
}
})
这会影响所有 non-blocking javascript 计时器的 setInterval 和 setTimeout