Skip to content

src: UV_RUN_ONCE in a loop is inefficient #8496

@bnoordhuis

Description

@bnoordhuis

src/node.cc calls uv_run(loop, UV_RUN_ONCE) in a loop:

do {
  v8_platform.PumpMessageLoop(isolate);
  more = uv_run(env.event_loop(), UV_RUN_ONCE);

  if (more == false) {
    v8_platform.PumpMessageLoop(isolate);
    EmitBeforeExit(&env);

    // Emit `beforeExit` if the loop became alive either after emitting
    // event, or after running some callbacks.
    more = uv_loop_alive(env.event_loop());
    if (uv_run(env.event_loop(), UV_RUN_NOWAIT) != 0)
      more = true;
  }
} while (more == true);

uv_run() looks like this:

int uv_run(uv_loop_t* loop, uv_run_mode mode) {
  // ...
  while (r != 0 && loop->stop_flag == 0) {
    uv__update_time(loop);
    uv__run_timers(loop);
    // ...
    uv__io_poll(loop, timeout);
    uv__run_check(loop);
    uv__run_closing_handles(loop);

    if (mode == UV_RUN_ONCE) {
      uv__update_time(loop);
      uv__run_timers(loop);
    }

    r = uv__loop_alive(loop);
    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
      break;
  }
  // ...
}

The way we use UV_RUN_ONCE is:

  1. Inefficient. uv__update_time() is called twice. It's expensive on systems where querying the system time is expensive (e.g. virtualized systems.)
  2. Arguably incorrect. Timers are effectively dispatched twice per look tick.

Branched off #8460 (comment).

Metadata

Metadata

Assignees

No one assigned

    Labels

    c++Issues and PRs that require attention from people who are familiar with C++.help wantedIssues that need assistance from volunteers or PRs that need help to proceed.lib / srcIssues and PRs related to general changes in the lib or src directory.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions