Is there a faster way to yield to Javascript event loop than setTimeout(0)?

后端 未结 4 649
误落风尘
误落风尘 2020-12-10 18:43

I am trying to write a web worker that performs an interruptible computation. The only way to do that (other than Worker.terminate()) that I know is to periodic

4条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-10 19:37

    I can confirm the 4ms round trip time of setTimeout(..., 0), but not consistently. I used the following worker (start with let w = new Worker('url/to/this/code.js', stop with w.terminate()).

    In the first two rounds the pause is sub 1ms, then I get one in the range of 8ms and then it stays around 4ms each further iteration.

    To reduce the wait I moved the yieldPromise executor in front of the workload. This way setTimeout() can keep it’s minimum delay without pausing the work loop longer than necessary. I guess the workload has to be longer than 4ms to be effective. That should not be a problem, unless catching the cancel message is the workload... ;-)

    Result: ~0.4ms delay only. I.e. reduction by at least factor 10.1

    'use strict';
    const timer = performance.now.bind(performance);
    
    async function work() {
        while (true) {
            const yieldPromise = new Promise(resolve => setTimeout(resolve, 0));
            const start = timer();
            while (timer() - start < 500) {
                // work here
            }
            const end = timer();
            // const yieldPromise = new Promise(resolve => setTimeout(resolve, 0));
            await yieldPromise;
            console.log('Took this time to come back working:', timer() - end);
        }
    }
    work();
    


    1 Isn’t the browser limiting the timer resolution to that range? No way to measure further improvements then...

提交回复
热议问题