1   /*
2    * Jour - java profiler and monitoring library
3    *
4    * Copyright (C) 2004 Jour team
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Library General Public
8    * License as published by the Free Software Foundation; either
9    * version 2 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Library General Public License for more details.
15   *
16   * You should have received a copy of the GNU Library General Public
17   * License along with this library; if not, write to the
18   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19   * Boston, MA  02111-1307, USA.
20   */
21  package net.sf.jour.log4j;
22  
23  import org.apache.log4j.xml.DOMConfigurator;
24  
25  import net.sf.jour.timer.SimpleTimer;
26  import net.sf.jour.timer.StatisticsItem;
27  
28  import net.sf.jour.util.PropertiesBase;
29  
30  import org.apache.log4j.LogManager;
31  import org.apache.log4j.Logger;
32  
33  /***
34   * Created on 22.11.2004
35   *
36   * Contributing Author(s):
37   *
38   *   Misha Lifschitz <mishalifschitz at users.sourceforge.net> (Inital implementation)
39   *   Vlad Skarzhevskyy <vlads at users.sourceforge.net> (Inital implementation)
40   *
41   * @author vlads
42   * @version $Revision: 1.6 $ ($Author: vlads $) $Date: 2004/12/09 17:58:41 $
43   */
44  public class PerformanceCase  {
45  
46      public PerformanceCase() {
47      }
48  
49      protected Logger log;
50      protected Logger testLog;
51      protected String name;
52      protected static String subcase;
53  
54      public static int warmUpCount = 3000;
55      public static int executeCount = 10000;
56  	public static int extraStackSize = 0;
57  
58      public void execute() {
59          testLog.debug(name);
60      }
61  
62      public void configure(String configFileName) {
63          if (configFileName != null) {
64              name = configFileName;
65              DOMConfigurator.configure(configFileName);
66      	} else {
67      	    name = this.getClass().getName();
68      	}
69          this.log = Logger.getLogger(PerformanceCase.class);
70          this.testLog = Logger.getLogger("testLog");
71      }
72  
73      static public void main(String[] args) throws Exception {
74          String className = null;
75          String configFileName = null;
76          int threads = 0;
77  
78  		PropertiesBase pargs = new PropertiesBase();
79  		pargs.loadArgs(args);
80  		className = pargs.getProperty("class");
81  		configFileName = pargs.getProperty("config");
82  		subcase = pargs.getProperty("subcase");
83  		extraStackSize = pargs.getIntProperty("extraStackSize");
84  		warmUpCount = pargs.getProperty("warmUpCount", warmUpCount);
85  		executeCount =  pargs.getProperty("executeCount", executeCount);
86  		threads = pargs.getProperty("threads", threads);
87  
88          if (className == null) {
89              className = PerformanceCase.class.getName();
90          }
91  
92          if (threads <= 0) {
93  			RunnerThread runner = new RunnerThread(className, configFileName);
94  			runner.run();
95          } else {
96  			try {
97  				Logger log = Logger.getLogger(PerformanceCase.class);
98  				log.info(threads + " threads " + className);
99  
100 				RunnerThread[] th = new RunnerThread[threads];
101                 SimpleTimer tr = new SimpleTimer();
102 
103                 for (int i = 0; i < threads; i++) {
104                     RunnerThread t = new RunnerThread(className, configFileName);
105                     th[i] = t;
106                     t.start();
107                 }
108 
109                 for (int i = 0; i < th.length; i++) {
110                     th[i].join();
111                 }
112                 tr.end();
113 
114                 log.info(threads + " threads duration = " + tr.text() + " ms");
115                 log.info("~call duration = " + SimpleTimer.text(tr.duration() / (staticTotalCallCount)) + " ms");
116 
117 			} catch (Throwable e) {
118 				Logger.getLogger(PerformanceCase.class).error("Test error", e);
119 			}
120         }
121 
122         LogManager.shutdown();
123     }
124 
125 	public static class RunnerThread extends Thread {
126 
127 		PerformanceCase pc;
128 
129         public RunnerThread(String className, String configFileName) {
130  			try {
131                 Object c = PerformanceCase.class.getClassLoader().loadClass(className).newInstance();
132                 pc = ((PerformanceCase) c);
133                 pc.configure(configFileName);
134             } catch (Exception e) {
135 				Logger.getLogger(PerformanceCase.class).error("Test error", e);
136 				pc = null;
137             }
138         }
139 
140 		public void run() {
141 			if (pc == null) {
142 				return;
143 			}
144 			try {
145 				if (extraStackSize != 0) {
146 					pc.buildExtraStackSize(extraStackSize);
147 				} else {
148 					pc.measureAvg();
149 				}
150 			} catch (Throwable e) {
151 				Logger.getLogger(PerformanceCase.class).error("Test error", e);
152 			}
153 		}
154 	}
155 
156     public int avgCount = 4;
157 
158     long totalCallCount = 0;
159 	static long staticTotalCallCount = 0;
160     double delta = 0;
161     public double measureCase() throws Exception {
162         // warm up
163         Thread.sleep(500);
164         for (int i = 0; i < warmUpCount; ++ i) {
165             this.execute();
166             this.totalCallCount++;
167         }
168         Thread.sleep(500);
169         log.debug("StartTest " + this.getName());
170         SimpleTimer tr_sys = new SimpleTimer(false);
171         SimpleTimer tr = new SimpleTimer();
172         for (int i = 0; i < executeCount; ++ i) {
173             this.execute();
174 			this.totalCallCount++;
175         }
176         tr.end();
177         tr_sys.end();
178         log.debug(this.getName() + " call duration = " + tr.text2(executeCount) + " ms");
179         log.debug(this.getName() + " call duration sys= " + tr_sys.text2(executeCount) + " ms");
180         delta += (tr.duration()/executeCount - tr_sys.duration()/executeCount);
181         return tr.duration()/executeCount;
182     }
183 
184     public void buildExtraStackSize(int extraStackSize)  throws Exception {
185         if (extraStackSize > 0) {
186             buildExtraStackSize(extraStackSize - 1);
187         } else {
188             measureAvg();
189         }
190     }
191 
192     public void measureAvg() throws Exception {
193 
194 		SimpleTimer total = new SimpleTimer();
195         StatisticsItem stat = new StatisticsItem();
196 
197         this.setUp();
198         // First time do not count.
199         measureCase();
200 
201         delta = 0;
202 
203         for (int i = 0; i < this.avgCount; i++) {
204             stat.add(measureCase());
205         }
206 
207         double diff = delta / this.avgCount;
208 
209 		SimpleTimer tr = new SimpleTimer();
210 		this.tearDown();
211 		tr.end();
212 		total.end();
213 
214         log.debug("totalCallCount:" + this.totalCallCount);
215         log.info("AVG call = \t" + SimpleTimer.text(stat.getAvg()) + " ms "
216                 + " +-" + SimpleTimer.text(stat.getStandardDeviation())
217                 + " \t SysDelta " + SimpleTimer.text(diff)
218                 + " \t " + SimpleTimer.textPrc(diff, stat.getAvg()) + " % "
219                 + " \t " +  this.getName());
220 		staticTotalCallCount += this.totalCallCount;
221         if (tr.duration() > 300) {
222 			log.info("tear Down duration = \t" + tr.text() + " ms "
223 				+ SimpleTimer.textPrc(tr.duration(), total.duration()) + " %" );
224         }
225     }
226 
227     public void setUp() throws Exception {
228         Thread.sleep(500);
229     }
230 
231     public void tearDown() throws Exception {
232 
233     }
234 
235     /***
236      * @return Returns the name.
237      */
238     public String getName() {
239         return name;
240     }
241 }