Browse Source

Polishing

pull/1477/head
Juergen Hoeller 7 years ago
parent
commit
efc5b47b9a
  1. 78
      spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java
  2. 217
      spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationPerformanceTests.java

78
spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java

@ -48,8 +48,7 @@ import org.springframework.expression.spel.testdata.PersonInOtherPackage; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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

217
spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationPerformanceTests.java

@ -1,5 +1,5 @@ @@ -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.*; @@ -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.*; @@ -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)
private final static boolean noisyTests = true;
int count = 50000; // number of evaluations that are timed in one run
Expression expression;
public static class Payload {
Two[] DR = new Two[]{new Two()};
public Two[] getDR() {
return DR;
}
}
int iterations = 10; // number of times to repeat 'count' evaluations (for averaging)
public static class Two {
Three DRFixedSection = new Three();
public Three getDRFixedSection() {
return DRFixedSection;
}
}
private final static boolean noisyTests = true;
public static class Three {
double duration = 0.4d;
public double getDuration() {
return duration;
}
}
Expression expression;
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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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…
Cancel
Save