Ist die monadische Programmierung in Java 8 langsamer? Unten ist mein Test (ein rechtsgerichtetes Es wird verwendet, das für jede Berechnung neue Instanzen erstellt). Die imperative Version ist 1000 mal schneller. Wie programmiere ich in Java8 monadisch und vergleiche die Leistung?Wie programmiere ich in Java8 monadisch und erhalte vergleichbare Leistung?
Main.java
public class Main {
public static void main(String args[]){
Main m = new Main();
m.work();
m.work2();
}
public void work(){
final long start = System.nanoTime();
final Either<Throwable,Integer> result =
Try(this::getInput).flatMap((s) ->
Try(this::getInput).flatMap((s2) ->
parseInt(s).flatMap((i) ->
parseInt(s2).map((i2) ->
i + i2
))));
final long end = System.nanoTime();
result.map(this::println).leftMap(this::println);
System.out.println((end-start)/1000+"us to execute");
}
public void work2(){
Object result;
final long start = System.nanoTime();
try {
final String s = getInput();
final String s2 = getInput();
final int i = parzeInt(s);
final int i2 = parzeInt(s2);
result = i + i2;
}catch(Throwable t){
result=t;
}
final long end = System.nanoTime();
println(result);
System.out.println((end-start)/1000+"us to execute");
}
public <A> A println(final A a){
System.out.println(a);
return a;
}
public String getInput(){
final Integer value = new Random().nextInt();
if(value % 2 == 0) return "Surprise!!!";
return value+"";
}
public Either<Throwable,Integer> parseInt(final String s){
try{
return Either.right(Integer.parseInt(s));
}catch(final Throwable t){
return Either.left(t);
}
}
public Integer parzeInt(final String s){
return Integer.parseInt(s);
}
}
Either.java
public abstract class Either<L,R>
{
public static <L,R> Either<L,R> left(final L l){
return new Left(l);
}
public static <L,R> Either<L,R> right(final R r){
return new Right(r);
}
public static<L,R> Either<L,R> toEither(final Optional<R> oR,final L l){
return oR.isPresent() ? right(oR.get()) : left(l);
}
public static <R> Either<Throwable,R> Try(final Supplier<R> sr){
try{
return right(sr.get());
}catch(Throwable t){
return left(t);
}
}
public abstract <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f);
public abstract <R2> Either<L,R2> map(final Function<R,R2> f);
public abstract <L2> Either<L2,R> leftMap(final Function<L,L2> f);
public abstract Either<R,L> swap();
public static class Left<L,R> extends Either<L,R> {
final L l;
private Left(final L l){
this.l=l;
}
public <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f){
return (Either<L,R2>)this;
}
public <R2> Either<L,R2> map(final Function<R,R2> f){
return (Either<L,R2>)this;
}
public <L2> Either<L2,R> leftMap(final Function<L,L2> f){
return new Left(f.apply(l));
}
public Either<R,L> swap(){
return new Right(l);
}
}
public static class Right<L,R> extends Either<L,R> {
final R r;
private Right(final R r){
this.r=r;
}
public <R2> Either<L,R2> flatMap(final Function<R,Either<L,R2>> f){
return f.apply(r);
}
public <R2> Either<L,R2> map(final Function<R,R2> f){
return new Right(f.apply(r));
}
public <L2> Either<L2,R> leftMap(final Function<L,L2> f){
return (Either<L2,R>)this;
}
public Either<R,L> swap(){
return new Left(r);
}
}
}
Nur noch einige Male "Arbeit" ausführen. Bootstrapping eines Lambda ist teuer. –
Mit 1.000.000 Läufen ist der Unterschied mehr als 10x langsamer. Mit 80% der Zeit in Main.parseInt (String) verbrachte, aus irgendeinem Grund ... –
geändert, um das Zeitdelta zurückzugeben. Lief es für 1.000.000 Läufe und 10.000.000 Läufe. Habe immer noch den Unterschied zu ungefähr 1000 gefunden. Ich habe nur die letzte Bewertung genommen (wenn es ziemlich warm sein sollte). Sie können die Ergebnisse in Mikrosekunden unter Funk: 57411000 \t Imper: 83000 – jordan3