Create a gist now

Instantly share code, notes, and snippets.

With more stable benchmark results
package javaslang;
import javaslang.collection.Array;
import javaslang.control.Option;
import org.junit.Test;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.stream.Stream;
import static javaslang.API.*;
import static javaslang.ForExpressionBenchmark.Variants.*;
/**
* Impl Score ± Error Unit java_exception java_option java_optional java_stream_option java_stream_optional slang_bind_option slang_option
* java_exception 192,309.05 ± 1.62% ops/s 0.04× 0.03× 0.10× 0.09× 0.06× 0.37×
* java_option 4,927,477.78 ± 0.42% ops/s 25.62× 0.87× 2.44× 2.21× 1.52× 9.55×
* java_optional 5,683,329.51 ± 2.70% ops/s 29.55× 1.15× 2.81× 2.55× 1.75× 11.02×
* java_stream_option 2,020,996.37 ± 0.91% ops/s 10.51× 0.41× 0.36× 0.91× 0.62× 3.92×
* java_stream_optional 2,226,325.04 ± 0.70% ops/s 11.58× 0.45× 0.39× 1.10× 0.69× 4.32×
* slang_bind_option 3,240,039.84 ± 0.90% ops/s 16.85× 0.66× 0.57× 1.60× 1.46× 6.28×
* slang_option 515,900.77 ± 0.95% ops/s 2.68× 0.10× 0.09× 0.26× 0.23× 0.16×
*/
@State(Scope.Benchmark)
public class ForExpressionBenchmark {
private static final Array<Class<?>> CLASSES = Array(ForExpressionBenchmark.class);
@Test
public void testAsserts() { JmhRunner.runDebugWithAsserts(CLASSES); }
// public static void runVerySlowNoAsserts(Array<Class<?>> groups, Includes... includes) {
// run(20, 20, 1000, ForkJvm.ENABLE, VerboseMode.EXTRA, Assertions.DISABLE, PrintInlining.DISABLE, groups, includes).print();
// }
public static void main(String... args) {
JmhRunner.runDebugWithAsserts(CLASSES);
JmhRunner.runVerySlowNoAsserts(CLASSES);
}
/*@formatter:off*/
final GrillServiceWithOptional grillServiceWithOptional_all = new GrillServiceWithOptional();
final GrillServiceWithOptional grillServiceWithOptional_no_charcoal = new GrillServiceWithOptional() { @Override Optional<Charcoal> charcoal() { return Optional.empty(); } };
final GrillServiceWithOptional grillServiceWithOptional_no_lighter = new GrillServiceWithOptional() { @Override Optional<Lighter> lighter() { return Optional.empty(); } };
final GrillServiceWithOptional grillServiceWithOptional_no_fire = new GrillServiceWithOptional() { @Override Optional<Fire> lightFire(Charcoal charcoal, Lighter lighter) { return Optional.empty(); } };
final GrillServiceWithOptional grillServiceWithOptional_no_cornCob = new GrillServiceWithOptional() { @Override Optional<CornCob> cornCob() { return Optional.empty(); } };
final GrillServiceWithOptional grillServiceWithOptional_no_grill = new GrillServiceWithOptional() { @Override Optional<Dinner> grill(Fire fire, CornCob cornCob) { return Optional.empty(); } };
final GrillServiceWithOption grillServiceWithOption_all = new GrillServiceWithOption();
final GrillServiceWithOption grillServiceWithOption_no_charcoal = new GrillServiceWithOption() { @Override Option<Charcoal> charcoal() { return None(); } };
final GrillServiceWithOption grillServiceWithOption_no_lighter = new GrillServiceWithOption() { @Override Option<Lighter> lighter() { return None(); } };
final GrillServiceWithOption grillServiceWithOption_no_fire = new GrillServiceWithOption() { @Override Option<Fire> lightFire(Charcoal charcoal, Lighter lighter) { return None(); } };
final GrillServiceWithOption grillServiceWithOption_no_cornCob = new GrillServiceWithOption() { @Override Option<CornCob> cornCob() { return None(); } };
final GrillServiceWithOption grillServiceWithOption_no_grill = new GrillServiceWithOption() { @Override Option<Dinner> grill(Fire fire, CornCob cornCob) { return None(); } };
/*@formatter:on*/
@Benchmark
public Object java_exception() {
final Optional<?> all = makeJavaDinner0(grillServiceWithOptional_all);
final Optional<?> noCharcoal = makeJavaDinner0(grillServiceWithOptional_no_charcoal);
final Optional<?> noLighter = makeJavaDinner0(grillServiceWithOptional_no_lighter);
final Optional<?> noFire = makeJavaDinner0(grillServiceWithOptional_no_fire);
final Optional<?> noCornCob = makeJavaDinner0(grillServiceWithOptional_no_cornCob);
final Optional<?> noGrill = makeJavaDinner0(grillServiceWithOptional_no_grill);
assert all.isPresent() && !noCharcoal.isPresent() && !noLighter.isPresent() && !noFire.isPresent() && !noCornCob.isPresent() && !noGrill.isPresent();
return new Object[] { all, noCharcoal, noLighter, noFire, noCornCob, noGrill };
}
@Benchmark
public Object java_optional() {
final Optional<?> all = makeJavaDinner(grillServiceWithOptional_all);
final Optional<?> noCharcoal = makeJavaDinner(grillServiceWithOptional_no_charcoal);
final Optional<?> noLighter = makeJavaDinner(grillServiceWithOptional_no_lighter);
final Optional<?> noFire = makeJavaDinner(grillServiceWithOptional_no_fire);
final Optional<?> noCornCob = makeJavaDinner(grillServiceWithOptional_no_cornCob);
final Optional<?> noGrill = makeJavaDinner(grillServiceWithOptional_no_grill);
assert all.isPresent() && !noCharcoal.isPresent() && !noLighter.isPresent() && !noFire.isPresent() && !noCornCob.isPresent() && !noGrill.isPresent();
return new Object[] { all, noCharcoal, noLighter, noFire, noCornCob, noGrill };
}
@Benchmark
public Object java_option() {
final Option<?> all = makeJavaDinner(grillServiceWithOption_all);
final Option<?> noCharcoal = makeJavaDinner(grillServiceWithOption_no_charcoal);
final Option<?> noLighter = makeJavaDinner(grillServiceWithOption_no_lighter);
final Option<?> noFire = makeJavaDinner(grillServiceWithOption_no_fire);
final Option<?> noCornCob = makeJavaDinner(grillServiceWithOption_no_cornCob);
final Option<?> noGrill = makeJavaDinner(grillServiceWithOption_no_grill);
assert all.isDefined() && noCharcoal.isEmpty() && noLighter.isEmpty() && noFire.isEmpty() && noCornCob.isEmpty() && noGrill.isEmpty();
return new Object[] { all, noCharcoal, noLighter, noFire, noCornCob, noGrill };
}
@Benchmark
public Object java_stream_option() {
final Option<?> all = makeJavaStreamDinner(grillServiceWithOption_all);
final Option<?> noCharcoal = makeJavaStreamDinner(grillServiceWithOption_no_charcoal);
final Option<?> noLighter = makeJavaStreamDinner(grillServiceWithOption_no_lighter);
final Option<?> noFire = makeJavaStreamDinner(grillServiceWithOption_no_fire);
final Option<?> noCornCob = makeJavaStreamDinner(grillServiceWithOption_no_cornCob);
final Option<?> noGrill = makeJavaStreamDinner(grillServiceWithOption_no_grill);
assert all.isDefined() && noCharcoal.isEmpty() && noLighter.isEmpty() && noFire.isEmpty() && noCornCob.isEmpty() && noGrill.isEmpty();
return new Object[] { all, noCharcoal, noLighter, noFire, noCornCob, noGrill };
}
@Benchmark
public Object java_stream_optional() {
final Optional<?> all = makeJavaStreamDinner(grillServiceWithOptional_all);
final Optional<?> noCharcoal = makeJavaStreamDinner(grillServiceWithOptional_no_charcoal);
final Optional<?> noLighter = makeJavaStreamDinner(grillServiceWithOptional_no_lighter);
final Optional<?> noFire = makeJavaStreamDinner(grillServiceWithOptional_no_fire);
final Optional<?> noCornCob = makeJavaStreamDinner(grillServiceWithOptional_no_cornCob);
final Optional<?> noGrill = makeJavaStreamDinner(grillServiceWithOptional_no_grill);
assert all.isPresent() && !noCharcoal.isPresent() && !noLighter.isPresent() && !noFire.isPresent() && !noCornCob.isPresent() && !noGrill.isPresent();
return new Object[] { all, noCharcoal, noLighter, noFire, noCornCob, noGrill };
}
@Benchmark
public Object slang_option() {
final Option<?> all = makeJavaslangDinner(grillServiceWithOption_all);
final Option<?> noCharcoal = makeJavaslangDinner(grillServiceWithOption_no_charcoal);
final Option<?> noLighter = makeJavaslangDinner(grillServiceWithOption_no_lighter);
final Option<?> noFire = makeJavaslangDinner(grillServiceWithOption_no_fire);
final Option<?> noCornCob = makeJavaslangDinner(grillServiceWithOption_no_cornCob);
final Option<?> noGrill = makeJavaslangDinner(grillServiceWithOption_no_grill);
assert all.isDefined() && noCharcoal.isEmpty() && noLighter.isEmpty() && noFire.isEmpty() && noCornCob.isEmpty() && noGrill.isEmpty();
return new Object[] { all, noCharcoal, noLighter, noFire, noCornCob, noGrill };
}
@Benchmark
public Object slang_bind_option() {
final Option<?> all = makeJavaslangBindDinner(grillServiceWithOption_all);
final Option<?> noCharcoal = makeJavaslangBindDinner(grillServiceWithOption_no_charcoal);
final Option<?> noLighter = makeJavaslangBindDinner(grillServiceWithOption_no_lighter);
final Option<?> noFire = makeJavaslangBindDinner(grillServiceWithOption_no_fire);
final Option<?> noCornCob = makeJavaslangBindDinner(grillServiceWithOption_no_cornCob);
final Option<?> noGrill = makeJavaslangBindDinner(grillServiceWithOption_no_grill);
assert all.isDefined() && noCharcoal.isEmpty() && noLighter.isEmpty() && noFire.isEmpty() && noCornCob.isEmpty() && noGrill.isEmpty();
return new Object[] { all, noCharcoal, noLighter, noFire, noCornCob, noGrill };
}
static class Variants {
/* benchmark Java solution using Exceptions */
static Optional<Dinner> makeJavaDinner0(GrillServiceWithOptional service) {
try {
final Optional<Charcoal> charcoal = service.charcoal();
final Optional<Lighter> lighter = service.lighter();
final Optional<CornCob> cornCob = service.cornCob();
final Optional<Fire> fire = service.lightFire(charcoal.get(), lighter.get());
return service.grill(fire.get(), cornCob.get());
} catch (NoSuchElementException e) {
return Optional.empty();
}
}
/* benchmark Java solution using Optional */
static Optional<Dinner> makeJavaDinner(GrillServiceWithOptional service) {
final Optional<Charcoal> charcoalOption = service.charcoal();
final Optional<Lighter> lighterOption = service.lighter();
if (charcoalOption.isPresent() && lighterOption.isPresent()) {
final Optional<Fire> fireOption = service.lightFire(charcoalOption.get(), lighterOption.get());
final Optional<CornCob> cornCobOption = service.cornCob();
if (fireOption.isPresent() && cornCobOption.isPresent()) {
return service.grill(fireOption.get(), cornCobOption.get());
}
}
return Optional.empty();
}
/* benchmark Java solution using Option */
static Option<Dinner> makeJavaDinner(GrillServiceWithOption service) {
final Option<Charcoal> charcoalOption = service.charcoal();
final Option<Lighter> lighterOption = service.lighter();
if (charcoalOption.isDefined() && lighterOption.isDefined()) {
final Option<Fire> fireOption = service.lightFire(charcoalOption.get(), lighterOption.get());
final Option<CornCob> cornCobOption = service.cornCob();
if (fireOption.isDefined() && cornCobOption.isDefined()) {
return service.grill(fireOption.get(), cornCobOption.get());
}
}
return None();
}
/* make Java Stream dinner using Optional */
static Optional<Dinner> makeJavaStreamDinner(GrillServiceWithOptional service) {
final Optional<Charcoal> charcoal = service.charcoal();
final Optional<Lighter> lighter = service.lighter();
final Optional<CornCob> cornCob = service.cornCob();
return Stream.of(charcoal, lighter, cornCob).allMatch(Optional::isPresent)
? service.lightFire(charcoal.get(), lighter.get()).flatMap(fire -> service.grill(fire, cornCob.get()))
: Optional.empty();
}
/* make Java Stream dinner using Option */
static Option<Dinner> makeJavaStreamDinner(GrillServiceWithOption service) {
final Option<Charcoal> charcoal = service.charcoal();
final Option<Lighter> lighter = service.lighter();
final Option<CornCob> cornCob = service.cornCob();
return Stream.of(charcoal, lighter, cornCob).allMatch(Option::isDefined)
? service.lightFire(charcoal.get(), lighter.get()).flatMap(fire -> service.grill(fire, cornCob.get()))
: None();
}
/* benchmark Javaslang solution using Option */
static Option<Dinner> makeJavaslangDinner(GrillServiceWithOption service) {
return For(service.charcoal(), charcoal
-> For(service.lighter(), lighter
-> For(service.lightFire(charcoal, lighter), fire
-> For(service.cornCob(), cornCob
-> For(service.grill(fire, cornCob))
.yield())))).toOption();
}
/* benchmark alternative Javaslang solution using Option */
static <T1, T2, U> Option<U> Bind(Option<T1> o1, Option<T2> o2, Function2<? super T1, ? super T2, Option<U>> mapper) {
return o1.flatMap(v1 -> o2.flatMap(v2 -> mapper.apply(v1, v2)));
}
static Option<Dinner> makeJavaslangBindDinner(GrillServiceWithOption service) {
return Bind(service.charcoal(), service.lighter(), (charcoal, lighter)
-> Bind(service.lightFire(charcoal, lighter), service.cornCob(), (fire, cornCob)
-> service.grill(fire, cornCob)));
}
}
}
class GrillServiceWithOption {
Option<Charcoal> charcoal() { return Some(new Charcoal()); }
Option<Lighter> lighter() { return Some(new Lighter()); }
Option<Fire> lightFire(Charcoal charcoal, Lighter lighter) { return Some(new Fire(charcoal, lighter)); }
Option<CornCob> cornCob() { return Some(new CornCob());}
Option<Dinner> grill(Fire fire, CornCob cornCob) { return Some(new Dinner(fire, cornCob)); }
}
class GrillServiceWithOptional {
Optional<Charcoal> charcoal() { return Optional.of(new Charcoal()); }
Optional<Lighter> lighter() { return Optional.of(new Lighter()); }
Optional<Fire> lightFire(Charcoal charcoal, Lighter lighter) { return Optional.of(new Fire(charcoal, lighter)); }
Optional<CornCob> cornCob() { return Optional.of(new CornCob()); }
Optional<Dinner> grill(Fire fire, CornCob cornCob) { return Optional.of(new Dinner(fire, cornCob)); }
}
class Charcoal {}
class Lighter {}
class Fire {
final Charcoal charcoal;
final Lighter lighter;
Fire(Charcoal charcoal, Lighter lighter) {
this.charcoal = charcoal;
this.lighter = lighter;
}
}
class CornCob {}
class Dinner {
final Fire fire;
final CornCob cornCob;
Dinner(Fire fire, CornCob cornCob) {
this.fire = fire;
this.cornCob = cornCob;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment