Skip to content

Provide an API in dedicate worker for executing event loop #10596

Open
@burningtnt

Description

@burningtnt

What problem are you trying to solve?

Some of the codes require extremely high performance. Therefore, these codes will use Web Worker and make their codes like this:

state = "A_STATE"
while (true) {
    switch (state) {
        ...
    }
}

Therefore, this Web Worker will never release the CPU and give the browser a chance to execute the event loop, which means, dozens of API, including self.onmessage, fetch, OffscreenCanvas cannot being used in this context.

What solutions exist today?

For the developers of these applications, they will use SharedArrayBuffer to receive the messages from the main thread, as this API provide a way to transfer messages without releasing the CPU.

They even use the XHR request and set sync=true to send a request to a ServiceWorker and transfer things back by catching this network request.

Some people may argue that why they don't refactor there codes to something like this:

let step = 0;
let executePart = () => { ... }

setTimeout(function myself() {
    executePart()
    
    setTimeout(myself)
}, 0)

These codes will reduce the performance as each executePart will wait about 4 - 10 ms before getting execute.

How would you solve it?

Adding an API like processEventLoop() for WebWorker only.

This API can be invoked in any place in WebWorker. Once it's invoked, the browser will pause this JS code and execute things including promise, setTimeout, event handle (onmessage, ...).

The codes will be like:

let queue = []
self.onmessage = (ev) => { queue.push(...) }

while (true) {
    for (let ev of queue) {
        ...
    }
    
    execute();
    
    processEventLoop()
}

This API can also take one argument, which is a promise, like let result = processEventLoop(fetch( ... )).
This is like await, but it's not required to invoked in a async function.
(The problem that why we don't use async function is that this will also reduce performance)

Anything else?

These API are strange because they provide another way to execute a promise. It's like OffscreenCanvasContext2D.commit(), as this provides a solution without release the CPU.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions