Browse Source

Polishing

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

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

@ -48,8 +48,7 @@ import org.springframework.expression.spel.testdata.PersonInOtherPackage;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* Checks the behaviour of the SpelCompiler. * Checks SpelCompiler behavior. This should cover compilation all compiled node types.
* This should cover compilation all compiled node types.
* *
* @author Andy Clement * @author Andy Clement
* @since 4.1 * @since 4.1
@ -324,29 +323,9 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
double resultC = expression.getValue(new TestClass1(), Double.TYPE); double resultC = expression.getValue(new TestClass1(), Double.TYPE);
assertEquals(3.4d, resultI, 0.1d); assertEquals(3.4d, resultI, 0.1d);
assertEquals(3.4d, resultC, 0.1d); assertEquals(3.4d, resultC, 0.1d);
assertEquals(3.4d, expression.getValue()); 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") @SuppressWarnings("rawtypes")
@Test @Test
public void inlineList() throws Exception { public void inlineList() throws Exception {
@ -476,8 +455,7 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
assertCanCompile(expression); assertCanCompile(expression);
assertEquals(new Integer(42), expression.getValue(Integer.class)); assertEquals(new Integer(42), expression.getValue(Integer.class));
// Code gen is different for -1 .. 6 because there are bytecode instructions specifically for those // Code gen is different for -1 .. 6 because there are bytecode instructions specifically for those values
// values
// Not an int literal but an opminus with one operand: // Not an int literal but an opminus with one operand:
// expression = parser.parseExpression("-1"); // expression = parser.parseExpression("-1");
@ -4372,7 +4350,8 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
expression = parser.parseExpression("DR[0].three"); expression = parser.parseExpression("DR[0].three");
Object v = expression.getValue(payload); 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"); Expression expression = parser.parseExpression("DR[0].three.four lt 0.1d?#root:null");
v = expression.getValue(payload); v = expression.getValue(payload);
@ -4620,14 +4599,16 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
@Test @Test
public void indexerMapAccessor_12045() throws Exception { 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); SpelExpressionParser sep = new SpelExpressionParser(spc);
expression=sep.parseExpression("headers[command]"); expression=sep.parseExpression("headers[command]");
MyMessage root = new MyMessage(); MyMessage root = new MyMessage();
assertEquals("wibble", expression.getValue(root)); assertEquals("wibble", expression.getValue(root));
// This next call was failing because the isCompilable check in Indexer did not check on the key being compilable // This next call was failing because the isCompilable check in Indexer
// (and also generateCode in the Indexer was missing the optimization that it didn't need necessarily need to call // did not check on the key being compilable (and also generateCode in the
// generateCode for that accessor) // Indexer was missing the optimization that it didn't need necessarily
// need to call generateCode for that accessor)
assertEquals("wibble", expression.getValue(root)); assertEquals("wibble", expression.getValue(root));
assertCanCompile(expression); assertCanCompile(expression);
@ -4803,6 +4784,25 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
assertIsCompiled(exp); 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 // helper methods

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

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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. * 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 * @author Andy Clement
* @since 4.1 * @since 4.1
@ -35,37 +36,14 @@ import static org.junit.Assert.*;
@Ignore @Ignore
public class SpelCompilationPerformanceTests extends AbstractExpressionTests { public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
int count = 50000; // Number of evaluations that are timed in one run 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; int iterations = 10; // number of times to repeat 'count' evaluations (for averaging)
public static class Payload {
Two[] DR = new Two[]{new Two()};
public Two[] getDR() {
return DR;
}
}
public static class Two { private final static boolean noisyTests = true;
Three DRFixedSection = new Three();
public Three getDRFixedSection() {
return DRFixedSection;
}
}
public static class Three { Expression expression;
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 * 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"); System.out.println("One million iterations: " + (System.currentTimeMillis()-stime) + "ms");
} }
@Test @Test
public void stringConcatenation() throws Exception { public void stringConcatenation() throws Exception {
expression = parser.parseExpression("'hello' + getWorld() + ' spring'"); 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"); System.out.println("One million iterations: " + (System.currentTimeMillis()-stime) + "ms");
} }
public static class Greeter {
public String getWorld() {
return "world";
}
}
@Test @Test
public void complexExpressionPerformance() throws Exception { public void complexExpressionPerformance() throws Exception {
Payload payload = new Payload(); Payload payload = new Payload();
@ -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 @Test
public void compilingPropertyReferenceField() throws Exception { public void compilingPropertyReferenceField() throws Exception {
long interpretedTotal = 0, compiledTotal = 0, stime, etime; long interpretedTotal = 0, compiledTotal = 0, stime, etime;
@ -481,7 +430,6 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
String interpretedResult = null, compiledResult = null; String interpretedResult = null, compiledResult = null;
TestClass2 testdata = new TestClass2(); TestClass2 testdata = new TestClass2();
Expression expression = parser.parseExpression("foo.bar.boo"); Expression expression = parser.parseExpression("foo.bar.boo");
// warmup // warmup
@ -666,13 +614,14 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
} }
} }
// ---
private void reportPerformance(String title, long interpretedTotal, long compiledTotal) { private void reportPerformance(String title, long interpretedTotal, long compiledTotal) {
double averageInterpreted = interpretedTotal/(iterations); double averageInterpreted = interpretedTotal / iterations;
double averageCompiled = compiledTotal/(iterations); double averageCompiled = compiledTotal / iterations;
double ratio = (averageCompiled / averageInterpreted) * 100.0d; 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"); logln(">>" + title + ": average for " + count + ": compiled=" + averageCompiled +
"ms interpreted=" + averageInterpreted + "ms: compiled takes " +
((int) ratio) + "% of the interpreted time");
if (averageCompiled > averageInterpreted) { if (averageCompiled > averageInterpreted) {
fail("Compiled version took longer than interpreted! CompiledSpeed=~" + averageCompiled + fail("Compiled version took longer than interpreted! CompiledSpeed=~" + averageCompiled +
"ms InterpretedSpeed=" + averageInterpreted + "ms"); "ms InterpretedSpeed=" + averageInterpreted + "ms");
@ -688,7 +637,7 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
private void logln(String... message) { private void logln(String... message) {
if (noisyTests) { if (noisyTests) {
if (message!=null && message.length>0) { if (message.length > 0) {
System.out.println(message[0]); System.out.println(message[0]);
} }
else { else {
@ -700,4 +649,84 @@ public class SpelCompilationPerformanceTests extends AbstractExpressionTests {
private void compile(Expression expression) { private void compile(Expression expression) {
assertTrue(SpelCompiler.compile(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