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 }