Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript:试图创建一个性能良好的后台作业,但当系统的其余部分大部分空闲时,它运行的时间太少?_Javascript_Background Process - Fatal编程技术网

JavaScript:试图创建一个性能良好的后台作业,但当系统的其余部分大部分空闲时,它运行的时间太少?

JavaScript:试图创建一个性能良好的后台作业,但当系统的其余部分大部分空闲时,它运行的时间太少?,javascript,background-process,Javascript,Background Process,在浏览器中,我尝试制作一个行为良好的后台工作,如下所示: function run() { var system = new System(); setInterval(function() { system.step(); }, 0); } 不管系统对象是什么,也不管step函数做什么(除了需要与UI交互,在我的例子中,更新画布以在后台运行Conway的生活游戏),活动执行得很慢,我希望它运行得更快。但是我已经在setInterval中指定了无等待时间,但是,当我在Chrome中检查

在浏览器中,我尝试制作一个行为良好的后台工作,如下所示:

function run() {
  var system = new System();
  setInterval(function() { system.step(); }, 0);
}
不管系统对象是什么,也不管step函数做什么(除了需要与UI交互,在我的例子中,更新画布以在后台运行Conway的生活游戏),活动执行得很慢,我希望它运行得更快。但是我已经在setInterval中指定了无等待时间,但是,当我在Chrome中检查分析工具时,它告诉我整个过程是80%空闲的:

有没有办法让它尽最大努力减少空闲时间,更快地完成我的工作?或者我必须建立自己的无限循环,然后以某种方式定期将时间回馈给事件循环吗

更新:有人建议使用requestIdleCallback,这样做实际上会让情况变得更糟。活动的速度明显较慢,即使分析数据不是很明显,但实际上空闲时间增加了:

更新:后来有人提议使用requestAnimationFrame,我再次发现其慢度和空闲度与requestIdleCallback方法相同,两者的运行速度大约是我从标准setInterval获得的速度的一半

PS:我已经更新了所有的计时,使之具有可比性,现在所有三个计时都在10秒左右运行相同的代码。我怀疑递归重新调度可能是导致更大速度的原因,但我排除了这一点,因为递归setTimeout调用的速度与setInterval方法差不多,而且两者的速度都是这些新的request*回调方法的两倍

我确实在实践中找到了一个可行的解决方案,稍后我会提供我自己的答案,但会再等一会儿

好的,除非有人给出另一个答案,否则这将是我的最后更新:我再次测量了所有4个选项,并测量了完成一个合理工作所花费的时间。结果如下:

  • 设置超时-31.056秒
  • 设定间隔-23.424秒
  • requestIdleCallback-68.149秒
  • requestAnimationFrame-68.177秒
  • 这给我的印象提供了客观数据,即使用request*的两种新方法的性能会更差


    我也有自己的实用解决方案,它允许我在55毫秒(0.055秒)内完成相同数量的工作,也就是说,速度要快500倍以上,并且仍然表现相对良好。我会在一段时间内报告。但是,想知道其他人能在这里了解到什么吗?

    我认为这实际上取决于你到底想实现什么

    例如,您可以在加载页面时初始化web worker并使其运行后台作业(如果需要),然后将作业的进度或状态告知浏览器的主线程。如果不喜欢使用<代码> POST消息<代码>来进行线程间的通信,请考虑用户<代码> COMLink

  • 然而,如果你打算做的背景工作不值得一个网络工作者做。您可以使用
    requestIdleCallback
    API。我认为它完全符合您在这里提到的内容,因为您已经可以使它递归。您不再需要计时器,浏览器可以帮助您安排任务,使其不会影响页面的呈现(通过将所有内容保持在60fps)

    类似=>

    function run() {
     // whatever you want to keep doing
      requestIdleCallback(run)
    
    }
    

    您可以在上阅读更多关于
    requestIdleCallback
    的信息。

    好的,我真的没有试图阻止其他人获得赏金,但是从我添加到问题中的细节可以看出,这些方法都不允许高速率执行回调

    原则上,setInterval是最有效的方法,因为我们已经不需要一直重新安排下一次回调。但这只是一个很小的区别。值得注意的是,当您希望快速回调时,requestIdleCallback和requestAnimationFrame是最糟糕的

    因此,我们需要做的不是只执行少量的工作,然后期望很快被召回,而是批量进行更多的工作。问题是,在工作量过大之前,我们不知道到底应该分批完成多少工作。这在大多数情况下都可以通过反复试验来解决


    动态地,我们可能会进行计时探测,以了解我们再次被呼叫的速度,并在两次呼叫之间的时间过期时抢先退出工作(某种循环)。

    感谢这个想法,不幸的是requestIdleCallback使情况更糟,我更新了问题以显示分析数据(可比较,让它运行10秒)此外,WebWork方法不起作用,因为我的后台任务在UI上更新了一个画布。你应该考虑<代码>请求动画框架>代码>,这也是一个Web API,可能会有帮助,同样的问题,我又更新了原来的问题,以类似的方式展示了这些结果。你的<代码> Stask.Stor()做什么?如果它在一个相当小的世界上执行gol的一个步骤,可能就不够了。特别是如果你想每帧只渲染一个步骤。那么你真正想要实现的是什么,让它尽可能快地运行(同时不阻塞主线程)?您希望如何与画布交互?@Bergi我可以看出,您正在接近解决方案。问题似乎是,此回调被javascript引擎限制,以邀请人们在一次回调中做更多的工作。这就是我最终将性能提高500倍或更多的原因。但我猜理论是cal的问题仍然是:为了保持“良好的行为”,一个人应该在回调中花费的最大工作量是多少?