Skip to content

await(Future future) should immediately return or raise if the future is complete - significant perf improvement #5402

@doctorpangloss

Description

@doctorpangloss

Version

4.5.11

Context

While upgrading my application to 4.5.11 from 4.4.x, I saw a significant performance regression (almost 3x slower) when removing my usage of the vertx virtual threads incubator and replacing with ThreadingModel.VIRTUAL_THREADS. The root cause was that in my fork of the threads incubator, awaiting a Future will check if the future is complete and return immediately or throw. Upstream, the virtual thread always parks. This is inefficient.

Do you have a reproducer?

This implementation of await exhibits the issue (this is just upstream await):

public static <T> T await(Future<T> fut) {
  return io.vertx.core.Future.await(fut);
}

This does not:

public static <T> T await(Future<T> fut) {
  if (fut == null) {
    throw new IllegalArgumentException("Future cannot be null");
  }
  if (fut.isComplete()) {
    if (fut.succeeded()) {
      return fut.result();
    } else if (fut.cause() != null) {
      throwAsUnchecked(fut.cause());
    } else {
      throw new RuntimeException();
    }
  }
  var ctx = Vertx.currentContext();
  if (ctx == null) {
    try {
      return fut.toCompletionStage().toCompletableFuture().get();
    } catch (InterruptedException | ExecutionException e) {
      throw new RuntimeException(e);
    }
  }
  return io.vertx.core.Future.await(fut);
}

Steps to reproduce

The tests in vert-x3/vertx-virtual-threads-incubator#8 previously investigated and reported the issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions