package brennus.eval;

import static brennus.eval.DynamicExpression.Type.DOUBLE;
import brennus.eval.DynamicExpression.Type;
import brennus.eval.Parameters.ParametersArray;

public class PerfTest {

  private static final String SPACE = "                                                    ";
  private static ExpressionCompiler compiler = new ExpressionCompiler();

  public static void main(String[] args) {
    perfTest();
  }

  public static void perfTest() {
    for (int i = 1; i <= 4; i++) {
      testPerf(i);
    }
  }

  private static void testPerf(int depth) {
    System.out.println(SPACE + "DEPTH: " + depth);
    Object[] values = new Object[Type.values().length];
    for (int i = 0; i < values.length; i++) {
      values[i] = TestEval.randomValue(Type.values()[i]);
    }
    ParametersArray p = new ParametersArray(values);
    Type t = DOUBLE;
    DynamicExpression e = TestEval.generateRandomExp(depth, t);
    System.out.println(p);
    System.out.println(e);
    long t0 = System.currentTimeMillis();
    Expression ce = compiler.compileExpression(e);
    long t1 = System.currentTimeMillis();
    System.out.println(SPACE + "compilation: " + (t1 - t0) +  "ms");
    compare(p, e, ce, 1000000);
    compare(p, e, ce, 1000000);
    compare(p, e, ce, 1000000);
    compare(p, e, ce, 10000000);
  }

  private static void compare(
      ParametersArray p,
      DynamicExpression e, Expression ce, int n) {
    System.out.print("<");
    long t0 = eval(p, e, n);
    System.out.print("><");
    long t1 = eval(p, ce, n);
    System.out.print(">");
    String message = "1E" + (int)Math.log10(n) + " " + msPerMil(n, t0) + " -> " + msPerMil(n, t1) + " ";
    while (message.length() < 25) {
      message += " ";
    }
    if (t0 > 0) {
      message += (((float)(t1 * 10000 / t0))/100) + "%";
    }
    System.out.println(SPACE + message);
  }

  private static String msPerMil(int n, long ms) {
    return ((float)1000000 * ms / n) + "ms";
  }

  public static double tot = 0;

  private static long eval(ParametersArray p, Expression e, int n) {
//    System.gc();
    long t0 = System.currentTimeMillis();
    tot = 0;
    for (int i = 0; i < n; i++) {
      tot += e.evalDouble(p);
    }
    long t1 = System.currentTimeMillis();
    long t = t1 - t0;
    return t;
  }

}

@@ -519,24 +519,71 @@
 %0A    %7D%0A  %7D%0A%0A
+  private static final int entrySize = 10000;%0A%0A
   private st
@@ -665,16 +665,118 @@
 depth);%0A
+    ParametersArray%5B%5D p = new ParametersArray%5BentrySize%5D;%0A    for (int i = 0; i %3C entrySize; i++) %7B%0A  
     Obje
@@ -823,24 +823,26 @@
 ength%5D;%0A    
+  
 for (int i =
@@ -838,24 +838,24 @@
 or (int 
-i
+j
  = 0; 
-i
+j
  %3C value
@@ -864,23 +864,25 @@
 length; 
-i
+j
 ++) %7B%0A
+  
       va
@@ -886,17 +886,17 @@
  values%5B
-i
+j
 %5D = Test
@@ -930,13 +930,15 @@
 s()%5B
-i
+j
 %5D);%0A
+  
     
@@ -943,33 +943,22 @@
   %7D%0A    
-ParametersArray p
+  p%5Bi%5D
  = new P
@@ -981,16 +981,22 @@
 alues);%0A
+    %7D%0A
     Type
@@ -1076,35 +1076,8 @@
 t);%0A
-    System.out.println(p);%0A
     
@@ -1489,16 +1489,18 @@
 ersArray
+%5B%5D
  p,%0A    
@@ -1542,24 +1542,41 @@
 e, int n) %7B%0A
+//  System.gc();%0A
     System.o
@@ -1615,24 +1615,47 @@
 l(p, e, n);%0A
+    double tot1 = tot;%0A
     System.o
@@ -1696,24 +1696,47 @@
 (p, ce, n);%0A
+    double tot2 = tot;%0A
     System.o
@@ -2038,16 +2038,54 @@
  message
+ + ((tot2 - tot1) != 0.0 ? %22 !!!%22: %22%22)
 );%0A  %7D%0A%0A
@@ -2260,16 +2260,18 @@
 ersArray
+%5B%5D
  p, Expr
@@ -2293,27 +2293,8 @@
 ) %7B%0A
-//    System.gc();%0A
     
@@ -2405,16 +2405,31 @@
 Double(p
+%5Bi %25 entrySize%5D
 );%0A    %7D

improve perf test