001 /*
002 * $Id: Performance.java 1188815 2011-10-25 17:31:01Z mcucchiara $
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 */
020 package org.apache.commons.ognl.test;
021
022 import org.apache.commons.ognl.Ognl;
023 import org.apache.commons.ognl.OgnlContext;
024 import org.apache.commons.ognl.OgnlException;
025 import org.apache.commons.ognl.SimpleNode;
026 import org.apache.commons.ognl.test.objects.Bean1;
027
028 import java.lang.reflect.Method;
029 import java.text.DecimalFormat;
030 import java.text.NumberFormat;
031
032 public class Performance
033 {
034
035 private static int MAX_ITERATIONS = -1;
036
037 private static boolean ITERATIONS_MODE;
038
039 private static long MAX_TIME = -1L;
040
041 private static boolean TIME_MODE;
042
043 private static NumberFormat FACTOR_FORMAT = new DecimalFormat( "0.000" );
044
045 private String _name;
046
047 private OgnlContext _context = (OgnlContext) Ognl.createDefaultContext( null );
048
049 private Bean1 _root = new Bean1();
050
051 private SimpleNode _expression;
052
053 private SimpleNode _compiledExpression;
054
055 private Method _method;
056
057 private int _iterations;
058
059 private String _expressionString;
060
061 private boolean _isMvel = false;
062
063 private long t0;
064
065 private long t1;
066
067 /*
068 * =================================================================== Private static classes
069 * ===================================================================
070 */
071 private static class Results
072 {
073
074 int iterations;
075
076 long time;
077
078 boolean mvel;
079
080 public Results( int iterations, long time, boolean mvel )
081 {
082 super();
083 this.iterations = iterations;
084 this.time = time;
085 this.mvel = mvel;
086 }
087
088 public String getFactor( Results otherResults )
089 {
090 String ret;
091
092 if ( TIME_MODE )
093 {
094 float factor;
095
096 if ( iterations < otherResults.iterations )
097 {
098 factor =
099 Math.max( (float) otherResults.iterations, (float) iterations )
100 / Math.min( (float) otherResults.iterations, (float) iterations );
101 }
102 else
103 {
104 factor =
105 Math.min( (float) otherResults.iterations, (float) iterations )
106 / Math.max( (float) otherResults.iterations, (float) iterations );
107 }
108
109 ret = FACTOR_FORMAT.format( factor );
110 if ( iterations > otherResults.iterations )
111 ret += " times faster than ";
112 else
113 ret += " times slower than ";
114
115 }
116 else
117 {
118 float factor =
119 Math.max( (float) otherResults.time, (float) time )
120 / Math.min( (float) otherResults.time, (float) time );
121
122 ret = FACTOR_FORMAT.format( factor );
123 if ( time < otherResults.time )
124 ret += " times faster than ";
125 else
126 ret += " times slower than ";
127 }
128
129 return ret;
130 }
131 }
132
133 /*
134 * =================================================================== Public static methods
135 * ===================================================================
136 */
137 public static void main( String[] args )
138 {
139 for ( int i = 0; i < args.length; i++ )
140 {
141 if ( args[i].equals( "-time" ) )
142 {
143 TIME_MODE = true;
144 MAX_TIME = Long.parseLong( args[++i] );
145 }
146 else if ( args[i].equals( "-iterations" ) )
147 {
148 ITERATIONS_MODE = true;
149 MAX_ITERATIONS = Integer.parseInt( args[++i] );
150 }
151 }
152 if ( !TIME_MODE && !ITERATIONS_MODE )
153 {
154 TIME_MODE = true;
155 MAX_TIME = 1500;
156 }
157
158 try
159 {
160 Performance[] tests =
161 new Performance[] {
162 new Performance( "Constant", "100 + 20 * 5", "testConstantExpression" ),
163 // new Performance("Constant", "100 + 20 * 5", "testConstantExpression", false),
164 new Performance( "Single Property", "bean2", "testSinglePropertyExpression" ),
165 new Performance( "Property Navigation", "bean2.bean3.value", "testPropertyNavigationExpression" ),
166 /*
167 * new Performance("Property Setting with context key", "bean2.bean3.nullValue",
168 * "testPropertyNavigationSetting"), new Performance("Property Setting with context key",
169 * "bean2.bean3.nullValue", "testPropertyNavigationSetting", true),
170 */
171 new Performance( "Property Navigation and Comparison", "bean2.bean3.value <= 24",
172 "testPropertyNavigationAndComparisonExpression" ),
173 /*
174 * new Performance("Property Navigation with Indexed Access", "bean2.bean3.indexedValue[25]",
175 * "testIndexedPropertyNavigationExpression"), new
176 * Performance("Property Navigation with Indexed Access", "bean2.bean3.indexedValue[25]",
177 * "testIndexedPropertyNavigationExpression", true),
178 */
179 new Performance( "Property Navigation with Map Access", "bean2.bean3.map['foo']",
180 "testPropertyNavigationWithMapExpression" ),
181 /*
182 * new Performance("Property Navigation with Map value set", "bean2.bean3.map['foo']",
183 * "testPropertyNavigationWithMapSetting"), new Performance("Property Navigation with Map value set",
184 * "bean2.bean3.map['foo']", "testPropertyNavigationWithMapSetting", true)
185 */
186 };
187
188 boolean timeMode = TIME_MODE;
189 boolean iterMode = ITERATIONS_MODE;
190 long maxTime = MAX_TIME;
191 int maxIterations = MAX_ITERATIONS;
192
193 // TIME_MODE = false;
194 // ITERATIONS_MODE = true;
195 // maxIterations = 1000;
196
197 runTests( tests, false );
198
199 TIME_MODE = timeMode;
200 ITERATIONS_MODE = iterMode;
201 MAX_TIME = maxTime;
202 MAX_ITERATIONS = maxIterations;
203
204 System.out.println( "\n\n============================================================================\n" );
205
206 Thread.sleep( 2500 );
207 runTests( tests, true );
208
209 // Thread.sleep(2000);
210
211 System.out.println( "\n\n============================================================================\n" );
212 // runTests(tests);
213
214 }
215 catch ( Exception ex )
216 {
217 ex.printStackTrace();
218 }
219 }
220
221 static void runTests( Performance[] tests, boolean output )
222 throws Exception
223 {
224 for ( Performance perf : tests )
225 {
226 try
227 {
228
229 Results javaResults = perf.testJava( ), interpretedResults = perf.testExpression( false ),
230 compiledResults = perf.testExpression( true );
231
232 if ( !output )
233 {
234 return;
235 }
236
237 System.out.println( ( compiledResults.mvel ? "MVEL" : "OGNL" ) + " " + perf.getName( ) + ": "
238 + perf.getExpression( ) );
239 System.out.println(
240 " java: " + javaResults.iterations + " iterations in " + javaResults.time + " ms" );
241
242 System.out.println(
243 " compiled: " + compiledResults.iterations + " iterations in " + compiledResults.time + " ms ("
244 + compiledResults.getFactor( javaResults ) + "java)" );
245
246 System.out.println(
247 "interpreted: " + interpretedResults.iterations + " iterations in " + interpretedResults.time
248 + " ms (" + interpretedResults.getFactor( javaResults ) + "java)" );
249
250 System.out.println( );
251
252 }
253 catch ( OgnlException ex )
254 {
255 ex.printStackTrace( );
256 }
257 }
258 }
259
260 /*
261 * =================================================================== Constructors
262 * ===================================================================
263 */
264 public Performance( String name, String expressionString, String javaMethodName )
265 throws Exception
266 {
267 this( name, expressionString, javaMethodName, false );
268 }
269
270 public Performance( String name, String expressionString, String javaMethodName, boolean mvel )
271 throws Exception
272 {
273 _name = name;
274 _isMvel = mvel;
275 _expressionString = expressionString;
276
277 try
278 {
279 _method = getClass().getMethod( javaMethodName, new Class[] {} );
280 }
281 catch ( Exception ex )
282 {
283 throw new OgnlException( "java method not found", ex );
284 }
285
286 if ( !_isMvel )
287 {
288 _expression = (SimpleNode) Ognl.parseExpression( expressionString );
289 _compiledExpression = (SimpleNode) Ognl.compileExpression( _context, _root, expressionString );
290 Ognl.getValue( _expression, _context, _root );
291 _context.put( "contextValue", "cvalue" );
292 }
293 else
294 {
295 // _mvelCompiled = MVEL.compileExpression(expressionString);
296 }
297 }
298
299 /*
300 * =================================================================== Protected methods
301 * ===================================================================
302 */
303 protected void startTest()
304 {
305 _iterations = 0;
306 t0 = t1 = System.currentTimeMillis();
307 }
308
309 protected Results endTest()
310 {
311 return new Results( _iterations, t1 - t0, _isMvel );
312 }
313
314 protected boolean done()
315 {
316 _iterations++;
317 t1 = System.currentTimeMillis();
318
319 if ( TIME_MODE )
320 {
321 return ( t1 - t0 ) >= MAX_TIME;
322 }
323 else
324 {
325 if ( ITERATIONS_MODE )
326 {
327 return _iterations >= MAX_ITERATIONS;
328 }
329 else
330 {
331 throw new RuntimeException( "no maximums specified" );
332 }
333 }
334 }
335
336 /*
337 * =================================================================== Public methods
338 * ===================================================================
339 */
340 public String getName()
341 {
342 return _name;
343 }
344
345 public String getExpression()
346 {
347 return _expressionString;
348 }
349
350 public Results testExpression( boolean compiled )
351 throws Exception
352 {
353 startTest();
354 do
355 {
356 if ( !_isMvel )
357 {
358 if ( compiled )
359 Ognl.getValue( _compiledExpression.getAccessor(), _context, _root );
360 else
361 Ognl.getValue( _expression, _context, _root );
362 }
363 else
364 {
365 /*
366 * if (compiled) MVEL.executeExpression(_mvelCompiled, _root); else MVEL.eval(_expressionString, _root);
367 */
368 }
369 }
370 while ( !done() );
371 return endTest();
372 }
373
374 public Results testJava()
375 throws OgnlException
376 {
377 try
378 {
379 return (Results) _method.invoke( this );
380 }
381 catch ( Exception ex )
382 {
383 throw new OgnlException( "invoking java method '" + _method.getName() + "'", ex );
384 }
385 }
386
387 public Results testConstantExpression()
388 throws OgnlException
389 {
390 startTest();
391 do
392 {
393 @SuppressWarnings( "unused" )
394 int result = 100 + 20 * 5;
395 }
396 while ( !done() );
397 return endTest();
398 }
399
400 public Results testSinglePropertyExpression()
401 throws OgnlException
402 {
403 startTest();
404 do
405 {
406 _root.getBean2();
407 }
408 while ( !done() );
409 return endTest();
410 }
411
412 public Results testPropertyNavigationExpression()
413 throws OgnlException
414 {
415 startTest();
416 do
417 {
418 _root.getBean2().getBean3().getValue();
419 }
420 while ( !done() );
421 return endTest();
422 }
423
424 public Results testPropertyNavigationSetting()
425 throws OgnlException
426 {
427 startTest();
428 do
429 {
430 _root.getBean2().getBean3().setNullValue( "a value" );
431 }
432 while ( !done() );
433 return endTest();
434 }
435
436 public Results testPropertyNavigationAndComparisonExpression()
437 throws OgnlException
438 {
439 startTest();
440 do
441 {
442 @SuppressWarnings( "unused" )
443 boolean result = _root.getBean2().getBean3().getValue() < 24;
444 }
445 while ( !done() );
446 return endTest();
447 }
448
449 public Results testIndexedPropertyNavigationExpression()
450 throws OgnlException
451 {
452 startTest();
453 do
454 {
455 _root.getBean2().getBean3().getIndexedValue( 25 );
456 }
457 while ( !done() );
458 return endTest();
459 }
460
461 public Results testPropertyNavigationWithMapSetting()
462 throws OgnlException
463 {
464 startTest();
465 do
466 {
467 _root.getBean2().getBean3().getMap().put( "bam", "bam" );
468 }
469 while ( !done() );
470 return endTest();
471 }
472
473 public Results testPropertyNavigationWithMapExpression()
474 throws OgnlException
475 {
476 startTest();
477 do
478 {
479 _root.getBean2().getBean3().getMap().get( "foo" );
480 }
481 while ( !done() );
482 return endTest();
483 }
484 }