|
Profiler |
|
1 /* 2 * Profiler.java - A simple profiling utility 3 * 4 * Copyright (c) 2001, OntoText Lab. (http://www.ontotext.com) 5 * 6 * This file is part of GATE (see http://gate.ac.uk/), and is free 7 * software, licenced under the GNU Library General Public License, 8 * Version 2, June 1991 (in the distribution as file licence.html, 9 * and also available at http://gate.ac.uk/gate/licence.html). 10 * 11 * Atanas Kiryakov, 05/11/01 12 * 13 * $Id: Profiler.java,v 1.1 2001/11/05 16:11:24 nasso Exp $ 14 */ 15 16 17 package gate.util.profile; 18 19 /** 20 * This is a simple "code-internal" profiler which can be used 21 * by introducing calls to its methods (mostly, checkPoint()) in the code. 22 * It allows detection and reporting of time and memory usage 23 * between execution points as well as for the whole run. In addition allows 24 * for collection/reporting of the resources usage by categories (types of 25 * activity performed between the check point and the previous one). 26 * The results are currently just dumped to the output. 27 * <p> 28 * Important feature is the possibility of the memory usage measurment code 29 * to call the Garbage Collector following a specific strategy that allows 30 * the real memory usage to be deteceted. This feature can be switched OFF 31 * if appropriate, for example, if the *real* run-time memory usage have to 32 * be measured rather than the precise but ideallistic one provided otherwise. 33 * <p> 34 * The profiler can be switched OFF using the enable(boolean) method. In such 35 * case it ignores any calls to its checkPoint(...) method, so, basically does 36 * nothing. This feature is usefull in cases when the profiler have to be 37 * "stripped" from the code in order to allow non-disturbed execution. 38 * <p> 39 * The profiler takes care to calculate the time exlusive its footprint. It 40 * takes account for both "net" time and the absolute duration. Also in 41 * relation to the execution time measurment - it depends on the speed of the 42 * machine as well as on the other applications running in parallel. 43 */ 44 45 import java.io.*; 46 import java.util.*; 47 48 public class Profiler { 49 50 private PrintStream m_out; 51 private boolean m_enabled = true; 52 private boolean m_garbageCollection = true; 53 54 // keeps the sum of the time spend on a category of tasks 55 // the catoegries are identified via strings which are used as 56 // keys in the table. The values in the table are Long objects, millisec. 57 private Hashtable m_categorySums; 58 59 // keeps the time spend on the last task of a category 60 // the catoegries are identified via strings which are used as 61 // keys in the table. The values in the table are Long objects, millisec. 62 private Hashtable m_categoryLasts; 63 64 private Runtime m_rt; 65 66 // all the time constants below in 1/1000s 67 // the time when the profiler was intiated for the current run 68 private long m_startTime; 69 private long m_lastCheckTime, m_profilerTime, m_lastDuration; 70 71 private long m_maxMemory, m_currMemory, m_diffMemory; 72 73 public Profiler() { 74 m_rt = Runtime.getRuntime(); 75 m_out = System.out; 76 } 77 78 /** 79 * Switches the profiler ON and OFF. When OFF all the methods do nothing 80 */ 81 public void enable(boolean isEnabled) { 82 m_enabled = isEnabled; 83 } // enable 84 85 /** 86 * Answers is the profiler switched ON or OFF. When OFF all the methods do 87 * nothing 88 */ 89 public boolean isEnabled() { 90 return m_enabled; 91 } 92 93 /** 94 * Tell's the profiler whether to call the garbage collector when detecting 95 * memory usage or not. If switched ON the GC is called following a 96 * specific strategy as many time as needed so to collect all the memory 97 * that can be collected. This makes the profiling slower and also does not 98 * correctly account for the really memory usage of the applicaton when 99 * run without the profiler. On the other hand, with garbage collection, it 100 * is easier to detecet the amount of memory really necessary for the 101 * application. 102 */ 103 public void enableGCCalling(boolean collect) { 104 m_garbageCollection = collect; 105 } 106 107 /** 108 * @see enableGCCalling(boolean) 109 */ 110 public boolean isGCCallingEnabled() { 111 return m_garbageCollection; 112 } 113 114 115 /** 116 * Returns the time spend by the profiler during the last run. It is the 117 * case that 118 * net_run_time = run_duration - profiler_time 119 */ 120 public long getProfilerTime() { 121 return m_profilerTime; 122 } 123 124 /** 125 * Returns the time spend in the last run without the time 126 * spend by the profiler. It is the case that 127 * net_run_time = run_duration - profiler_time 128 */ 129 public long getNetRunTime() { 130 return m_lastCheckTime - m_profilerTime; 131 }; 132 133 /** 134 * Returns the time spend in the current run until the last check-point 135 * inclusive the time spend by the profiler. It is the case that 136 * net_run_time = run_duration - profiler_time 137 */ 138 public long getRunDuration() { 139 return m_lastCheckTime; 140 // long auxTime1 = (System.currentTimeMillis() - m_startTime1000)/10; 141 // return ((double)auxTime1)/100; 142 } ; 143 144 145 /** 146 * Inialises the profiler for a new run 147 */ 148 public void initRun(String runDescription) { 149 m_out.println("-----------------------------------------------"); 150 m_out.println("New profiler run: " + runDescription); 151 m_out.println("-----------------------------------------------"); 152 153 m_maxMemory=0; 154 m_currMemory=0; 155 m_diffMemory=0; 156 m_profilerTime=0; 157 m_startTime = System.currentTimeMillis(); 158 m_lastCheckTime=0; 159 m_lastDuration=0; 160 161 m_categorySums = new Hashtable(); 162 m_categoryLasts = new Hashtable(); 163 } // initRun 164 165 /** 166 * To be called at all execution points of interest. Detects the time 167 * and memory usage in absolute terms as well as compared to the previous 168 * execution point 169 */ 170 public void checkPoint(String execPointDescr) { 171 checkPoint(execPointDescr, new String[0], true, true, true); 172 } 173 174 /** 175 * In addition to the variant of the method with two parameters allows: 176 * a set of categories (identified by strings) to which the preceeding 177 * fragment of code belongs; flag determining whether the description of 178 * the execution point to be displayed; flag determining whether the 179 * statistics to be shown 180 */ 181 public void checkPoint(String execPointDescr, String categories[], 182 boolean showDescr, boolean showStats, boolean memoryCheck) 183 { 184 if (!m_enabled) 185 return; 186 187 long currTime = System.currentTimeMillis() - m_startTime; 188 m_lastDuration = currTime - m_lastCheckTime; 189 190 if (memoryCheck) { 191 long oldMemory = m_currMemory; 192 193 if (m_garbageCollection) { 194 do { 195 m_currMemory = m_rt.totalMemory() - m_rt.freeMemory(); 196 m_rt.gc(); 197 try {wait(300);} catch (Exception e) {} 198 m_rt.gc(); 199 } while (m_currMemory > m_rt.totalMemory() - m_rt.freeMemory()); 200 } 201 else { 202 m_currMemory = m_rt.totalMemory() - m_rt.freeMemory(); 203 } 204 205 m_currMemory /= 1000; 206 m_maxMemory = Math.max(m_maxMemory, m_currMemory); 207 m_diffMemory = m_currMemory - oldMemory; 208 } // if (memoryCheck) 209 210 m_lastCheckTime = System.currentTimeMillis() - m_startTime; 211 m_profilerTime += (m_lastCheckTime - currTime); 212 213 checkCategories(categories); 214 showResults(execPointDescr, showDescr, showStats); 215 } // checkPoint 216 217 private void checkCategories(String categs[]) { 218 int size = categs.length; 219 String categ; 220 long last, sum; 221 Long l; 222 for (int i=0; i<size; i++) { 223 categ = categs[i].toUpperCase(); 224 l = (Long)m_categorySums.get(categ); 225 sum = (l==null) ? 0 : l.longValue(); 226 sum += m_lastDuration; 227 m_categorySums.put(categ, new Long(sum)); 228 m_categoryLasts.put(categ, new Long(m_lastDuration)); 229 } // for 230 } // checkCategories 231 232 private void showResults(String execPointDescr, boolean showDescr, 233 boolean showStats) 234 { 235 StringBuffer buff = new StringBuffer(500); 236 if (showDescr) { 237 buff.append("---------LOG: "); 238 buff.append(execPointDescr); 239 buff.append("---------"); 240 } 241 242 if (showStats) { 243 buff.append("\nMemory: "); 244 buff.append(m_currMemory); 245 buff.append("k; change: "); 246 buff.append(m_diffMemory); 247 buff.append("k; max: "); 248 buff.append(m_maxMemory); 249 buff.append("k; Net time: "); 250 buff.append(printTime(getNetRunTime())); 251 buff.append("; since prev.: "); 252 buff.append(printTime(m_lastDuration)); 253 // buff.append("; profiler time: "); 254 // buff.append(printTime(m_profilerTime)); 255 // buff.append("; duration: "); 256 // buff.append(printTime(m_lastCheckTime)); 257 } 258 259 if (buff.length() > 0) { 260 m_out.println(buff.toString()); 261 } 262 } // showResults 263 264 /** 265 * Returns 0 if the category was not found 266 */ 267 public long getCategoryTimeSum(String category) { 268 Long sum = (Long)m_categorySums.get(category.toUpperCase()); 269 return (sum == null) ? 0 : sum.longValue(); 270 } // getCategoryTimeSum 271 272 /** 273 * Returns 0 if the category was not found 274 */ 275 public long getCategoryTimeLast(String category) { 276 Long sum = (Long)m_categoryLasts.get(category.toUpperCase()); 277 return (sum == null) ? 0 : sum.longValue(); 278 } // getCategoryTimeSum 279 280 /** 281 * Prints the time for all the categories of activities 282 */ 283 public void showCategoryTimes() { 284 m_out.println("Time spent by categories:"); 285 Enumeration categNames = m_categorySums.keys(); 286 String categ; 287 while (categNames.hasMoreElements()) { 288 categ = (String)categNames.nextElement(); 289 showCategoryTime(categ); 290 } // while 291 } // showCategoryTimes 292 293 /** 294 * Prints the time for certain category of activities 295 */ 296 public void showCategoryTime(String categ) { 297 m_out.println(categ + ", sum=" + 298 printTime(getCategoryTimeSum(categ)) + 299 ", last=" + printTime(getCategoryTimeLast(categ))); 300 } // showCategoryTimes 301 302 /** 303 * An auxiliary routine printing time in "nnn.nns" format 304 */ 305 public String printTime(long timeMillis) { 306 long round = timeMillis/1000; 307 long remaind = (timeMillis % 1000)/10; 308 StringBuffer buff = new StringBuffer(10); 309 buff.append(round); 310 buff.append("."); 311 buff.append(remaind); 312 buff.append("s"); 313 return buff.toString(); 314 } // printTime 315 316 /** 317 * An auxiliary routine printing in a string speed 318 */ 319 public String printSpeed(long timeMillis, 320 double whatever, String whateverMeasure) 321 { 322 double speed1000 = (double) whatever/ timeMillis; 323 long round = (long)((double)speed1000*1000); 324 long remaind = (long)(((double)speed1000*100000) - 100 * round); 325 StringBuffer buff = new StringBuffer(10); 326 buff.append(round); 327 buff.append("."); 328 buff.append(remaind); 329 buff.append(whateverMeasure); 330 buff.append("/s"); 331 return buff.toString(); 332 } // printTime 333 334 /** 335 * An auxiliary routine printing time, avg. time, and avg. speed for 336 * a category 337 */ 338 public void printCategAvg(String categ, long items, 339 double volume, String whateverMeasure) 340 { 341 long time = getCategoryTimeSum(categ); 342 if (time==0) { 343 m_out.println("Category \"" + categ + "\" not found"); 344 } 345 346 m_out.println("Category \"" + categ + "\", Time= " + 347 printTime(time) + "; avg. time= " + 348 printTime(time/items) + "; speed= " + 349 printSpeed(time, volume, whateverMeasure)); 350 } // printCategAvg 351 352 } // Profiler
|
Profiler |
|