You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(That's a bad issue title, but I can't think of a better one, sorry)
There are two main issues with the current implementation of the event loop:
As long as there is work to do, it keeps waking up the task, even if the work is a timer many seconds into the future, leading to busy-waiting and wasted CPU cycles.
It does't wake up the task when it receives new work to do (e.g. when a promise continuation or future is enqueued as a result of running some code).
The second point is especially painful. Let's assume there's a select! somewhere:
what happens is that do_stuff will run until it creates the PromiseFuture, then wait for the event loop to progress the promise. However, if the event loop was empty, it won't be polled (this is the only sensible thing to do when running JS alongside native code; otherwise, we're always busy-waiting), so now we're stuck waiting for something else to wake the task up (For context, we didn't discover this so far because the WinterJS event loop was a bit of a patchwork implementation, and relied on being interrupted every millisecond or so.)
Here's my commit that fixes this in our fork: e9e2ec5. I've added a few things:
the event loop stores a waker, and when something (future, microtask, macrotask) is enqueued, we wake the task up.
the macrotask queue now registers timers when it wants to be woken up later.
The event loop itself no longer has a concept of "running to completion". Instead, it has a step function that does as much as it can and register wake-up calls for its pending work. There's a new Future type named RunToEnd that keeps stepping the event loop until it's empty.
Runtime::run_event_loop now uses RunToEnd internally, but the semantics should be unchanged.
(That's a bad issue title, but I can't think of a better one, sorry)
There are two main issues with the current implementation of the event loop:
The second point is especially painful. Let's assume there's a
select!
somewhere:and
do_stuff
does:what happens is that
do_stuff
will run until it creates thePromiseFuture
, then wait for the event loop to progress the promise. However, if the event loop was empty, it won't be polled (this is the only sensible thing to do when running JS alongside native code; otherwise, we're always busy-waiting), so now we're stuck waiting for something else to wake the task up (For context, we didn't discover this so far because the WinterJS event loop was a bit of a patchwork implementation, and relied on being interrupted every millisecond or so.)Here's my commit that fixes this in our fork: e9e2ec5. I've added a few things:
step
function that does as much as it can and register wake-up calls for its pending work. There's a newFuture
type namedRunToEnd
that keeps stepping the event loop until it's empty.Runtime::run_event_loop
now usesRunToEnd
internally, but the semantics should be unchanged.Runtime::step_event_loop
. You can see how this is useful here: https://github.com/wasmerio/winterjs/blob/main/src/runners/event_loop_stream.rsThe text was updated successfully, but these errors were encountered: