Polishing
This commit is contained in:
parent
83051b06b8
commit
efc5b47b9a
|
@ -48,8 +48,7 @@ import org.springframework.expression.spel.testdata.PersonInOtherPackage;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Checks the behaviour of the SpelCompiler.
|
||||
* This should cover compilation all compiled node types.
|
||||
* Checks SpelCompiler behavior. This should cover compilation all compiled node types.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @since 4.1
|
||||
|
@ -322,30 +321,10 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
double resultI = expression.getValue(new TestClass1(), Double.TYPE);
|
||||
assertCanCompile(expression);
|
||||
double resultC = expression.getValue(new TestClass1(), Double.TYPE);
|
||||
assertEquals(3.4d, resultI,0.1d);
|
||||
assertEquals(3.4d, resultC,0.1d);
|
||||
|
||||
assertEquals(3.4d, resultI, 0.1d);
|
||||
assertEquals(3.4d, resultC, 0.1d);
|
||||
assertEquals(3.4d, expression.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repeatedCompilation() throws Exception {
|
||||
// Verifying that after a number of compilations, the classloaders
|
||||
// used to load the compiled expressions are discarded/replaced.
|
||||
// See SpelCompiler.loadClass()
|
||||
Field f = SpelExpression.class.getDeclaredField("compiledAst");
|
||||
Set<Object> classloadersUsed = new HashSet<>();
|
||||
for (int i =0; i < 1500; i++) { // 1500 is greater than SpelCompiler.CLASSES_DEFINED_LIMIT
|
||||
expression = parser.parseExpression("4 + 5");
|
||||
assertEquals(9, (int) expression.getValue(Integer.class));
|
||||
assertCanCompile(expression);
|
||||
f.setAccessible(true);
|
||||
CompiledExpression cEx = (CompiledExpression)f.get(expression);
|
||||
classloadersUsed.add(cEx.getClass().getClassLoader());
|
||||
assertEquals(9, (int) expression.getValue(Integer.class));
|
||||
}
|
||||
assertTrue(classloadersUsed.size() > 1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
|
@ -476,13 +455,12 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertCanCompile(expression);
|
||||
assertEquals(new Integer(42), expression.getValue(Integer.class));
|
||||
|
||||
// Code gen is different for -1 .. 6 because there are bytecode instructions specifically for those
|
||||
// values
|
||||
// Code gen is different for -1 .. 6 because there are bytecode instructions specifically for those values
|
||||
|
||||
// Not an int literal but an opminus with one operand:
|
||||
// expression = parser.parseExpression("-1");
|
||||
// assertCanCompile(expression);
|
||||
// assertEquals(-1, expression.getValue());
|
||||
// expression = parser.parseExpression("-1");
|
||||
// assertCanCompile(expression);
|
||||
// assertEquals(-1, expression.getValue());
|
||||
expression = parser.parseExpression("0");
|
||||
assertCanCompile(expression);
|
||||
assertEquals(0, expression.getValue());
|
||||
|
@ -527,8 +505,8 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
float resultI = expression.getValue(new TestClass1(), Float.TYPE);
|
||||
assertCanCompile(expression);
|
||||
float resultC = expression.getValue(new TestClass1(), Float.TYPE);
|
||||
assertEquals(3.4f, resultI,0.1f);
|
||||
assertEquals(3.4f, resultC,0.1f);
|
||||
assertEquals(3.4f, resultI, 0.1f);
|
||||
assertEquals(3.4f, resultC, 0.1f);
|
||||
|
||||
assertEquals(3.4f, expression.getValue());
|
||||
}
|
||||
|
@ -3314,10 +3292,10 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertCanCompile(expression);
|
||||
Object o = expression.getValue();
|
||||
assertEquals(testclass8,o.getClass().getName());
|
||||
TestClass8 tc8 = (TestClass8)o;
|
||||
TestClass8 tc8 = (TestClass8) o;
|
||||
assertEquals(42, tc8.i);
|
||||
assertEquals("123", tc8.s);
|
||||
assertEquals(4.0d, tc8.d,0.5d);
|
||||
assertEquals(4.0d, tc8.d, 0.5d);
|
||||
assertEquals(true, tc8.z);
|
||||
|
||||
// no-arg ctor
|
||||
|
@ -4372,7 +4350,8 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
|
||||
expression = parser.parseExpression("DR[0].three");
|
||||
Object v = expression.getValue(payload);
|
||||
assertEquals("Lorg/springframework/expression/spel/SpelCompilationCoverageTests$Three", getAst().getExitDescriptor());
|
||||
assertEquals("Lorg/springframework/expression/spel/SpelCompilationCoverageTests$Three",
|
||||
getAst().getExitDescriptor());
|
||||
|
||||
Expression expression = parser.parseExpression("DR[0].three.four lt 0.1d?#root:null");
|
||||
v = expression.getValue(payload);
|
||||
|
@ -4380,7 +4359,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
SpelExpression sExpr = (SpelExpression) expression;
|
||||
Ternary ternary = (Ternary) sExpr.getAST();
|
||||
OpLT oplt = (OpLT) ternary.getChild(0);
|
||||
CompoundExpression cExpr = (CompoundExpression)oplt.getLeftOperand();
|
||||
CompoundExpression cExpr = (CompoundExpression) oplt.getLeftOperand();
|
||||
String cExprExitDescriptor = cExpr.getExitDescriptor();
|
||||
assertEquals("D", cExprExitDescriptor);
|
||||
assertEquals("Z", oplt.getExitDescriptor());
|
||||
|
@ -4620,14 +4599,16 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
|
||||
@Test
|
||||
public void indexerMapAccessor_12045() throws Exception {
|
||||
SpelParserConfiguration spc = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,getClass().getClassLoader());
|
||||
SpelParserConfiguration spc = new SpelParserConfiguration(
|
||||
SpelCompilerMode.IMMEDIATE,getClass().getClassLoader());
|
||||
SpelExpressionParser sep = new SpelExpressionParser(spc);
|
||||
expression=sep.parseExpression("headers[command]");
|
||||
MyMessage root = new MyMessage();
|
||||
assertEquals("wibble", expression.getValue(root));
|
||||
// This next call was failing because the isCompilable check in Indexer did not check on the key being compilable
|
||||
// (and also generateCode in the Indexer was missing the optimization that it didn't need necessarily need to call
|
||||
// generateCode for that accessor)
|
||||
// This next call was failing because the isCompilable check in Indexer
|
||||
// did not check on the key being compilable (and also generateCode in the
|
||||
// Indexer was missing the optimization that it didn't need necessarily
|
||||
// need to call generateCode for that accessor)
|
||||
assertEquals("wibble", expression.getValue(root));
|
||||
assertCanCompile(expression);
|
||||
|
||||
|
@ -4803,6 +4784,25 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertIsCompiled(exp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repeatedCompilation() throws Exception {
|
||||
// Verifying that after a number of compilations, the classloaders
|
||||
// used to load the compiled expressions are discarded/replaced.
|
||||
// See SpelCompiler.loadClass()
|
||||
Field f = SpelExpression.class.getDeclaredField("compiledAst");
|
||||
Set<Object> classloadersUsed = new HashSet<>();
|
||||
for (int i = 0; i < 1500; i++) { // 1500 is greater than SpelCompiler.CLASSES_DEFINED_LIMIT
|
||||
expression = parser.parseExpression("4 + 5");
|
||||
assertEquals(9, (int) expression.getValue(Integer.class));
|
||||
assertCanCompile(expression);
|
||||
f.setAccessible(true);
|
||||
CompiledExpression cEx = (CompiledExpression) f.get(expression);
|
||||
classloadersUsed.add(cEx.getClass().getClassLoader());
|
||||
assertEquals(9, (int) expression.getValue(Integer.class));
|
||||
}
|
||||
assertTrue(classloadersUsed.size() > 1);
|
||||
}
|
||||
|
||||
|
||||
// helper methods
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -26,8 +26,9 @@ import static org.junit.Assert.*;
|
|||
|
||||
/**
|
||||
* Checks the speed of compiled SpEL expressions.
|
||||
* By default these tests are marked Ignore since they can fail on a busy machine because they
|
||||
* compare relative performance of interpreted vs compiled.
|
||||
*
|
||||
* <p>By default these tests are marked @Ignore since they can fail on a busy machine
|
||||
* because they compare relative performance of interpreted vs compiled.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @since 4.1
|
||||
|
@ -35,37 +36,14 @@ import static org.junit.Assert.*;
|
|||
@Ignore
|
||||
public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
||||
|
||||
int count = 50000; // Number of evaluations that are timed in one run
|
||||
int iterations = 10; // Number of times to repeat 'count' evaluations (for averaging)
|
||||
int count = 50000; // number of evaluations that are timed in one run
|
||||
|
||||
int iterations = 10; // number of times to repeat 'count' evaluations (for averaging)
|
||||
|
||||
private final static boolean noisyTests = true;
|
||||
|
||||
Expression expression;
|
||||
|
||||
public static class Payload {
|
||||
Two[] DR = new Two[]{new Two()};
|
||||
|
||||
public Two[] getDR() {
|
||||
return DR;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Two {
|
||||
Three DRFixedSection = new Three();
|
||||
public Three getDRFixedSection() {
|
||||
return DRFixedSection;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Three {
|
||||
double duration = 0.4d;
|
||||
public double getDuration() {
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NumberHolder {
|
||||
public int payload = 36;
|
||||
}
|
||||
|
||||
/**
|
||||
* This test verifies the new support for compiling mathematical expressions with
|
||||
|
@ -241,7 +219,6 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
System.out.println("One million iterations: " + (System.currentTimeMillis()-stime) + "ms");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void stringConcatenation() throws Exception {
|
||||
expression = parser.parseExpression("'hello' + getWorld() + ' spring'");
|
||||
|
@ -287,12 +264,6 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
System.out.println("One million iterations: " + (System.currentTimeMillis()-stime) + "ms");
|
||||
}
|
||||
|
||||
public static class Greeter {
|
||||
public String getWorld() {
|
||||
return "world";
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexExpressionPerformance() throws Exception {
|
||||
Payload payload = new Payload();
|
||||
|
@ -313,8 +284,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
long etime = System.currentTimeMillis();
|
||||
long interpretedSpeed = (etime - stime);
|
||||
iTotal+=interpretedSpeed;
|
||||
log(interpretedSpeed+"ms ");
|
||||
iTotal += interpretedSpeed;
|
||||
log(interpretedSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -329,8 +300,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
long etime = System.currentTimeMillis();
|
||||
long compiledSpeed = (etime - stime);
|
||||
cTotal+=compiledSpeed;
|
||||
log(compiledSpeed+"ms ");
|
||||
cTotal += compiledSpeed;
|
||||
log(compiledSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -376,8 +347,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long interpretedSpeed = (etime - stime);
|
||||
interpretedTotal+=interpretedSpeed;
|
||||
log(interpretedSpeed+"ms ");
|
||||
interpretedTotal += interpretedSpeed;
|
||||
log(interpretedSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -392,8 +363,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long compiledSpeed = (etime - stime);
|
||||
compiledTotal+=compiledSpeed;
|
||||
log(compiledSpeed+"ms ");
|
||||
compiledTotal += compiledSpeed;
|
||||
log(compiledSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -407,28 +378,6 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
|
||||
|
||||
|
||||
public static class TestClass2 {
|
||||
public String name = "Santa";
|
||||
private String name2 = "foobar";
|
||||
public String getName2() {
|
||||
return name2;
|
||||
}
|
||||
public Foo foo = new Foo();
|
||||
public static class Foo {
|
||||
public Bar bar = new Bar();
|
||||
Bar b = new Bar();
|
||||
public Bar getBaz() {
|
||||
return b;
|
||||
}
|
||||
public Bar bay() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
public static class Bar {
|
||||
public String boo = "oranges";
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compilingPropertyReferenceField() throws Exception {
|
||||
long interpretedTotal = 0, compiledTotal = 0, stime, etime;
|
||||
|
@ -450,8 +399,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long interpretedSpeed = (etime - stime);
|
||||
interpretedTotal+=interpretedSpeed;
|
||||
log(interpretedSpeed+"ms ");
|
||||
interpretedTotal += interpretedSpeed;
|
||||
log(interpretedSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -466,8 +415,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long compiledSpeed = (etime - stime);
|
||||
compiledTotal+=compiledSpeed;
|
||||
log(compiledSpeed+"ms ");
|
||||
compiledTotal += compiledSpeed;
|
||||
log(compiledSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -481,7 +430,6 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
String interpretedResult = null, compiledResult = null;
|
||||
|
||||
TestClass2 testdata = new TestClass2();
|
||||
|
||||
Expression expression = parser.parseExpression("foo.bar.boo");
|
||||
|
||||
// warmup
|
||||
|
@ -497,8 +445,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long interpretedSpeed = (etime - stime);
|
||||
interpretedTotal+=interpretedSpeed;
|
||||
log(interpretedSpeed+"ms ");
|
||||
interpretedTotal += interpretedSpeed;
|
||||
log(interpretedSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -513,8 +461,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long compiledSpeed = (etime - stime);
|
||||
compiledTotal+=compiledSpeed;
|
||||
log(compiledSpeed+"ms ");
|
||||
compiledTotal += compiledSpeed;
|
||||
log(compiledSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -542,8 +490,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long interpretedSpeed = (etime - stime);
|
||||
interpretedTotal+=interpretedSpeed;
|
||||
log(interpretedSpeed+"ms ");
|
||||
interpretedTotal += interpretedSpeed;
|
||||
log(interpretedSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -558,8 +506,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long compiledSpeed = (etime - stime);
|
||||
compiledTotal+=compiledSpeed;
|
||||
log(compiledSpeed+"ms ");
|
||||
compiledTotal += compiledSpeed;
|
||||
log(compiledSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -635,8 +583,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long interpretedSpeed = (etime - stime);
|
||||
interpretedTotal+=interpretedSpeed;
|
||||
log(interpretedSpeed+"ms ");
|
||||
interpretedTotal += interpretedSpeed;
|
||||
log(interpretedSpeed + "ms ");
|
||||
}
|
||||
logln();
|
||||
|
||||
|
@ -652,8 +600,8 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
}
|
||||
etime = System.currentTimeMillis();
|
||||
long compiledSpeed = (etime - stime);
|
||||
compiledTotal+=compiledSpeed;
|
||||
log(compiledSpeed+"ms ");
|
||||
compiledTotal += compiledSpeed;
|
||||
log(compiledSpeed + "ms ");
|
||||
|
||||
}
|
||||
logln();
|
||||
|
@ -661,21 +609,22 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
assertEquals(interpretedResult,compiledResult);
|
||||
|
||||
reportPerformance("property reference (getter)", interpretedTotal, compiledTotal);
|
||||
if (compiledTotal>=interpretedTotal) {
|
||||
if (compiledTotal >= interpretedTotal) {
|
||||
fail("Compiled version is slower than interpreted!");
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
private void reportPerformance(String title, long interpretedTotal, long compiledTotal) {
|
||||
double averageInterpreted = interpretedTotal/(iterations);
|
||||
double averageCompiled = compiledTotal/(iterations);
|
||||
double ratio = (averageCompiled/averageInterpreted)*100.0d;
|
||||
logln(">>"+title+": average for "+count+": compiled="+averageCompiled+"ms interpreted="+averageInterpreted+"ms: compiled takes " + ((int)ratio)+"% of the interpreted time");
|
||||
if (averageCompiled>averageInterpreted) {
|
||||
fail("Compiled version took longer than interpreted! CompiledSpeed=~"+averageCompiled+
|
||||
"ms InterpretedSpeed="+averageInterpreted+"ms");
|
||||
double averageInterpreted = interpretedTotal / iterations;
|
||||
double averageCompiled = compiledTotal / iterations;
|
||||
double ratio = (averageCompiled / averageInterpreted) * 100.0d;
|
||||
logln(">>" + title + ": average for " + count + ": compiled=" + averageCompiled +
|
||||
"ms interpreted=" + averageInterpreted + "ms: compiled takes " +
|
||||
((int) ratio) + "% of the interpreted time");
|
||||
if (averageCompiled > averageInterpreted) {
|
||||
fail("Compiled version took longer than interpreted! CompiledSpeed=~" + averageCompiled +
|
||||
"ms InterpretedSpeed=" + averageInterpreted + "ms");
|
||||
}
|
||||
logln();
|
||||
}
|
||||
|
@ -688,7 +637,7 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
|
||||
private void logln(String... message) {
|
||||
if (noisyTests) {
|
||||
if (message!=null && message.length>0) {
|
||||
if (message.length > 0) {
|
||||
System.out.println(message[0]);
|
||||
}
|
||||
else {
|
||||
|
@ -700,4 +649,84 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
|
|||
private void compile(Expression expression) {
|
||||
assertTrue(SpelCompiler.compile(expression));
|
||||
}
|
||||
|
||||
|
||||
public static class Payload {
|
||||
|
||||
Two[] DR = new Two[]{new Two()};
|
||||
|
||||
public Two[] getDR() {
|
||||
return DR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Two {
|
||||
|
||||
Three DRFixedSection = new Three();
|
||||
|
||||
public Three getDRFixedSection() {
|
||||
return DRFixedSection;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Three {
|
||||
|
||||
double duration = 0.4d;
|
||||
|
||||
public double getDuration() {
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class NumberHolder {
|
||||
|
||||
public int payload = 36;
|
||||
}
|
||||
|
||||
|
||||
public static class Greeter {
|
||||
|
||||
public String getWorld() {
|
||||
return "world";
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestClass2 {
|
||||
|
||||
public String name = "Santa";
|
||||
|
||||
private String name2 = "foobar";
|
||||
|
||||
public String getName2() {
|
||||
return name2;
|
||||
}
|
||||
|
||||
public Foo foo = new Foo();
|
||||
}
|
||||
|
||||
|
||||
public static class Foo {
|
||||
|
||||
public Bar bar = new Bar();
|
||||
|
||||
Bar b = new Bar();
|
||||
|
||||
public Bar getBaz() {
|
||||
return b;
|
||||
}
|
||||
|
||||
public Bar bay() {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Bar {
|
||||
|
||||
public String boo = "oranges";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue