back out change to separate event type and timestamp streams, one stream supports...
[IRC.git] / Robust / CoreProf / Trace.java
1 import java.io.FileInputStream;
2 import java.io.InputStream;
3 import java.io.BufferedInputStream;
4 import java.util.Vector;
5 import java.util.Hashtable;
6 import java.util.Iterator;
7 import java.util.Set;
8
9 public class Trace {
10
11   // everything defined here should match coreprof.h
12   // definitions exactly
13   public static final int CP_EVENT_MASK           = 3;
14   public static final int CP_EVENT_BASESHIFT      = 2;
15                                                   
16   public static final int CP_EVENTTYPE_BEGIN      = 0;
17   public static final int CP_EVENTTYPE_END        = 1;
18   public static final int CP_EVENTTYPE_ONEOFF     = 2;
19
20   public static final int CP_EVENTID_MAIN         = 0;
21   public static final int CP_EVENTID_RUNMALLOC    = 1;
22   public static final int CP_EVENTID_RUNFREE      = 2;
23   public static final int CP_EVENTID_TASKDISPATCH = 3;
24   public static final int CP_EVENTID_TASKRETIRE   = 4;
25   public static final int CP_EVENTID_TASKSTALLVAR = 5;
26   public static final int CP_EVENTID_TASKSTALLMEM = 6;
27
28
29   void initNames() {
30     eid2name = new Hashtable<Integer, String>();
31     eid2name.put( CP_EVENTID_MAIN,         "MAIN        " );
32     eid2name.put( CP_EVENTID_RUNMALLOC,    "RUNMALLOC   " );
33     eid2name.put( CP_EVENTID_RUNFREE,      "RUNFREE     " );
34     eid2name.put( CP_EVENTID_TASKDISPATCH, "TASKDISPATCH" );
35     eid2name.put( CP_EVENTID_TASKRETIRE,   "TASKRETIRE  " );
36     eid2name.put( CP_EVENTID_TASKSTALLVAR, "TASKSTALLVAR" );
37     eid2name.put( CP_EVENTID_TASKSTALLMEM, "TASKSTALLMEM" );
38   }
39   
40
41   public static void main( String args[] ) {
42     if( args.length != 1 ) {
43       System.out.println( "usage: <coreprof.dat file>" );
44       System.exit( 0 );
45     }
46     Trace t = new Trace( args[0] );    
47     t.printStats();
48   }
49
50
51   // event IDs are a word, timestamps are long ints
52   public static final int WORD_SIZE      = 4;
53   public static final int EVENT_SIZE     = WORD_SIZE;
54   public static final int TIMESTAMP_SIZE = WORD_SIZE*2;
55   public static final int STACKMAX       = 512;
56
57   int                           numThreads;
58   BufferedInputStream[]         threadNum2stream;
59   int[]                         threadNum2numWords;
60   Event[][]                     threadNum2eventStack;
61   Hashtable<Integer, Counter>[] threadNum2eid2c;
62   Hashtable<Integer, String>    eid2name;
63
64
65   public Trace( String filename ) {  
66     openInputStreams( filename );
67     initNames();
68     readThreads();
69   }
70
71
72   protected void openInputStreams( String filename ) {
73
74     BufferedInputStream bis    = null;
75     int                 offset = 0;
76
77     try {
78       bis    = new BufferedInputStream( new FileInputStream( filename ) );
79       offset = readHeader( bis );
80       bis.close();
81     } catch( Exception e ) {
82       e.printStackTrace();
83       System.exit( -1 );
84     }
85
86     threadNum2stream = new BufferedInputStream[numThreads];
87     
88     for( int i = 0; i < numThreads; ++i ) {
89       try {
90
91         // point a thread's event stream to the
92         // beginning of its data within the input file
93         threadNum2stream[i] = 
94           new BufferedInputStream( new FileInputStream( filename ) );
95
96         int skip = offset;
97         while( skip > 0 ) {
98           skip -= threadNum2stream[i].skip( skip );
99         }
100
101         offset += WORD_SIZE*threadNum2numWords[i];
102
103       } catch( Exception e ) {
104         e.printStackTrace();
105         System.exit( -1 );
106       }
107     }
108   }
109
110
111   int readHeader( BufferedInputStream bis ) {
112
113     // check version
114     int version = readInt( bis );
115     if( version != 0 ) {
116       throw new Error( "Unsupported Version" );
117     }
118     int offset = WORD_SIZE;
119     
120     // read number of threads
121     numThreads = readInt( bis );
122     offset += WORD_SIZE;
123
124     // read number of words used for event, per thread
125     threadNum2numWords   = new int[numThreads];
126     threadNum2eventStack = new Event[numThreads][STACKMAX];
127     for( int i = 0; i < numThreads; ++i ) {
128       threadNum2numWords[i] = readInt( bis );
129       offset += WORD_SIZE;
130     }
131     return offset;
132   }
133
134
135   public void readThreads() {
136     // cannot have array of generics, so this line generates
137     // a compiler warning, just grimace and move on  :oP
138     threadNum2eid2c = new Hashtable[numThreads];
139
140     for( int i = 0; i < numThreads; i++ ) {
141       threadNum2eid2c[i] = new Hashtable<Integer, Counter>();
142       readThread( i );
143     }
144   }
145
146   
147   public void readThread( int tNum ) {
148
149     BufferedInputStream         stream   = threadNum2stream    [tNum];
150     int                         numWords = threadNum2numWords  [tNum];
151     Event[]                     stack    = threadNum2eventStack[tNum];
152     Hashtable<Integer, Counter> eid2c    = threadNum2eid2c     [tNum];
153
154     int  depth     = 0;
155     long timeStamp = 0;
156     int  i         = 0;
157
158     while( i < numWords ) {
159       
160       int event = readInt ( stream );
161       timeStamp = readLong( stream );
162       i += 3;
163
164       int eventType = event &  CP_EVENT_MASK;
165       int eventID   = event >> CP_EVENT_BASESHIFT;
166
167       switch( eventType ) {
168
169         case CP_EVENTTYPE_BEGIN: {
170           Counter counter = eid2c.get( eventID );
171           if( counter == null ) {
172             counter = new Counter();
173             eid2c.put( eventID, counter );
174           }
175           counter.count++;
176           if( stack[depth] == null ) {
177             stack[depth] = new Event( timeStamp, eventID, counter );
178           } else {
179             stack[depth].timeStamp = timeStamp;
180             stack[depth].eventID   = eventID;
181             stack[depth].counter   = counter;
182           }
183           depth++;
184           if( depth == STACKMAX ) {
185             throw new Error( "Event stack overflow\n" );
186           }
187         } break;
188
189         case CP_EVENTTYPE_END: {
190           depth--;
191           if( depth < 0 ) {
192             throw new Error( "Event stack underflow\n" );
193           }
194           Event   e           = stack[depth];
195           long    elapsedTime = timeStamp - e.timeStamp;
196           Counter c           = e.counter;
197           c.totalTime += elapsedTime;
198           c.selfTime  += elapsedTime;
199           if( depth - 1 >= 0 ) {
200             Counter cParent = stack[depth-1].counter;
201             cParent.selfTime -= elapsedTime;
202           }
203         } break;        
204       }
205     }
206
207     
208     if( depth != 0 ) {
209       System.out.println( "Warning: unmatched event begin/end\n" );
210       /*
211       //get rid of last item also
212         depth--;
213         Event e=stack[depth];
214         long elapsedtime=time-e.time;
215         Counter c=e.counter;
216         c.totaltime+=elapsedtime;
217         c.selftime+=elapsedtime;
218         if(depth-1>=0) {
219           Counter cn=stack[depth-1].counter;
220           cn.selftime-=elapsedtime;
221           }
222       */
223     }
224   }
225
226
227   public static int readInt( InputStream is ) {
228     try {
229       int b1 = is.read();
230       int b2 = is.read();
231       int b3 = is.read();
232       int b4 = is.read();
233
234       int retval = (b4<<24)|(b3<<16)|(b2<<8)|b1;
235
236       if( retval < 0 ) {
237         throw new Error();
238       }
239       return retval;
240
241     } catch( Exception e ) {
242       throw new Error();
243     }
244   }
245
246
247   public static long readLong( InputStream is ) {
248     try {
249       long b1 = is.read();
250       long b2 = is.read();
251       long b3 = is.read();
252       long b4 = is.read();
253       long b5 = is.read();
254       long b6 = is.read();
255       long b7 = is.read();
256       long b8 = is.read();
257
258       long retval = 
259         (b8<<56)|(b7<<48)|(b6<<40)|(b5<<32)|
260         (b4<<24)|(b3<<16)|(b2<< 8)|b1;
261       
262       if( retval < 0 ) {
263         throw new Error();
264       }
265       return retval;
266       
267     } catch( Exception e ) {
268       throw new Error();
269     }
270   }
271
272
273   public void printStats() {
274     
275     for( int i = 0; i < numThreads; ++i ) {
276
277       System.out.println( "Thread "+i );
278       
279       for( Iterator<Integer> evit = threadNum2eid2c[i].keySet().iterator();
280            evit.hasNext();
281            ) {
282         Integer event     = evit.next();
283         Counter c         = threadNum2eid2c[i].get( event );
284         String  eventname = eid2name.containsKey( event ) ?
285                             eid2name.get( event )         :
286                             Integer.toString( event );
287
288         float   tSelf_s   = new Long( c.selfTime  ).floatValue() / 1000000.0f;
289         float   tTotal_s  = new Long( c.totalTime ).floatValue() / 1000000.0f;
290
291         System.out.println( "Event: "+eventname+
292                             " self time=" +tSelf_s+
293                             " total time="+tTotal_s+
294                             " count="+c.count
295                             );
296       }
297       System.out.println("----------------------------------------------------");
298     }
299   }
300
301 }