【问题标题】:node: run function consistently X times per second while tracking how long it runs节点:在跟踪它运行多长时间的同时,每秒一致地运行函数 X 次
【发布时间】:2021-12-08 16:27:01
【问题描述】:

我想编写一个自动执行最大值的系统。 8192 个不同的值,每秒持续 40 次。我想做的那种自动化是例如让一些值形成从 0 到 255 的正弦曲线,其他值从 50 上升到 80,其他值在 255 和 0 之间切换,等等。

我需要知道每次执行需要多长时间,如果执行时间超过允许的时间,它应该“丢帧”。

我的第一种方法是

// simplified code
const fps = 40
const executionStats : number[] = []
executionStats.length = fps * 10

const startFrame = new Date()

type SingleValue = {current: number, effectType: string, effectStarted: number}
const values : SingleValue[] = [...] // up to 8192 entries

// this is calculating the target value based on some lookups in other objects
// and based on when the effect started and in what tick we are in right now
const runSingleEffect = (value: SingleValue, tick: number) : number => {...}

const handler = async (tick: number) => {
   values.forEach(value => {value.current = runSingleEffect(value, tick)})
}

setInterval(async () => {
   const start = new Date()
   await handler((start - startFrame) / fps);
   const end = new Date()
   executionStats.push(end - start)
   executionStats.unshift()
}, 1000 / fps)

有没有比使用简单的setInterval 更好的方法? (显然我可以为执行统计使用环形缓冲区)但是有没有更好的方法来确保一次只运行一个处理程序?有没有这类东西的图书馆?

【问题讨论】:

    标签: node.js typescript setinterval


    【解决方案1】:

    我会使用setTimeout 并持续重新订阅。您将在每个“循环”结束时重新计算下一个刻度。

    function defer (ms) {
        const frameBudgetMs = 1000 / fps;
        setTimeout(async () => {
            const start = Date.now();
            try {
                await handler((start - startFrame) / fps);
            } finally {
                const end = Date.now();
                const ms = end - start;
                executionStats.push(ms);
                executionStats.unshift();
    
                // a) In case we are over our frame, start next defer immediately.
                let nextTickMs = Math.max(0, frameBudgetMs - ms);
                defer(nextTickMs);
    
                // b) In case we want to execute at specific frame interval, but just dropping the frames
                let nextTickMs = frameBudget - ms % frameBudget;
                defer(nextTickMs);
            }
        }, ms)
    }
    
    // start our loop
    defer(0);
    

    如您所见,您在重新订阅场景中完全灵活,在这样的“循环”中不可能有并行运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-21
      • 2020-07-15
      • 1970-01-01
      • 2012-01-09
      • 2018-12-19
      • 1970-01-01
      • 2017-03-30
      • 2020-06-09
      相关资源
      最近更新 更多