package io.trane.future; import org.openjdk.jmh.annotations.Benchmark; import scala.Function1; import scala.concurrent.Await; import scala.concurrent.ExecutionContext; import scala.concurrent.Future; import scala.concurrent.Future$; import scala.concurrent.Promise; import scala.concurrent.duration.Duration; import scala.concurrent.duration.Duration.Infinite; import scala.util.Try; public class ScalaFutureBenchmark { private static final String string = "s"; private static final RuntimeException exception = new RuntimeException(); private static final ExecutionContext ec = scala.concurrent.ExecutionContext.global(); private static final Future<String> constFuture = Future.successful(string); private static final Future<Void> constVoidFuture = Future.successful(null); private static final Function1<String, String> mapF = i -> string; private static final Function1<String, Future<String>> flatMapF = i -> constFuture; private static final Function1<Try<Void>, Try<Void>> ensureF = t -> t; private static final Infinite inf = Duration.Inf(); @Benchmark public Promise<String> newPromise() { return Promise.<String>apply(); } @Benchmark public Future<String> value() { return Future.successful(string); } @Benchmark public Future<String> exception() { return Future$.MODULE$.<String>failed(exception); } @Benchmark public String mapConst() throws Exception { return Await.result(constFuture.map(mapF, ec), inf); } @Benchmark public String mapConstN() throws Exception { Future<String> f = constFuture; for (int i = 0; i < N.n; i++) f = f.map(mapF, ec); return Await.result(f, inf); } @Benchmark public String mapPromise() throws Exception { Promise<String> p = Promise.<String>apply(); Future<String> f = p.future().map(mapF, ec); p.success(string); return Await.result(f, inf); } @Benchmark public String mapPromiseN() throws Exception { Promise<String> p = Promise.<String>apply(); Future<String> f = p.future(); for (int i = 0; i < N.n; i++) f = f.map(mapF, ec); p.success(string); return Await.result(f, inf); } @Benchmark public String flatMapConst() throws Exception { return Await.result(constFuture.flatMap(flatMapF, ec), inf); } @Benchmark public String flatMapConstN() throws Exception { Future<String> f = constFuture; for (int i = 0; i < N.n; i++) f = f.flatMap(flatMapF, ec); return Await.result(f, inf); } @Benchmark public String flatMapPromise() throws Exception { Promise<String> p = Promise.<String>apply(); Future<String> f = p.future().flatMap(flatMapF, ec); p.success(string); return Await.result(f, inf); } @Benchmark public String flatMapPromiseN() throws Exception { Promise<String> p = Promise.<String>apply(); Future<String> f = p.future(); for (int i = 0; i < N.n; i++) f = f.flatMap(flatMapF, ec); p.success(string); return Await.result(f, inf); } @Benchmark public Void ensureConst() throws Exception { return Await.result(constVoidFuture.transform(ensureF, ec), inf); } @Benchmark public Void ensureConstN() throws Exception { Future<Void> f = constVoidFuture; for (int i = 0; i < N.n; i++) f.transform(ensureF, ec); return Await.result(f, inf); } @Benchmark public Void ensurePromise() throws Exception { Promise<Void> p = Promise.<Void>apply(); Future<Void> f = p.future().transform(ensureF, ec); p.success(null); return Await.result(f, inf); } @Benchmark public Void ensurePromiseN() throws Exception { Promise<Void> p = Promise.<Void>apply(); Future<Void> f = p.future(); for (int i = 0; i < N.n; i++) f = f.transform(ensureF, ec); p.success(null); return Await.result(f, inf); } @Benchmark public String setValue() throws Exception { Promise<String> p = Promise.<String>apply(); p.success(string); return Await.result(p.future(), inf); } @Benchmark public String setValueN() throws Exception { Promise<String> p = Promise.<String>apply(); Future<String> f = p.future(); for (int i = 0; i < N.n; i++) f = f.map(mapF, ec); p.success(string); return Await.result(f, inf); } private Future<Integer> loop(int i) { if (i > 0) return Future.successful(i - 1).flatMap(this::loop, ec); else return Future.successful(0); } @Benchmark public Integer recursiveConst() throws Exception { return Await.result(loop(N.n), inf); } }