使用 setTimeout 延迟所有繁重的计算

Deferring all heavy computation using setTimeout

本文关键字:计算 setTimeout 延迟 使用      更新时间:2023-09-26
  1. 假设我有一个非常繁重的计算,它涉及两个嵌套的 for 循环,大小为 1000*1000 的数组

  2. 计算大约需要 1 分钟。

  3. 我在网页上还有很多其他的东西,尤其是用户交互。(点击,滚动,动画等)

  4. 现在我需要在某个时候进行 60 年代的计算。例如,我可以做:

    setTimeout TwoForLoops,0
    

    这会将函数调用推迟到清除所有其他单击、滚动等事件。但是,由于计算需要 1 分钟,因此用户可能会在此期间触发某些事件。你认为如果我只做以下事情,我会阻止 JavaScript 挂起来吗?假设重计算计算大约需要 0.06 毫秒。

    # _.map is from underscore@ library, basically does a for loop
    # HeavyComputation is a slow function with lots of operations made for my app
    NonBlockMap = (x,f)-> setTimeout (->_.map x,f),0
    NonBlockHeavyComputation = (x) -> setTimeout (-> HeavyComputation(x)),0
    TwoForLoops = (ArrayOfArray) ->
       SecondLoop = (element) -> NonBlockHeavyComputation element
       FirstLoop = (array) -> NonBlockMap array, SecondLoop
    
       return NonBlockMap ArrayOfArray,FirstLoop
    

    这实质上意味着 javascript 将挂起的最大时间约为 0.06 毫秒,但我不太确定这是否可行。

    做什么?

我认为您的代码将所有百万个 HeavyComputing 可连续对象预先排队,而不是按其预测。 事件循环将在处理新用户事件之前按顺序处理每个事件,因此您仍然阻止了一分钟。

不过,您应该使用 setInstant,或者仔细检查 setTimeout of 0 是否不休眠。 Nodejs(我的工作;也许也是chrome?)总是休眠1毫秒。

考虑对繁重的计算嵌套循环进行批处理,如下所示:

function batchedHeavyComputation( elements, iFrom, jFrom, batchSize ) {
    var i, j, numcalls = 0;
    for (i=iFrom; i<1000; i++) {
        for (j=jFrom; j<1000; j++) {
            HeavyComputation(elements[i][j])
            if (++numcalls >= batchSize) {
                setImmediate(function(){
                    var jNext = j < 999 : j+1 : 0;
                    var iNext = j < 999 ? i : i+1;
                    batchedHeavyComputation(elements, iNext, jNext, batchSize);
                });
                return;
            }
        }
    }
}
batchedHeavyComputation(elements, 0, 0, 20);