Package loop

Source Code of loop.AsmMvelPerformanceBenchmark$Callable

package loop;

import loop.ast.script.Unit;
import org.junit.Test;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;
import org.mvel2.integration.VariableResolverFactory;
import org.mvel2.util.VariableSpaceCompiler;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
* Measures the performance of various Loop scripts compiled against the MVEL and
* ASM/Java Bytecode backends.
*
* @author dhanji@gmail.com (Dhanji R. Prasanna)
*/
@SuppressWarnings("unchecked") // No idea why but the compiler keeps whinging
public class AsmMvelPerformanceBenchmark extends LoopTest {
  // Number of cycles for the benchmark, should be > 200000 for anything useful.
//  private static final int RUNS = 500000;
  private static final int RUNS = 1;
  private static final int WARMUP_RUNS = RUNS > 100 ? 15000 : 0;

  @Test
  public final void quicksort() throws Exception {
    Callable callable = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("quicksort", Object.class);
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke("quicksort", Arrays.asList(5, 2, 6, 19, 0, 92, 144, 1));
      }
    };

    time("quicksort(ls) =>\n" +
        "  []        : []\n" +
        "  [x:xs]    : quicksort(i for i in xs if i < x) + [x] + quicksort(i for i in xs if i > x)\n" +
        "\n",
        callable, "quicksort([5, 2, 6, 19, 0, 92, 144, 1])");
  }


//  @Test
  public final void interpolatedStrings() throws Exception {
    Callable callable = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("fun", Object.class);
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null, "yo");
      }
    };

    time("fun(name) ->\n  \"hhi @{name.toLowerCase()} - @{1 + 2} >>@{5 * 4}<< @{name} @{name} \"",
        callable, "fun('yo');");
  }


  @Test
  public final void patternMatchingFunctionWithGuards() throws Exception {
    String script =
        "pick(ls) =>\n" +
            "  5                    : 'five'\n" +
            "  *         | ls == 1  : 'one'\n" +
            "            | ls == 2  : 'two'\n" +
            "            | else     : 'other'\n";

    Callable callable = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("pick", Object.class);
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null, 2);
      }
    };

    time(script, callable, "pick(2);");
  }


  @Test
  public final void newJavaObject() throws Exception {
    Callable callable = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("fun");
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null);
      }
    };

    time("fun() ->\n  new loop.TestObjectWithUnaryCtor(23)", callable, "fun();");
  }

  @Test
  public final void newJavaObjectWithNullaryCtor() throws Exception {
    Callable callable = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("fun");
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null);
      }
    };

    time("fun() ->\n  new java.lang.String()", callable, "fun();");
  }

  @Test
  public final void valueTypedEquals() throws Exception {
    Callable callable = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("eq", Object.class, Object.class);
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null, "mynameisinigomontoya", "mynameisinigomontoya");
      }
    };

    time("eq(m1, m2) ->\n  m1 == m2", callable, "eq(\"mynameisinigomontoya\", \"mynameisinigomontoya\");");
  }

  @Test
  public final void loopFunctionCalling() throws Exception {
    Callable callable = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("func");
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null);
      }
    };

    time("cons(x) ->\n  '1'\n\nfunc() ->\n  cons('10')", callable, "func();");
  }

  @Test
  public final void loopFunctionCallingWithIntegrals() throws Exception {
    Callable callable = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("func");
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null);
      }
    };

    time("cons(x) ->\n  1 + 2\n\nfunc() ->\n  cons(10)", callable, "func();");
  }

  @Test
  public final void integerAddition() throws Exception {
    Callable add = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("add", Object.class, Object.class, Object.class);
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null, 10, 20, 40);
      }
    };

    time("add(x, y, z) ->\n  x + y + z\n", add, "add(10, 20, 40);");
  }

  @Test
  public final void arithmetic() throws Exception {
    Callable add = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("arith", Object.class, Object.class);
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null, 10, 20);
      }
    };

    time("arith(x, y) ->\n  ((100 + x - y) * 10 / 2) % 40\n", add, "arith(10, 20);");
  }

  @Test
  public final void collectionAddition() throws Exception {
    Callable add = new Callable() {

      @Override public Method lookup(Class target) throws Exception {
        return target.getDeclaredMethod("add", Object.class, Object.class);
      }

      @Override public Object call(Method target) throws Exception {
        return target.invoke(null, Arrays.asList(10, 20), Arrays.asList(40));
      }
    };

    time("add(x, y) ->\n  x + y\n", add, "add([10, 20], [40]);");
  }

  public static void time(String script, Callable javaCallable, String mvelCallable) throws Exception {
    if (RUNS > 1) {
      System.out.println("Profiling loop script:");
      System.out.println(script);
      System.out.println("\n\n");
    }
    Parser parser = new LexprParser(new Tokenizer(script).tokenize());
    Unit unit = parser.script(null);
    unit.reduceAll();

    // Compile ASM.
    Class<?> generated = new AsmCodeEmitter(unit).write(unit);
    Method asmCallable = javaCallable.lookup(generated);

    // Compile MVEL.
    String mvel = new MvelCodeEmitter(unit).write(unit);
    Serializable compiledMvel = MVEL.compileExpression(mvel + "; " + mvelCallable);

    // Assert validity.
    Object javaGen = javaCallable.call(asmCallable);
    Object mvelGen = MVEL.executeExpression(compiledMvel, new HashMap());
    assertNotNull(javaGen);
    assertNotNull(mvelGen);

    // MVEL incorrectly type-widens certain integer arithmetic expressions to double. If so,
    // convert it back into an integer.
    if (mvelGen instanceof Double && !(javaGen instanceof Double))
      mvelGen = ((Double)mvelGen).intValue();

    assertEquals(javaGen, mvelGen);

    // Warm up JVM.
    for (int i = 0; i < WARMUP_RUNS; i++) {
       javaCallable.call(asmCallable);
       MVEL.executeExpression(compiledMvel, new HashMap());
    }

    String targetRunMvel = mvel + ";\n for(i = 0; i < " + RUNS + "; i++) {\n "
        + mvelCallable + "\n}\n";

    ParserContext parserContext = new ParserContext();
    parserContext.addIndexedInput(new String[0]);

    VariableResolverFactory factory =
        VariableSpaceCompiler.compile(targetRunMvel, parserContext).createFactory(new Object[0]);
    compiledMvel = MVEL.compileExpression(targetRunMvel, parserContext);

    long start = System.currentTimeMillis();
    MVEL.executeExpression(compiledMvel, factory);

    if (RUNS > 1)
      System.out.println("Mvel runtime: " + (System.currentTimeMillis() - start));

    start = System.currentTimeMillis();
    for (int i = 0; i < RUNS; i++) {
      javaCallable.call(asmCallable);
    }
    if (RUNS > 1) {
      System.out.println("Asm runtime: " + (System.currentTimeMillis() - start));
      System.out.println();
    }
  }

  public static interface Callable {
    Method lookup(Class target) throws Exception;
    Object call(Method target) throws Exception;
  }
}
TOP

Related Classes of loop.AsmMvelPerformanceBenchmark$Callable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.