Skip to content

Eliminate blocking on the event loop when possible #8341

Closed
@toddaaro

Description

@toddaaro

In the current design the scheduler takes one scheduling action, registers a callback to wake up in the run_sched_once function, and then blocks on the event loop. This "block" is implemented as just finishing the execution associated with the run_sched_once callback. As there is a callback registered it immediately wakes up and repeats the process.

This should be unnecessary. The drop back to the event loop is a very long process relative to a task context swap, so this is likely very bad for performance. A better solution would be to keep the scheduler active until it runs out of stuff to do, and then block on the event loop.

To do this we should have a "live" flag for the scheduler. If the flag is set the scheduler is guarenteed to check for messages and likely work before going to sleep. While active the scheduler algorithm becomes:

  1. Call run on the event loop with the NO_WAIT flag set. This will make it so that if there are no events, the function returns immediately instead of blocking.
  2. Find a task to run, and run it. Repeat a small number of times to get better task throughput.
  3. If the live flag is false, call a blocking run.
  4. If no work has been done this round, set the live flag to false.
  5. Goto (1)

The libuv "uv_run" function has three modes. UV_RUN_DEFAULT is what we have been using, a blocking "do stuff until the program is done" use of the event loop. UV_RUN_NOWAIT polls for new events and then does not block if there are no events ready. This is the style that we want for the non-blocking run case. UV_RUN_ONCE is how we would perform blocking runs. It will block until it handles a single event, and then return how many pending events there are.

To wake up the scheduler while it is "sleeping", the old idle-callback is used. Except now the function provided simply modifies the live flag to "awake", and the scheduler loop logic takes over. In any case where an idle callback would be registered and the live flag is set the callback can be skipped.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-runtimeArea: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions