【发布时间】:2016-08-08 16:47:12
【问题描述】:
我注意到 JavaScript 中有一种奇怪的技术,我用它来提高在画布上绘制的重复过程的性能。将来,我计划在实现时使用SharedBufffer 甚至SharedCanvas,但与此同时,这是我使用的总体思路:
function someContinuousProcess(intervals, delay) {
var count = 0;
var span = document.querySelector('span');
function someExpensiveFunction() {
if (count >= 1e9) {
return false;
}
do {
count++;
} while (count % 1e5);
span.textContent = count;
return true;
}
function wrapper(index) {
var start = performance.now();
if (someExpensiveFunction()) {
var delta = performance.now() - start;
// some logic here to determine new
// values for `intervals` and `delay`
scheduler[index] = setTimeout(
wrapper.bind(null, index),
delay
);
}
}
var scheduler = [];
function startScheduler() {
for (var i = 0; i < intervals; i++) {
scheduler[i] = setTimeout(
wrapper.bind(null, i),
delay
);
}
}
function stopScheduler() {
for (var i = 0; i < scheduler.length; i++) {
clearTimeout(scheduler[i]);
}
scheduler = [];
}
startScheduler();
}
int.onchange = del.onchange = () => {
var intervals = parseInt(int.value);
var delay = parseInt(del.value);
if (!isNaN(intervals) && !isNaN(delay)) {
someContinuousProcess(intervals, delay);
}
};
<input placeholder=intervals id=int>
<input placeholder=delay id=del>
<span></span>
如果你弄乱了参数,你会发现delay 和intervals 当然都会对性能产生显着影响。但在一定程度上,如果你设置过多的intervals 以达到一定的延迟,性能提升会变成性能下降,同时导致线程无响应。
我的问题是,是否可以根据给定的someExpensiveFunction 自适应地选择intervals 和delay?假设我们可以让someExpensiveFunction() 返回一个高分辨率时间戳performance.now(),那么我们如何使用它来智能地改变intervals 和delay 以优化性能?
【问题讨论】:
-
您希望使用 setTimeout 而不是 setInterval,以便间隔的持续时间可以随时间变化。此外,正确使用 setTimeout 可以防止您一次堆叠大量操作。 (如果你在 setInterval 中的逻辑超过了区间,那你就麻烦了。)
-
@ChristopherDavies 如果您愿意,我可以重写调度程序以使用
setTimeout,但这并不能真正回答我的主要问题,即如何以编程方式定位最佳值。另外,如果setInterval中的逻辑超过了间隔,如果你仔细这样做,我发现这就是提高性能的方法。我的猜测是 JavaScript 引擎以某种方式提示 CPU 超频或在这些条件下进行某些操作,但正如我尝试暗示的那样,不同的计算机和浏览器之间的特定值会有所不同。 -
这里有一个很好的链接来说明为什么应该使用 setTimeout:zetafleet.com/blog/2010/04/… 至于你的主要问题,我将发表后续评论。
-
您可以让昂贵的函数更新某些状态(例如
durationOfLastComputation或类似的东西)。然后,您将根据durationOfLastComputation确定超时持续时间。但是,如果您使用 setTimeout 而不是间隔,则可能不必这样做,因为根据定义,如果您从超时回调中调用expensiveFunction,则在执行之前不会发生重新调度。跨度> -
@ChristopherDavies 我更新了我的代码 sn-p 以根据您的要求使用 setTimeout
标签: javascript performance asynchronous optimization micro-optimization