Tested and Debugged versions of waitingQueue for the hashStructure.
[IRC.git] / Robust / CoreProf / Trace.java
1 import java.io.*;
2 import java.util.*;
3
4 public class Trace {
5
6   // everything defined here should match coreprof.h
7   // definitions exactly
8   public static final int CP_EVENT_MASK           = 3;
9   public static final int CP_EVENT_BASESHIFT      = 8;
10                                                   
11   public static final int CP_EVENTTYPE_BEGIN      = 1;
12   public static final int CP_EVENTTYPE_END        = 2;
13   public static final int CP_EVENTTYPE_ONEOFF     = 3;
14
15   public static final int CP_EVENTID_MAIN          = 0x04;
16   public static final int CP_EVENTID_RUNMALLOC     = 0x10;
17   public static final int CP_EVENTID_RUNFREE       = 0x11;
18   public static final int CP_EVENTID_WORKSCHEDGRAB = 0x20;
19   public static final int CP_EVENTID_TASKDISPATCH  = 0x30;
20   public static final int CP_EVENTID_TASKEXECUTE   = 0x31;
21   public static final int CP_EVENTID_TASKRETIRE    = 0x32;
22   public static final int CP_EVENTID_TASKSTALLVAR  = 0x40;
23   public static final int CP_EVENTID_TASKSTALLMEM  = 0x41;
24
25
26   void initNames() {
27     eid2name = new Hashtable<Integer, String>();
28     eid2name.put( CP_EVENTID_MAIN,          "MAIN         " );
29     eid2name.put( CP_EVENTID_RUNMALLOC,     "RUNMALLOC    " );
30     eid2name.put( CP_EVENTID_RUNFREE,       "RUNFREE      " );
31     eid2name.put( CP_EVENTID_WORKSCHEDGRAB, "WORKSCHEDGRAB" );
32     eid2name.put( CP_EVENTID_TASKDISPATCH,  "TASKDISPATCH " );
33     eid2name.put( CP_EVENTID_TASKEXECUTE,   "TASKEXECUTE  " );
34     eid2name.put( CP_EVENTID_TASKRETIRE,    "TASKRETIRE   " );
35     eid2name.put( CP_EVENTID_TASKSTALLVAR,  "TASKSTALLVAR " );
36     eid2name.put( CP_EVENTID_TASKSTALLMEM,  "TASKSTALLMEM " );
37   }
38
39   Hashtable<Integer, String> eid2name;
40   
41
42
43   public static void main( String args[] ) {
44     if( args.length != 2 ) {
45       System.out.println( "usage: <coreprof.dat file> <trace out file>" );
46       System.exit( 0 );
47     }
48     Trace t = new Trace( args[0], args[1] );
49   }
50
51
52
53   // event IDs are a word, timestamps are long ints
54   public static final int WORD_SIZE      = 4;
55   public static final int EVENT_SIZE     = WORD_SIZE;
56   public static final int TIMESTAMP_SIZE = WORD_SIZE*2;
57
58   int          numThreads;
59   ThreadData[] threadData;
60
61
62
63   public Trace( String inFile, String outFile ) {
64
65     openInputStreams( inFile );
66
67     initNames();
68
69     for( int i = 0; i < numThreads; i++ ) {
70       readThread( i );
71     }
72
73     printStats( outFile );
74   }
75
76
77   public static int readInt( InputStream is ) {
78     try {
79       int b1 = is.read();
80       int b2 = is.read();
81       int b3 = is.read();
82       int b4 = is.read();
83
84       int retval = (b4<<24)|(b3<<16)|(b2<<8)|b1;
85
86       if( retval < 0 ) {
87         throw new Error();
88       }
89       return retval;
90
91     } catch( Exception e ) {
92       throw new Error();
93     }
94   }
95
96
97   public static long readLong( InputStream is ) {
98     try {
99       long b1 = is.read();
100       long b2 = is.read();
101       long b3 = is.read();
102       long b4 = is.read();
103       long b5 = is.read();
104       long b6 = is.read();
105       long b7 = is.read();
106       long b8 = is.read();
107
108       long retval = 
109         (b8<<56)|(b7<<48)|(b6<<40)|(b5<<32)|
110         (b4<<24)|(b3<<16)|(b2<< 8)|b1;
111       
112       if( retval < 0 ) {
113         throw new Error();
114       }
115       return retval;
116       
117     } catch( Exception e ) {
118       throw new Error();
119     }
120   }
121
122
123   protected void openInputStreams( String filename ) {
124
125     BufferedInputStream bis    = null;
126     int                 offset = 0;
127
128     try {
129       bis    = new BufferedInputStream( new FileInputStream( filename ) );
130       offset = readHeader( bis );
131       bis.close();
132     } catch( Exception e ) {
133       e.printStackTrace();
134       System.exit( -1 );
135     }
136
137     for( int i = 0; i < numThreads; ++i ) {
138       try {
139         // point a thread's event stream to the
140         // beginning of its data within the input file
141         threadData[i].dataStream = 
142           new BufferedInputStream( new FileInputStream( filename ) );
143
144         int skip = offset;
145         while( skip > 0 ) {
146           skip -= threadData[i].dataStream.skip( skip );
147         }
148
149         offset += WORD_SIZE*threadData[i].numDataWords;
150
151       } catch( Exception e ) {
152         e.printStackTrace();
153         System.exit( -1 );
154       }
155     }
156   }
157
158
159   int readHeader( BufferedInputStream bis ) {
160
161     // check version
162     int version = readInt( bis );
163     if( version != 0 ) {
164       throw new Error( "Unsupported Version" );
165     }
166     int offset = WORD_SIZE;
167     
168     // read number of threads
169     numThreads = readInt( bis );
170     offset += WORD_SIZE;
171
172     threadData = new ThreadData[numThreads];
173
174     // read number of words used for all events, per thread
175     for( int i = 0; i < numThreads; ++i ) {
176       threadData[i] = new ThreadData();
177       threadData[i].numDataWords = readInt( bis );
178       offset += WORD_SIZE;
179     }
180     return offset;
181   }
182
183   
184   public void readThread( int tNum ) {
185
186     System.out.print( "Reading thread "+tNum );
187
188     ThreadData tdata = threadData[tNum];
189     tdata.stackDepth = 0;
190     long timeStamp   = 0;
191     int  i           = 0;
192     int numProgress  = 10;
193
194     int progressChunk = tdata.numDataWords / numProgress;
195     int j;
196     boolean[] progress = new boolean[numProgress];
197     for( j = 0; j < numProgress; ++j ) {
198       progress[j] = false;
199     }
200     j = 0;
201     
202     while( i < tdata.numDataWords ) {
203       
204       if( !progress[j] && i > j*progressChunk ) {
205         System.out.print( "." );
206         progress[j] = true;
207         if( j < numProgress - 1 ) {
208           ++j;
209         }
210       }
211
212       int eventRaw = readInt ( tdata.dataStream );
213       timeStamp    = readLong( tdata.dataStream );
214       i += 3;
215
216       int eventType = eventRaw &  CP_EVENT_MASK;
217       int eventID   = eventRaw >> CP_EVENT_BASESHIFT;
218
219       switch( eventType ) {
220
221         case CP_EVENTTYPE_BEGIN: {
222           pushEvent( tdata, eventID, timeStamp );
223         } break;
224
225         case CP_EVENTTYPE_END: {
226           popEvent( tdata, eventID, timeStamp );
227         } break;    
228     
229       }
230     }
231
232     System.out.println( "" );
233
234     while( tdata.stackDepth > 0 ) {
235       // worker threads currently do not exit gracefully, and therefore
236       // may not register END events, so supply them with whatever the
237       // latest known timestamp is
238       EventSummary eventSummary = tdata.eventStack.get( tdata.stackDepth );
239       popEvent( tdata, eventSummary.eventID, timeStamp );
240
241       --tdata.stackDepth;
242     }
243   }
244
245
246   protected void pushEvent( ThreadData tdata,
247                             int        eventID,
248                             long       timeStamp ) {
249
250     EventSummary eventSummary = null;
251
252     if( tdata.stackDepth == 0 ) {
253       // there are no parents, so look in the rootEvents
254       // for an existing EventSummary of this type
255       for( Iterator<EventSummary> itr = tdata.rootEvents.iterator();
256            itr.hasNext();
257            ) {
258         EventSummary es = itr.next();
259         if( es.eventID == eventID ) {
260           eventSummary = es;
261           break;
262         }
263       }
264       if( eventSummary == null ) {
265         // there is no summary for this event type yet,
266         // so add it
267         eventSummary = new EventSummary( eventID );
268         tdata.rootEvents.add( eventSummary );
269       }
270
271     } else {
272       // look through the parent's children for an existing
273       // EventSummary of this type
274       EventSummary esParent = tdata.eventStack.get( tdata.stackDepth - 1 );
275       for( Iterator<EventSummary> itr = esParent.children.iterator();
276            itr.hasNext();
277            ) {
278         EventSummary es = itr.next();
279         if( es.eventID == eventID ) {
280           eventSummary = es;
281           break;
282         }
283       }
284       if( eventSummary == null ) {
285         // there is no summary for this event type yet,
286         // under this parent, so add it
287         eventSummary = new EventSummary( eventID );
288         esParent.children.add( eventSummary );
289         eventSummary.parent = esParent;
290       }
291     }
292
293     eventSummary.timeStampBeginLatestInstance = timeStamp;
294     
295     eventSummary.instanceCount++;
296
297     if( tdata.eventStack.size() <= tdata.stackDepth ) {
298       tdata.eventStack.setSize( 2*tdata.stackDepth + 20 );
299     }
300     tdata.eventStack.set( tdata.stackDepth, eventSummary );
301
302     tdata.stackDepth++;
303   }
304
305
306   protected void popEvent( ThreadData tdata,
307                            int        eventID,
308                            long       timeStamp ) {
309     tdata.stackDepth--;
310     if( tdata.stackDepth < 0 ) {
311       throw new Error( "Event stack underflow\n" );
312     }
313
314     EventSummary eventSummary = tdata.eventStack.get( tdata.stackDepth );
315     assert eventSummary != null;
316
317     if( eventSummary.eventID != eventID ) {
318       System.out.println( "Warning: event begin("+
319                           getEventName( eventSummary.eventID )+
320                           ") end("+
321                           getEventName( eventID )+
322                           ") mismatch!\n" );
323     }
324
325     long elapsedTime = 
326       timeStamp - eventSummary.timeStampBeginLatestInstance;
327
328     eventSummary.totalTime_ticks += elapsedTime;
329     eventSummary.selfTime_ticks  += elapsedTime;
330     
331     if( tdata.stackDepth - 1 >= 0 ) {
332       EventSummary esParent = tdata.eventStack.get( tdata.stackDepth-1 );
333       esParent.selfTime_ticks -= elapsedTime;
334     }
335   }
336
337
338
339   public void printStats( String filename ) {
340
341     System.out.println( "Printing..." );
342
343     try {
344       BufferedWriter bw = 
345         new BufferedWriter( new FileWriter( filename ) );
346       
347       for( int i = 0; i < numThreads; ++i ) {
348
349         ThreadData tdata = threadData[i];
350
351         bw.write( "----------------------------------\n" );
352         bw.write( "Thread "+i+"\n" );
353       
354         for( Iterator<EventSummary> itr = tdata.rootEvents.iterator();
355              itr.hasNext();
356              ) {
357           EventSummary es = itr.next();
358           printEventSummary( bw, es, 0 );
359         }
360
361         bw.write( "\n" );
362       }
363
364       bw.close();
365
366     } catch( IOException e ) {}
367   }
368
369
370   public String getEventName( int eventID ) {
371     return
372       eid2name.containsKey( eventID ) ?
373       eid2name.get        ( eventID ) :
374       Integer.toString    ( eventID );
375   }
376   
377
378   public void printEventSummary( BufferedWriter bw,
379                                  EventSummary   es, 
380                                  int            depth ) 
381     throws IOException {
382
383     String strIndent = "";
384     for( int i = 0; i < depth; ++i ) {
385       strIndent += "--";
386     }
387
388     String strEventName = getEventName( es.eventID );
389         
390     float tOfParent_perc;
391     String strPercParent = "";
392     if( es.parent != null ) {
393       float divisor = new Long( es.parent.totalTime_ticks ).floatValue();
394       if( divisor <= 0.00001f ) {
395         divisor = 0.00001f;
396       }
397
398       tOfParent_perc =
399         100.0f *
400         new Long( es.totalTime_ticks        ).floatValue() /
401         divisor;
402       
403       strPercParent = String.format( " %%ofParent=%5.1f",
404                                      tOfParent_perc );
405     }
406     
407     float tSelf_perc = 
408       100.0f *
409       new Long( es.selfTime_ticks  ).floatValue() /
410       new Long( es.totalTime_ticks ).floatValue();      
411
412     String strSelfStats =
413       String.format( " total(ticks)=%12dK, %%self=%5.1f, count=%d",
414                      es.totalTime_ticks/1000,
415                      tSelf_perc,
416                      es.instanceCount );
417
418     bw.write( strIndent+
419               strEventName+
420               strPercParent+
421               strSelfStats+
422               "\n" );
423
424     for( Iterator<EventSummary> itr = es.children.iterator();
425          itr.hasNext();
426          ) {
427       EventSummary esChild = itr.next();
428       printEventSummary( bw, esChild, depth + 1 );
429     }    
430   }
431 }