我注意到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
一段延迟,性能提升将变成性能下降,同时使线程无响应。
我的问题是,是否可以根据给定的intervals
自适应地选择delay
和someExpensiveFunction
?假设我们可以someExpensiveFunction()
返回高分辨率时间戳performance.now()
,那么我们如何使用它来智能地改变intervals
和delay
以优化性能?
答案 0 :(得分:0)
这似乎是使用网络工作者的绝佳机会。它们在一个单独的线程中执行,因此它们不会影响主线程上的动画。
但是,仍然要求您不要经常postMessage
,或者主线程中的事件循环会对大量消息产生阻塞。
function simple() {
var span = $('#v1');
var worker = new Worker('data:text/javascript;charset=UTF-8,' + encodeURI($('#someExpensiveFunction').text()));
worker.onmessage = progress => span.text(progress.data);
worker.onerror = x => {
debugger;
};
}
function withanim() {
var span = $('#v2');
var worker = new Worker('data:text/javascript;charset=UTF-8,' + encodeURI($('#someExpensiveFunction').text()));
var latestMessage = 0;
worker.onmessage = progress => latestMessage = progress.data;
worker.onerror = x => {
debugger;
};
var myReq;
function step(timestamp) {
span.text(latestMessage);
if (latestMessage < 1e9)
myReq = requestAnimationFrame(step);
}
myReq = requestAnimationFrame(step);
}
simple();
withanim();
&#13;
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"
type="text/javascript" charset="utf-8"></script>
<div id=v1></div>
<div id=v2></div>
<script type="text/worker" id="someExpensiveFunction">
var count = 0;
var start = performance.now();
var reportPerSec = 100; //change this
var delay = 1000/reportPerSec;
do {
//some un-interrupable task
//it might be useful to put this in a setTimeout(0), if you also want to use onmessage to get data to work on from the main thread
do {
count++;
} while (count % 1e2);
//report progress
if (performance.now() - start > delay) {
postMessage(count);
start = performance.now();
}
} while (count < 1e9);
postMessage(count); //make sure to send 'done'
</script>
&#13;