Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web worker as precise timer: inconsistent in iOS?

I'm using the following code in a web worker to schedule events to happen precisely 10ms apart.

This seems to work in all browsers except any iOS browser. (Desktop safari is fine.)

Worker <script> tag:

<script id="masterClock" type="javascript/worker">
  let onmessage = function (event) {
    let delay = 10; // milliseconds
    let time = Date.now();
    while (Date.now() < time + delay) { }; // waits 10ms increments in all browsers except mobile Safari
    postMessage({data: []});
  };
</script>

Main <script> tag (simplified):

let blob = new Blob([document.querySelector("#FastTimer").textContent]);
let blobURL = window.URL.createObjectURL(blob);
let worker = new Worker(blobURL);

worker.addEventListener("message", receivedWorkerMessage);

// simplified example of interacting with the timer
function receivedWorkerMessage(event) {
    worker.postMessage(userInteractionData);
    doNextStepOfWork(); 
    counter++;  
}

Any suggestions/explanations appreciated!

Notes:

  • I tried using a setTimeout based timer, but it was much too imprecise, and didn't help with iOS at all.
  • I tried an alternative timer based on requestAnimationFrame, but it was also inconsistent in iOS.
  • I've considered using AudioContext, but I wouldn't want to pre-schedule all the events, because the user interacts with them as they go; but maybe it could serve as the timer?
like image 218
ultraGentle Avatar asked Jul 03 '26 09:07

ultraGentle


1 Answers

This construct

while (Date.now() < startTime + delay) { }

is not very nice to the computer/device. It's the equivalent of flooring your accelerator and brake pedal at once. You are forcing one cpu to work 100% until you have 'paused' for a number of milliseconds. Why?

Instead just use a setTimeout, or setInterval or create your own async sleep function:

const sleep = ms => new Promise(res => setTimeout(res, ms));

That you can call like this inside any async function:

await sleep(milliseconds)

Or, I asked myself, am I missing something here: Is this waste of CPU power a more exact timer? So I made som test comparing calling the while loop and the await sleep with 10 ms as a delay and then checking the delay with performance.now. And both seems as exact/inexact - clocking in between 9.5-10.5 ms on my computer. So why use a blocking while-loop (I know it's in a worker so it's not blocking the main thread)? It's a waste of CPU cycles/battery power...

like image 104
Thomas Frank Avatar answered Jul 04 '26 23:07

Thomas Frank



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!