00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 package org.antlr.runtime.debug;
00029
00030 import org.antlr.runtime.*;
00031 import org.antlr.runtime.misc.Stats;
00032
00033 import java.util.*;
00034 import java.io.IOException;
00035
00039 public class Profiler extends BlankDebugEventListener {
00043 public static final String Version = "2";
00044 public static final String RUNTIME_STATS_FILENAME = "runtime.stats";
00045 public static final int NUM_RUNTIME_STATS = 29;
00046
00047 public DebugParser parser = null;
00048
00049
00050
00051 protected int ruleLevel = 0;
00052 protected int decisionLevel = 0;
00053 protected int maxLookaheadInCurrentDecision = 0;
00054 protected CommonToken lastTokenConsumed=null;
00055
00056 protected List lookaheadStack = new ArrayList();
00057
00058
00059
00060 public int numRuleInvocations = 0;
00061 public int numGuessingRuleInvocations = 0;
00062 public int maxRuleInvocationDepth = 0;
00063 public int numFixedDecisions = 0;
00064 public int numCyclicDecisions = 0;
00065 public int numBacktrackDecisions = 0;
00066 public int[] decisionMaxFixedLookaheads = new int[200];
00067 public int[] decisionMaxCyclicLookaheads = new int[200];
00068 public List decisionMaxSynPredLookaheads = new ArrayList();
00069 public int numHiddenTokens = 0;
00070 public int numCharsMatched = 0;
00071 public int numHiddenCharsMatched = 0;
00072 public int numSemanticPredicates = 0;
00073 public int numSyntacticPredicates = 0;
00074 protected int numberReportedErrors = 0;
00075 public int numMemoizationCacheMisses = 0;
00076 public int numMemoizationCacheHits = 0;
00077 public int numMemoizationCacheEntries = 0;
00078
00079 public Profiler() {
00080 }
00081
00082 public Profiler(DebugParser parser) {
00083 this.parser = parser;
00084 }
00085
00086 public void enterRule(String grammarFileName, String ruleName) {
00087
00088 ruleLevel++;
00089 numRuleInvocations++;
00090 if ( ruleLevel >maxRuleInvocationDepth ) {
00091 maxRuleInvocationDepth = ruleLevel;
00092 }
00093
00094 }
00095
00100 public void examineRuleMemoization(IntStream input,
00101 int ruleIndex,
00102 String ruleName)
00103 {
00104
00105 int stopIndex = parser.getRuleMemoization(ruleIndex, input.index());
00106 if ( stopIndex==BaseRecognizer.MEMO_RULE_UNKNOWN ) {
00107
00108 numMemoizationCacheMisses++;
00109 numGuessingRuleInvocations++;
00110 }
00111 else {
00112
00113
00114 numMemoizationCacheHits++;
00115 }
00116 }
00117
00118 public void memoize(IntStream input,
00119 int ruleIndex,
00120 int ruleStartIndex,
00121 String ruleName)
00122 {
00123
00124
00125 numMemoizationCacheEntries++;
00126 }
00127
00128 public void exitRule(String grammarFileName, String ruleName) {
00129 ruleLevel--;
00130 }
00131
00132 public void enterDecision(int decisionNumber) {
00133 decisionLevel++;
00134 int startingLookaheadIndex = parser.getTokenStream().index();
00135
00136 lookaheadStack.add(new Integer(startingLookaheadIndex));
00137 }
00138
00139 public void exitDecision(int decisionNumber) {
00140
00141
00142
00143 if ( parser.isCyclicDecision ) {
00144 numCyclicDecisions++;
00145 }
00146 else {
00147 numFixedDecisions++;
00148 }
00149 lookaheadStack.remove(lookaheadStack.size()-1);
00150 decisionLevel--;
00151 if ( parser.isCyclicDecision ) {
00152 if ( numCyclicDecisions>=decisionMaxCyclicLookaheads.length ) {
00153 int[] bigger = new int[decisionMaxCyclicLookaheads.length*2];
00154 System.arraycopy(decisionMaxCyclicLookaheads,0,bigger,0,decisionMaxCyclicLookaheads.length);
00155 decisionMaxCyclicLookaheads = bigger;
00156 }
00157 decisionMaxCyclicLookaheads[numCyclicDecisions-1] = maxLookaheadInCurrentDecision;
00158 }
00159 else {
00160 if ( numFixedDecisions>=decisionMaxFixedLookaheads.length ) {
00161 int[] bigger = new int[decisionMaxFixedLookaheads.length*2];
00162 System.arraycopy(decisionMaxFixedLookaheads,0,bigger,0,decisionMaxFixedLookaheads.length);
00163 decisionMaxFixedLookaheads = bigger;
00164 }
00165 decisionMaxFixedLookaheads[numFixedDecisions-1] = maxLookaheadInCurrentDecision;
00166 }
00167 parser.isCyclicDecision = false;
00168 maxLookaheadInCurrentDecision = 0;
00169 }
00170
00171 public void consumeToken(Token token) {
00172
00173 lastTokenConsumed = (CommonToken)token;
00174 }
00175
00179 public boolean inDecision() {
00180 return decisionLevel>0;
00181 }
00182
00183 public void consumeHiddenToken(Token token) {
00184
00185 lastTokenConsumed = (CommonToken)token;
00186 }
00187
00190 public void LT(int i, Token t) {
00191 if ( inDecision() ) {
00192
00193 int stackTop = lookaheadStack.size()-1;
00194 Integer startingIndex = (Integer)lookaheadStack.get(stackTop);
00195
00196 int thisRefIndex = parser.getTokenStream().index();
00197 int numHidden =
00198 getNumberOfHiddenTokens(startingIndex.intValue(), thisRefIndex);
00199 int depth = i + thisRefIndex - startingIndex.intValue() - numHidden;
00200
00201
00202
00203
00204 if ( depth>maxLookaheadInCurrentDecision ) {
00205 maxLookaheadInCurrentDecision = depth;
00206 }
00207 }
00208 }
00209
00225 public void beginBacktrack(int level) {
00226
00227 numBacktrackDecisions++;
00228 }
00229
00231 public void endBacktrack(int level, boolean successful) {
00232
00233 decisionMaxSynPredLookaheads.add(
00234 new Integer(maxLookaheadInCurrentDecision)
00235 );
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 public void recognitionException(RecognitionException e) {
00262 numberReportedErrors++;
00263 }
00264
00265 public void semanticPredicate(boolean result, String predicate) {
00266 if ( inDecision() ) {
00267 numSemanticPredicates++;
00268 }
00269 }
00270
00271 public void terminate() {
00272 String stats = toNotifyString();
00273 try {
00274 Stats.writeReport(RUNTIME_STATS_FILENAME,stats);
00275 }
00276 catch (IOException ioe) {
00277 System.err.println(ioe);
00278 ioe.printStackTrace(System.err);
00279 }
00280 System.out.println(toString(stats));
00281 }
00282
00283 public void setParser(DebugParser parser) {
00284 this.parser = parser;
00285 }
00286
00287
00288
00289 public String toNotifyString() {
00290 TokenStream input = parser.getTokenStream();
00291 for (int i=0; i<input.size()&&lastTokenConsumed!=null&&i<=lastTokenConsumed.getTokenIndex(); i++) {
00292 Token t = input.get(i);
00293 if ( t.getChannel()!=Token.DEFAULT_CHANNEL ) {
00294 numHiddenTokens++;
00295 numHiddenCharsMatched += t.getText().length();
00296 }
00297 }
00298 numCharsMatched = lastTokenConsumed.getStopIndex() + 1;
00299 decisionMaxFixedLookaheads = trim(decisionMaxFixedLookaheads, numFixedDecisions);
00300 decisionMaxCyclicLookaheads = trim(decisionMaxCyclicLookaheads, numCyclicDecisions);
00301 StringBuffer buf = new StringBuffer();
00302 buf.append(Version);
00303 buf.append('\t');
00304 buf.append(parser.getClass().getName());
00305 buf.append('\t');
00306 buf.append(numRuleInvocations);
00307 buf.append('\t');
00308 buf.append(maxRuleInvocationDepth);
00309 buf.append('\t');
00310 buf.append(numFixedDecisions);
00311 buf.append('\t');
00312 buf.append(Stats.min(decisionMaxFixedLookaheads));
00313 buf.append('\t');
00314 buf.append(Stats.max(decisionMaxFixedLookaheads));
00315 buf.append('\t');
00316 buf.append(Stats.avg(decisionMaxFixedLookaheads));
00317 buf.append('\t');
00318 buf.append(Stats.stddev(decisionMaxFixedLookaheads));
00319 buf.append('\t');
00320 buf.append(numCyclicDecisions);
00321 buf.append('\t');
00322 buf.append(Stats.min(decisionMaxCyclicLookaheads));
00323 buf.append('\t');
00324 buf.append(Stats.max(decisionMaxCyclicLookaheads));
00325 buf.append('\t');
00326 buf.append(Stats.avg(decisionMaxCyclicLookaheads));
00327 buf.append('\t');
00328 buf.append(Stats.stddev(decisionMaxCyclicLookaheads));
00329 buf.append('\t');
00330 buf.append(numBacktrackDecisions);
00331 buf.append('\t');
00332 buf.append(Stats.min(toArray(decisionMaxSynPredLookaheads)));
00333 buf.append('\t');
00334 buf.append(Stats.max(toArray(decisionMaxSynPredLookaheads)));
00335 buf.append('\t');
00336 buf.append(Stats.avg(toArray(decisionMaxSynPredLookaheads)));
00337 buf.append('\t');
00338 buf.append(Stats.stddev(toArray(decisionMaxSynPredLookaheads)));
00339 buf.append('\t');
00340 buf.append(numSemanticPredicates);
00341 buf.append('\t');
00342 buf.append(parser.getTokenStream().size());
00343 buf.append('\t');
00344 buf.append(numHiddenTokens);
00345 buf.append('\t');
00346 buf.append(numCharsMatched);
00347 buf.append('\t');
00348 buf.append(numHiddenCharsMatched);
00349 buf.append('\t');
00350 buf.append(numberReportedErrors);
00351 buf.append('\t');
00352 buf.append(numMemoizationCacheHits);
00353 buf.append('\t');
00354 buf.append(numMemoizationCacheMisses);
00355 buf.append('\t');
00356 buf.append(numGuessingRuleInvocations);
00357 buf.append('\t');
00358 buf.append(numMemoizationCacheEntries);
00359 return buf.toString();
00360 }
00361
00362 public String toString() {
00363 return toString(toNotifyString());
00364 }
00365
00366 protected static String[] decodeReportData(String data) {
00367 String[] fields = new String[NUM_RUNTIME_STATS];
00368 StringTokenizer st = new StringTokenizer(data, "\t");
00369 int i = 0;
00370 while ( st.hasMoreTokens() ) {
00371 fields[i] = st.nextToken();
00372 i++;
00373 }
00374 if ( i!=NUM_RUNTIME_STATS ) {
00375 return null;
00376 }
00377 return fields;
00378 }
00379
00380 public static String toString(String notifyDataLine) {
00381 String[] fields = decodeReportData(notifyDataLine);
00382 if ( fields==null ) {
00383 return null;
00384 }
00385 StringBuffer buf = new StringBuffer();
00386 buf.append("ANTLR Runtime Report; Profile Version ");
00387 buf.append(fields[0]);
00388 buf.append('\n');
00389 buf.append("parser name ");
00390 buf.append(fields[1]);
00391 buf.append('\n');
00392 buf.append("Number of rule invocations ");
00393 buf.append(fields[2]);
00394 buf.append('\n');
00395 buf.append("Number of rule invocations in \"guessing\" mode ");
00396 buf.append(fields[27]);
00397 buf.append('\n');
00398 buf.append("max rule invocation nesting depth ");
00399 buf.append(fields[3]);
00400 buf.append('\n');
00401 buf.append("number of fixed lookahead decisions ");
00402 buf.append(fields[4]);
00403 buf.append('\n');
00404 buf.append("min lookahead used in a fixed lookahead decision ");
00405 buf.append(fields[5]);
00406 buf.append('\n');
00407 buf.append("max lookahead used in a fixed lookahead decision ");
00408 buf.append(fields[6]);
00409 buf.append('\n');
00410 buf.append("average lookahead depth used in fixed lookahead decisions ");
00411 buf.append(fields[7]);
00412 buf.append('\n');
00413 buf.append("standard deviation of depth used in fixed lookahead decisions ");
00414 buf.append(fields[8]);
00415 buf.append('\n');
00416 buf.append("number of arbitrary lookahead decisions ");
00417 buf.append(fields[9]);
00418 buf.append('\n');
00419 buf.append("min lookahead used in an arbitrary lookahead decision ");
00420 buf.append(fields[10]);
00421 buf.append('\n');
00422 buf.append("max lookahead used in an arbitrary lookahead decision ");
00423 buf.append(fields[11]);
00424 buf.append('\n');
00425 buf.append("average lookahead depth used in arbitrary lookahead decisions ");
00426 buf.append(fields[12]);
00427 buf.append('\n');
00428 buf.append("standard deviation of depth used in arbitrary lookahead decisions ");
00429 buf.append(fields[13]);
00430 buf.append('\n');
00431 buf.append("number of evaluated syntactic predicates ");
00432 buf.append(fields[14]);
00433 buf.append('\n');
00434 buf.append("min lookahead used in a syntactic predicate ");
00435 buf.append(fields[15]);
00436 buf.append('\n');
00437 buf.append("max lookahead used in a syntactic predicate ");
00438 buf.append(fields[16]);
00439 buf.append('\n');
00440 buf.append("average lookahead depth used in syntactic predicates ");
00441 buf.append(fields[17]);
00442 buf.append('\n');
00443 buf.append("standard deviation of depth used in syntactic predicates ");
00444 buf.append(fields[18]);
00445 buf.append('\n');
00446 buf.append("rule memoization cache size ");
00447 buf.append(fields[28]);
00448 buf.append('\n');
00449 buf.append("number of rule memoization cache hits ");
00450 buf.append(fields[25]);
00451 buf.append('\n');
00452 buf.append("number of rule memoization cache misses ");
00453 buf.append(fields[26]);
00454 buf.append('\n');
00455 buf.append("number of evaluated semantic predicates ");
00456 buf.append(fields[19]);
00457 buf.append('\n');
00458 buf.append("number of tokens ");
00459 buf.append(fields[20]);
00460 buf.append('\n');
00461 buf.append("number of hidden tokens ");
00462 buf.append(fields[21]);
00463 buf.append('\n');
00464 buf.append("number of char ");
00465 buf.append(fields[22]);
00466 buf.append('\n');
00467 buf.append("number of hidden char ");
00468 buf.append(fields[23]);
00469 buf.append('\n');
00470 buf.append("number of syntax errors ");
00471 buf.append(fields[24]);
00472 buf.append('\n');
00473 return buf.toString();
00474 }
00475
00476 protected int[] trim(int[] X, int n) {
00477 if ( n<X.length ) {
00478 int[] trimmed = new int[n];
00479 System.arraycopy(X,0,trimmed,0,n);
00480 X = trimmed;
00481 }
00482 return X;
00483 }
00484
00485 protected int[] toArray(List a) {
00486 int[] x = new int[a.size()];
00487 for (int i = 0; i < a.size(); i++) {
00488 Integer I = (Integer) a.get(i);
00489 x[i] = I.intValue();
00490 }
00491 return x;
00492 }
00493
00495 public int getNumberOfHiddenTokens(int i, int j) {
00496 int n = 0;
00497 TokenStream input = parser.getTokenStream();
00498 for (int ti = i; ti<input.size() && ti <= j; ti++) {
00499 Token t = input.get(ti);
00500 if ( t.getChannel()!=Token.DEFAULT_CHANNEL ) {
00501 n++;
00502 }
00503 }
00504 return n;
00505 }
00506 }