0

Я заметил странную технику в 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

Вы хотели бы использовать SetTimeout вместо setInterval, так что длительность интервала может изменяться с течением времени. Кроме того, правильное использование setTimeout не позволяет вам выполнять много операций одновременно. (Если ваша логика в setInterval превышает интервал, у вас возникнут проблемы.) –

+0

@ChristopherDavies Я могу переписать планировщик, чтобы использовать 'setTimeout', если вы предпочитаете, но это на самом деле не отвечает на мой главный вопрос о том, как программно найти оптимальные значения. Кроме того, если логика в 'setInterval' превышает интервал, если вы делаете это внимательно, это то, что я нахожу, повышает производительность. Я предполагаю, что механизм JavaScript как-то подсказывает, что процессор разгоняется или что-то в этих условиях, но по мере того, как я пытался намекать, конкретные значения будут отличаться между различными компьютерами и браузерами. –

+0

Вот довольно хорошая ссылка на то, почему вы должны использовать setTimeout: https://zetafleet.com/blog/2010/04/why-i-consider-setinterval-to-be-harmful.html Что касается вашего основного вопроса, Опубликуйте комментарий. –

ответ

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();
<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) { 
 
    \t postMessage(count); 
 
start = performance.now(); 
 
    } 
 
} while (count < 1e9); 
 
postMessage(count); //make sure to send 'done' 
 
</script>

Fiddle

+0

Раньше я использовал веб-работников. Узкое место заканчивается тем, что сообщения сложены и не отправляются в поток DOM так быстро, как только они создаются.Я уверен, что этот ответ может пригодиться другим, но –

+0

Таким образом, причина для reportPerSec. Это та же проблема, что и в сценарии не-веб-работника, где вы перегружаете цикл событий. Кроме того, у вас также есть основной код для контента. – Cine

Смежные вопросы