View Javadoc

1   /*
2    * $Id: Performance.java 1188815 2011-10-25 17:31:01Z mcucchiara $
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   * http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   */
20  package org.apache.commons.ognl.test;
21  
22  import org.apache.commons.ognl.Ognl;
23  import org.apache.commons.ognl.OgnlContext;
24  import org.apache.commons.ognl.OgnlException;
25  import org.apache.commons.ognl.SimpleNode;
26  import org.apache.commons.ognl.test.objects.Bean1;
27  
28  import java.lang.reflect.Method;
29  import java.text.DecimalFormat;
30  import java.text.NumberFormat;
31  
32  public class Performance
33  {
34  
35      private static int MAX_ITERATIONS = -1;
36  
37      private static boolean ITERATIONS_MODE;
38  
39      private static long MAX_TIME = -1L;
40  
41      private static boolean TIME_MODE;
42  
43      private static NumberFormat FACTOR_FORMAT = new DecimalFormat( "0.000" );
44  
45      private String _name;
46  
47      private OgnlContext _context = (OgnlContext) Ognl.createDefaultContext( null );
48  
49      private Bean1 _root = new Bean1();
50  
51      private SimpleNode _expression;
52  
53      private SimpleNode _compiledExpression;
54  
55      private Method _method;
56  
57      private int _iterations;
58  
59      private String _expressionString;
60  
61      private boolean _isMvel = false;
62  
63      private long t0;
64  
65      private long t1;
66  
67      /*
68       * =================================================================== Private static classes
69       * ===================================================================
70       */
71      private static class Results
72      {
73  
74          int iterations;
75  
76          long time;
77  
78          boolean mvel;
79  
80          public Results( int iterations, long time, boolean mvel )
81          {
82              super();
83              this.iterations = iterations;
84              this.time = time;
85              this.mvel = mvel;
86          }
87  
88          public String getFactor( Results otherResults )
89          {
90              String ret;
91  
92              if ( TIME_MODE )
93              {
94                  float factor;
95  
96                  if ( iterations < otherResults.iterations )
97                  {
98                      factor =
99                          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 }