001: //--------------------------------------------------------------------------
002: // Copyright (c) 2004, Drew Davidson and Luke Blanshard
003: // All rights reserved.
004: //
005: // Redistribution and use in source and binary forms, with or without
006: // modification, are permitted provided that the following conditions are
007: // met:
008: //
009: // Redistributions of source code must retain the above copyright notice,
010: // this list of conditions and the following disclaimer.
011: // Redistributions in binary form must reproduce the above copyright
012: // notice, this list of conditions and the following disclaimer in the
013: // documentation and/or other materials provided with the distribution.
014: // Neither the name of the Drew Davidson nor the names of its contributors
015: // may be used to endorse or promote products derived from this software
016: // without specific prior written permission.
017: //
018: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
019: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
020: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
021: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
022: // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
023: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
024: // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
025: // OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026: // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
027: // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
028: // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
029: // DAMAGE.
030: //--------------------------------------------------------------------------
031: package org.ognl.test;
032:
033: import java.lang.reflect.*;
034: import java.text.*;
035: import ognl.Ognl;
036: import ognl.OgnlContext;
037: import ognl.OgnlException;
038: import ognl.OgnlRuntime;
039: import ognl.SimpleNode;
040: import org.ognl.test.objects.Bean1;
041:
042: public class Performance extends Object {
043: private static int MAX_ITERATIONS = -1;
044: private static boolean ITERATIONS_MODE;
045: private static long MAX_TIME = -1L;
046: private static boolean TIME_MODE;
047: private static NumberFormat FACTOR_FORMAT = new DecimalFormat("0.0");
048:
049: private String name;
050: private OgnlContext context = (OgnlContext) Ognl
051: .createDefaultContext(null);
052: private Bean1 root = new Bean1();
053: private SimpleNode expression;
054: private Method method;
055: private int iterations;
056: private long t0;
057: private long t1;
058:
059: /*===================================================================
060: Private static classes
061: ===================================================================*/
062: private static class Results {
063: int iterations;
064: long time;
065:
066: public Results(int iterations, long time) {
067: super ();
068: this .iterations = iterations;
069: this .time = time;
070: }
071:
072: public float getFactor(Results otherResults) {
073: if (TIME_MODE) {
074: return Math.max((float) otherResults.iterations,
075: (float) iterations)
076: / Math.min((float) otherResults.iterations,
077: (float) iterations);
078: }
079: return Math.max((float) otherResults.time, (float) time)
080: / Math.min((float) otherResults.time, (float) time);
081: }
082: }
083:
084: /*===================================================================
085: Public static methods
086: ===================================================================*/
087: public static void main(String[] args) {
088: for (int i = 0; i < args.length; i++) {
089: if (args[i].equals("-time")) {
090: TIME_MODE = true;
091: MAX_TIME = Long.parseLong(args[++i]);
092: } else if (args[i].equals("-iterations")) {
093: ITERATIONS_MODE = true;
094: MAX_ITERATIONS = Integer.parseInt(args[++i]);
095: }
096: }
097: if (!TIME_MODE && !ITERATIONS_MODE) {
098: TIME_MODE = true;
099: MAX_TIME = 1000;
100: }
101: OgnlRuntime.setPropertyAccessor(Object.class,
102: new CompilingPropertyAccessor());
103: try {
104: Performance[] tests = new Performance[] {
105: new Performance("Constant", "100 + 20 * 5",
106: "testConstantExpression"),
107: new Performance("Single Property", "bean2",
108: "testSinglePropertyExpression"),
109: new Performance("Property Navigation",
110: "bean2.bean3.value",
111: "testPropertyNavigationExpression"),
112: new Performance(
113: "Property Navigation and Comparison",
114: "bean2.bean3.value <= 24",
115: "testPropertyNavigationAndComparisonExpression"),
116: new Performance(
117: "Property Navigation with Indexed Access",
118: "bean2.bean3.indexedValue[25]",
119: "testIndexedPropertyNavigationExpression"),
120: new Performance(
121: "Property Navigation with Map Access",
122: "bean2.bean3.map['foo']",
123: "testPropertyNavigationWithMapExpression"), };
124:
125: for (int i = 0; i < tests.length; i++) {
126: Performance perf = tests[i];
127:
128: try {
129: Results javaResults = perf.testJava(), interpretedResults = perf
130: .testExpression(false), compiledResults = perf
131: .testExpression(true);
132:
133: System.out.println(perf.getName() + ": "
134: + perf.getExpression().toString());
135: System.out.println(" java: "
136: + javaResults.iterations
137: + " iterations in " + javaResults.time
138: + " ms");
139: System.out.println(" compiled: "
140: + compiledResults.iterations
141: + " iterations in "
142: + compiledResults.time
143: + " ms ("
144: + FACTOR_FORMAT.format(compiledResults
145: .getFactor(javaResults))
146: + " times slower than java)");
147: System.out.println("interpreted: "
148: + interpretedResults.iterations
149: + " iterations in "
150: + interpretedResults.time
151: + " ms ("
152: + FACTOR_FORMAT.format(interpretedResults
153: .getFactor(javaResults))
154: + " times slower than java)");
155: System.out.println();
156: } catch (OgnlException ex) {
157: ex.printStackTrace();
158: }
159: }
160: } catch (Exception ex) {
161: ex.printStackTrace();
162: }
163: }
164:
165: /*===================================================================
166: Constructors
167: ===================================================================*/
168: public Performance(String name, String expressionString,
169: String javaMethodName) throws OgnlException {
170: super ();
171: this .name = name;
172: expression = (SimpleNode) Ognl
173: .parseExpression(expressionString);
174: try {
175: method = getClass().getMethod(javaMethodName,
176: new Class[] {});
177: } catch (Exception ex) {
178: throw new OgnlException("java method not found", ex);
179: }
180: }
181:
182: /*===================================================================
183: Protected methods
184: ===================================================================*/
185: protected void startTest() {
186: iterations = 0;
187: t0 = t1 = System.currentTimeMillis();
188: }
189:
190: protected Results endTest() {
191: return new Results(iterations, t1 - t0);
192: }
193:
194: protected boolean done() {
195: iterations++;
196: t1 = System.currentTimeMillis();
197: if (TIME_MODE) {
198: return (t1 - t0) >= MAX_TIME;
199: } else {
200: if (ITERATIONS_MODE) {
201: return iterations >= MAX_ITERATIONS;
202: } else {
203: throw new RuntimeException("no maximums specified");
204: }
205: }
206: }
207:
208: /*===================================================================
209: Public methods
210: ===================================================================*/
211: public String getName() {
212: return name;
213: }
214:
215: public SimpleNode getExpression() {
216: return expression;
217: }
218:
219: public Results testExpression(boolean compiled)
220: throws OgnlException {
221: if (compiled) {
222: context.put("_compile", Boolean.TRUE);
223: } else {
224: context.remove("_compile");
225: }
226: Ognl.getValue(expression, context, root);
227: startTest();
228: do {
229: Ognl.getValue(expression, context, root);
230: } while (!done());
231: return endTest();
232: }
233:
234: public Results testJava() throws OgnlException {
235: try {
236: return (Results) method.invoke(this , new Object[] {});
237: } catch (Exception ex) {
238: throw new OgnlException("invoking java method '"
239: + method.getName() + "'", ex);
240: }
241: }
242:
243: public Results testConstantExpression() throws OgnlException {
244: startTest();
245: do {
246: int result = 100 + 20 * 5;
247: } while (!done());
248: return endTest();
249: }
250:
251: public Results testSinglePropertyExpression() throws OgnlException {
252: startTest();
253: do {
254: root.getBean2();
255: } while (!done());
256: return endTest();
257: }
258:
259: public Results testPropertyNavigationExpression()
260: throws OgnlException {
261: startTest();
262: do {
263: root.getBean2().getBean3().getValue();
264: } while (!done());
265: return endTest();
266: }
267:
268: public Results testPropertyNavigationAndComparisonExpression()
269: throws OgnlException {
270: startTest();
271: do {
272: boolean result = root.getBean2().getBean3().getValue() < 24;
273: } while (!done());
274: return endTest();
275: }
276:
277: public Results testIndexedPropertyNavigationExpression()
278: throws OgnlException {
279: startTest();
280: do {
281: root.getBean2().getBean3().getIndexedValue(25);
282: } while (!done());
283: return endTest();
284: }
285:
286: public Results testPropertyNavigationWithMapExpression()
287: throws OgnlException {
288: startTest();
289: do {
290: root.getBean2().getBean3().getMap().get("foo");
291: } while (!done());
292: return endTest();
293: }
294: }
|