Skip to content

src: UV_RUN_ONCE in a loop is inefficient #8496

Closed
@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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions