【问题标题】:Node.js extremely inaccurate setTimeoutNode.js 极其不准确的 setTimeout
【发布时间】: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


【解决方案1】:

经过大量测试,发现chrome throttles background tabs/windows from Chrome 88,非常适合笔记本电脑上的网站省电

但是对于电子应用程序来说真的很糟糕(使用 Chromium 引擎),不应该被限制。

要解决这个问题,您应该将 backgroundThrottling 更改为 false,默认情况下为 true

const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {           
        backgroundThrottling: false,
    }
})

摘自throttling doc

这会影响所有非阻塞 JavaScript 计时器所基于的 setInterval 和 setTimeout

【讨论】:

    猜你喜欢
    • 2012-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 2015-07-02
    相关资源
    最近更新 更多