Jump to content
Excelsior Forums
Sign in to follow this  
roedy

Disappointing optimisation

Recommended Posts

Here is a benchmark. Jet just beats out java -client, but java -server is 1.4 times as fast as Jet. :huh: I thought perhaps analysing this program might provide hints on how to improve Jet optimisation.  I presume the problem is simply that -server has access to run time stats Jet does not.

run it with  Simplify.exe 10000000 3

Result with Athlon 64 X2 3800+ dual core, 2 gig ram.

java -client Simplify 10000000 3

[* x [+ [+ [* 12 0] [+ 23 8]] y]]

Bench 0

Took 4.422 seconds

Bench 1

Took 4.728 seconds

Bench 2

Took 4.408 seconds

[* x [+ 31 y]]

using jet

Simplify.exe 10000000 3

[E:\exper]Simplify 10000000 3

[* x [+ [+ [* 12 0] [+ 23 8]] y]]

Bench 0

Took 4.178 seconds

Bench 1

Took 4.193 seconds

Bench 2

Took 4.303 seconds

[* x [+ 31 y]]

java -server Simplify 10000000 3

[* x [+ [+ [* 12 0] [+ 23 8]] y]]

Bench 0

Took 2.91 seconds

Bench 1

Took 2.84 seconds

Bench 2

Took 2.84 seconds

[* x [+ 31 y]]

---- Simplify.java -----

// Simplify.java

import java.math.BigDecimal;

public class Simplify {

  public static void main(String[] args) {

    int lim = Integer.parseInt(args[0]);

    int nbench = Integer.parseInt(args[1]);

    Expr expr =

          mul(var("x"),

                add(

                  add(mul(rat( 12 ),rat( 0 )), add(rat( 23 ),rat( 8 ))),

                  var("y")

                  )

                );

    System.out.println(expr);

    Expr reduced = null;

    for (int batch = 0; batch < nbench; batch++) {

      long start = System.currentTimeMillis();

      System.err.println("Bench " + batch);

      for (int i = 0; i < lim; i++) {

        reduced = expr.simplify();

      }

      System.err.println("Took " +

        (System.currentTimeMillis() - start) / 1000.0 + " seconds");

    }

    System.out.println(reduced);

  }

  private static Expr mul(Expr a, Expr B) {

    return new Mul(a,B);

  }

  private static Expr add(Expr a, Expr B) {

    return new Add(a,B);

  }

  private static Expr rat(long a) {

      return Val.create(BigDecimal.valueOf(a));

  }

  private static Expr var(String s) {

    return new Sym(s);

  }

  public static abstract class Expr {

      public abstract Expr simplify();

  }

  public static final class Add extends Expr {

    private final Expr l, r;

    public Add(Expr l, Expr r) {

      this.l = l;

      this.r = r;

    }

    public Expr simplify() {

      return add(l.simplify(), r.simplify());

    }

    private Expr add(Expr l, Expr r) {

      if (Val.ZERO == l) {

        return r;

      } else if (Val.ZERO == r) {

        return l;

      } else if (l instanceof Val && r instanceof Val) {

        return add((Val) l, (Val) r) ;

      } else if (r instanceof Add) {

        return add(l, (Add) r);

      } else {

        return new Add(l, r);

      }

    }

    private Expr add(Val l, Val r) {

      return Val.create(l.getValue().add(r.getValue()));

    }

    private Expr add(Expr l, Add r) {

      return new Add(new Add(l, r.l), r.r).simplify();

    }

    public String toString() {

      return "[+ " + l + " " + r +"]";

    }

  }

  public static class Mul extends Expr {

    private final Expr l, r;

    public Mul(Expr l, Expr r) {

      this.l = l;

      this.r = r;

    }

    public Expr simplify() {

      return mul(l.simplify(), r.simplify());

    }

    private Expr mul(Expr l, Expr r) {

      if (Val.ZERO == l || Val.ZERO == r) {

        return Val.ZERO;

      } else if (Val.ONE == l) {

        return r;

      } else if (Val.ONE == r) {

        return l;

      } else if (l instanceof Val && r instanceof Val) {

        return mul((Val) l, (Val) r) ;

      } else if (r instanceof Mul) {

        return mul(l, (Mul) r);

      } else {

        return new Mul(l, r);

      }

    }

    private Expr mul(Val l, Val r) {

      return Val.create(l.getValue().multiply(r.getValue()));

    }

    private Expr mul(Expr l, Mul r) {

      return new Mul(new Mul(l, r.l), r.r).simplify();

    }

    public String toString() {

      return "[* " + l + " " + r +"]";

    }

  }

  public static class Sym extends Expr {

    private final String symbol;

    public Sym(String symbol) {

      this.symbol = symbol;

    }

    public Expr simplify() {

      return this;

    }

    public String toString() {

      return symbol;

    }

  }

  public static class Val extends Expr {

    public static final Val ZERO = new Val(BigDecimal.ZERO);

    public static final Val ONE = new Val(BigDecimal.ONE);

    private final BigDecimal value;

    private Val(BigDecimal value) {

      this.value = value;

    }

    public Expr simplify() {

      return this;

    }

    public static Val create(BigDecimal value) {

      if (BigDecimal.ZERO == value || BigDecimal.ZERO.equals(value)) {

        return ZERO;

      } else if (BigDecimal.ONE == value && BigDecimal.ONE.equals(value)) {

        return ONE;

      } else {

        return new Val(value);

      }

    }

    public BigDecimal getValue() {

      return value;

    }

    public String toString() {

      return String.valueOf(value);

    }

  }

}

Share this post


Link to post
Share on other sites

Thanks for posting this microbenchmark.

I presume the problem is simply that -server has access to run time stats Jet does not.

We have doubts that run time profiling could help with this test. Most probably, certain low-level optimizations are poorly implemented or not implemented at all.

We will check it and let you know.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×