/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package org.apache.commons.ognl.test; | |
import org.apache.commons.ognl.Ognl; | |
import org.apache.commons.ognl.OgnlContext; | |
import org.apache.commons.ognl.OgnlException; | |
import org.apache.commons.ognl.SimpleNode; | |
import org.apache.commons.ognl.test.objects.Bean1; | |
import java.lang.reflect.Method; | |
import java.text.DecimalFormat; | |
import java.text.NumberFormat; | |
public class Performance | |
{ | |
private static int MAX_ITERATIONS = -1; | |
private static boolean ITERATIONS_MODE; | |
private static long MAX_TIME = -1L; | |
private static boolean TIME_MODE; | |
private static final NumberFormat FACTOR_FORMAT = new DecimalFormat( "0.000" ); | |
private final String _name; | |
private final OgnlContext _context = (OgnlContext) Ognl.createDefaultContext( null ); | |
private final Bean1 _root = new Bean1(); | |
private SimpleNode _expression; | |
private SimpleNode _compiledExpression; | |
private final Method _method; | |
private int _iterations; | |
private final String _expressionString; | |
private boolean _isMvel = false; | |
private long t0; | |
private long t1; | |
/* | |
* =================================================================== Private static classes | |
* =================================================================== | |
*/ | |
private static class Results | |
{ | |
int iterations; | |
long time; | |
boolean mvel; | |
public Results( int iterations, long time, boolean mvel ) | |
{ | |
this.iterations = iterations; | |
this.time = time; | |
this.mvel = mvel; | |
} | |
public String getFactor( Results otherResults ) | |
{ | |
String ret; | |
if ( TIME_MODE ) | |
{ | |
float factor; | |
if ( iterations < otherResults.iterations ) | |
{ | |
factor = | |
Math.max( (float) otherResults.iterations, (float) iterations ) | |
/ Math.min( (float) otherResults.iterations, (float) iterations ); | |
} | |
else | |
{ | |
factor = | |
Math.min( (float) otherResults.iterations, (float) iterations ) | |
/ Math.max( (float) otherResults.iterations, (float) iterations ); | |
} | |
ret = FACTOR_FORMAT.format( factor ); | |
if ( iterations > otherResults.iterations ) | |
ret += " times faster than "; | |
else | |
ret += " times slower than "; | |
} | |
else | |
{ | |
float factor = | |
Math.max( (float) otherResults.time, (float) time ) | |
/ Math.min( (float) otherResults.time, (float) time ); | |
ret = FACTOR_FORMAT.format( factor ); | |
if ( time < otherResults.time ) | |
ret += " times faster than "; | |
else | |
ret += " times slower than "; | |
} | |
return ret; | |
} | |
} | |
/* | |
* =================================================================== Public static methods | |
* =================================================================== | |
*/ | |
public static void main( String[] args ) | |
{ | |
for ( int i = 0; i < args.length; i++ ) | |
{ | |
if ( args[i].equals( "-time" ) ) | |
{ | |
TIME_MODE = true; | |
MAX_TIME = Long.parseLong( args[++i] ); | |
} | |
else if ( args[i].equals( "-iterations" ) ) | |
{ | |
ITERATIONS_MODE = true; | |
MAX_ITERATIONS = Integer.parseInt( args[++i] ); | |
} | |
} | |
if ( !TIME_MODE && !ITERATIONS_MODE ) | |
{ | |
TIME_MODE = true; | |
MAX_TIME = 1500; | |
} | |
try | |
{ | |
Performance[] tests = | |
new Performance[] { | |
new Performance( "Constant", "100 + 20 * 5", "testConstantExpression" ), | |
// new Performance("Constant", "100 + 20 * 5", "testConstantExpression", false), | |
new Performance( "Single Property", "bean2", "testSinglePropertyExpression" ), | |
new Performance( "Property Navigation", "bean2.bean3.value", "testPropertyNavigationExpression" ), | |
/* | |
* new Performance("Property Setting with context key", "bean2.bean3.nullValue", | |
* "testPropertyNavigationSetting"), new Performance("Property Setting with context key", | |
* "bean2.bean3.nullValue", "testPropertyNavigationSetting", true), | |
*/ | |
new Performance( "Property Navigation and Comparison", "bean2.bean3.value <= 24", | |
"testPropertyNavigationAndComparisonExpression" ), | |
/* | |
* new Performance("Property Navigation with Indexed Access", "bean2.bean3.indexedValue[25]", | |
* "testIndexedPropertyNavigationExpression"), new | |
* Performance("Property Navigation with Indexed Access", "bean2.bean3.indexedValue[25]", | |
* "testIndexedPropertyNavigationExpression", true), | |
*/ | |
new Performance( "Property Navigation with Map Access", "bean2.bean3.map['foo']", | |
"testPropertyNavigationWithMapExpression" ), | |
/* | |
* new Performance("Property Navigation with Map value set", "bean2.bean3.map['foo']", | |
* "testPropertyNavigationWithMapSetting"), new Performance("Property Navigation with Map value set", | |
* "bean2.bean3.map['foo']", "testPropertyNavigationWithMapSetting", true) | |
*/ | |
}; | |
boolean timeMode = TIME_MODE; | |
boolean iterMode = ITERATIONS_MODE; | |
long maxTime = MAX_TIME; | |
int maxIterations = MAX_ITERATIONS; | |
// TIME_MODE = false; | |
// ITERATIONS_MODE = true; | |
// maxIterations = 1000; | |
runTests( tests, false ); | |
TIME_MODE = timeMode; | |
ITERATIONS_MODE = iterMode; | |
MAX_TIME = maxTime; | |
MAX_ITERATIONS = maxIterations; | |
System.out.println( "\n\n============================================================================\n" ); | |
Thread.sleep( 2500 ); | |
runTests( tests, true ); | |
// Thread.sleep(2000); | |
System.out.println( "\n\n============================================================================\n" ); | |
// runTests(tests); | |
} | |
catch ( Exception ex ) | |
{ | |
ex.printStackTrace(); | |
} | |
} | |
static void runTests( Performance[] tests, boolean output ) | |
throws Exception | |
{ | |
for ( Performance perf : tests ) | |
{ | |
try | |
{ | |
Results javaResults = perf.testJava( ), interpretedResults = perf.testExpression( false ), | |
compiledResults = perf.testExpression( true ); | |
if ( !output ) | |
{ | |
return; | |
} | |
System.out.println( ( compiledResults.mvel ? "MVEL" : "OGNL" ) + " " + perf.getName( ) + ": " | |
+ perf.getExpression( ) ); | |
System.out.println( | |
" java: " + javaResults.iterations + " iterations in " + javaResults.time + " ms" ); | |
System.out.println( | |
" compiled: " + compiledResults.iterations + " iterations in " + compiledResults.time + " ms (" | |
+ compiledResults.getFactor( javaResults ) + "java)" ); | |
System.out.println( | |
"interpreted: " + interpretedResults.iterations + " iterations in " + interpretedResults.time | |
+ " ms (" + interpretedResults.getFactor( javaResults ) + "java)" ); | |
System.out.println( ); | |
} | |
catch ( OgnlException ex ) | |
{ | |
ex.printStackTrace( ); | |
} | |
} | |
} | |
/* | |
* =================================================================== Constructors | |
* =================================================================== | |
*/ | |
public Performance( String name, String expressionString, String javaMethodName ) | |
throws Exception | |
{ | |
this( name, expressionString, javaMethodName, false ); | |
} | |
public Performance( String name, String expressionString, String javaMethodName, boolean mvel ) | |
throws Exception | |
{ | |
_name = name; | |
_isMvel = mvel; | |
_expressionString = expressionString; | |
try | |
{ | |
_method = getClass().getMethod( javaMethodName ); | |
} | |
catch ( Exception ex ) | |
{ | |
throw new OgnlException( "java method not found", ex ); | |
} | |
if ( !_isMvel ) | |
{ | |
_expression = (SimpleNode) Ognl.parseExpression( expressionString ); | |
_compiledExpression = (SimpleNode) Ognl.compileExpression( _context, _root, expressionString ); | |
Ognl.getValue( _expression, _context, _root ); | |
_context.put( "contextValue", "cvalue" ); | |
} | |
else | |
{ | |
// _mvelCompiled = MVEL.compileExpression(expressionString); | |
} | |
} | |
/* | |
* =================================================================== Protected methods | |
* =================================================================== | |
*/ | |
protected void startTest() | |
{ | |
_iterations = 0; | |
t0 = t1 = System.currentTimeMillis(); | |
} | |
protected Results endTest() | |
{ | |
return new Results( _iterations, t1 - t0, _isMvel ); | |
} | |
protected boolean done() | |
{ | |
_iterations++; | |
t1 = System.currentTimeMillis(); | |
if ( TIME_MODE ) | |
{ | |
return ( t1 - t0 ) >= MAX_TIME; | |
} | |
if ( ITERATIONS_MODE ) | |
{ | |
return _iterations >= MAX_ITERATIONS; | |
} | |
throw new RuntimeException( "no maximums specified" ); | |
} | |
/* | |
* =================================================================== Public methods | |
* =================================================================== | |
*/ | |
public String getName() | |
{ | |
return _name; | |
} | |
public String getExpression() | |
{ | |
return _expressionString; | |
} | |
public Results testExpression( boolean compiled ) | |
throws Exception | |
{ | |
startTest(); | |
do | |
{ | |
if ( !_isMvel ) | |
{ | |
if ( compiled ) | |
Ognl.getValue( _compiledExpression.getAccessor(), _context, _root ); | |
else | |
Ognl.getValue( _expression, _context, _root ); | |
} | |
else | |
{ | |
/* | |
* if (compiled) MVEL.executeExpression(_mvelCompiled, _root); else MVEL.eval(_expressionString, _root); | |
*/ | |
} | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
public Results testJava() | |
throws OgnlException | |
{ | |
try | |
{ | |
return (Results) _method.invoke( this ); | |
} | |
catch ( Exception ex ) | |
{ | |
throw new OgnlException( "invoking java method '" + _method.getName() + "'", ex ); | |
} | |
} | |
public Results testConstantExpression() | |
throws OgnlException | |
{ | |
startTest(); | |
do | |
{ | |
@SuppressWarnings( "unused" ) | |
int result = 100 + 20 * 5; | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
public Results testSinglePropertyExpression() | |
throws OgnlException | |
{ | |
startTest(); | |
do | |
{ | |
_root.getBean2(); | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
public Results testPropertyNavigationExpression() | |
throws OgnlException | |
{ | |
startTest(); | |
do | |
{ | |
_root.getBean2().getBean3().getValue(); | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
public Results testPropertyNavigationSetting() | |
throws OgnlException | |
{ | |
startTest(); | |
do | |
{ | |
_root.getBean2().getBean3().setNullValue( "a value" ); | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
public Results testPropertyNavigationAndComparisonExpression() | |
throws OgnlException | |
{ | |
startTest(); | |
do | |
{ | |
@SuppressWarnings( "unused" ) | |
boolean result = _root.getBean2().getBean3().getValue() < 24; | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
public Results testIndexedPropertyNavigationExpression() | |
throws OgnlException | |
{ | |
startTest(); | |
do | |
{ | |
_root.getBean2().getBean3().getIndexedValue( 25 ); | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
public Results testPropertyNavigationWithMapSetting() | |
throws OgnlException | |
{ | |
startTest(); | |
do | |
{ | |
_root.getBean2().getBean3().getMap().put( "bam", "bam" ); | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
public Results testPropertyNavigationWithMapExpression() | |
throws OgnlException | |
{ | |
startTest(); | |
do | |
{ | |
_root.getBean2().getBean3().getMap().get( "foo" ); | |
} | |
while ( !done() ); | |
return endTest(); | |
} | |
} |