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;
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 = 8;
16 public static final int CP_EVENTTYPE_BEGIN = 1;
17 public static final int CP_EVENTTYPE_END = 2;
18 public static final int CP_EVENTTYPE_ONEOFF = 3;
20 public static final int CP_EVENTID_MAIN = 0x04;
21 public static final int CP_EVENTID_RUNMALLOC = 0x05;
22 public static final int CP_EVENTID_RUNFREE = 0x06;
23 public static final int CP_EVENTID_TASKDISPATCH = 0x07;
24 public static final int CP_EVENTID_TASKRETIRE = 0x08;
25 public static final int CP_EVENTID_TASKSTALLVAR = 0x09;
26 public static final int CP_EVENTID_TASKSTALLMEM = 0x0a;
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" );
41 public static void main( String args[] ) {
42 if( args.length != 1 ) {
43 System.out.println( "usage: <coreprof.dat file>" );
46 Trace t = new Trace( args[0] );
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;
58 BufferedInputStream[] threadNum2stream;
59 int[] threadNum2numWords;
60 Event[][] threadNum2eventStack;
61 Hashtable<Integer, Counter>[] threadNum2eid2c;
62 Hashtable<Integer, String> eid2name;
64 // calculate this as the single-longest running event
65 // and use it as the parent of all other events
69 public Trace( String filename ) {
71 openInputStreams( filename );
77 protected void openInputStreams( String filename ) {
79 BufferedInputStream bis = null;
83 bis = new BufferedInputStream( new FileInputStream( filename ) );
84 offset = readHeader( bis );
86 } catch( Exception e ) {
91 threadNum2stream = new BufferedInputStream[numThreads];
93 for( int i = 0; i < numThreads; ++i ) {
96 // point a thread's event stream to the
97 // beginning of its data within the input file
99 new BufferedInputStream( new FileInputStream( filename ) );
103 skip -= threadNum2stream[i].skip( skip );
106 offset += WORD_SIZE*threadNum2numWords[i];
108 } catch( Exception e ) {
116 int readHeader( BufferedInputStream bis ) {
119 int version = readInt( bis );
121 throw new Error( "Unsupported Version" );
123 int offset = WORD_SIZE;
125 // read number of threads
126 numThreads = readInt( bis );
129 // read number of words used for all events, per thread
130 threadNum2numWords = new int[numThreads];
131 threadNum2eventStack = new Event[numThreads][STACKMAX];
132 for( int i = 0; i < numThreads; ++i ) {
133 threadNum2numWords[i] = readInt( bis );
140 public void readThreads() {
141 // cannot have array of generics, so this line generates
142 // a compiler warning, just grimace and move on :oP
143 threadNum2eid2c = new Hashtable[numThreads];
145 for( int i = 0; i < numThreads; i++ ) {
146 threadNum2eid2c[i] = new Hashtable<Integer, Counter>();
152 public void readThread( int tNum ) {
154 BufferedInputStream stream = threadNum2stream [tNum];
155 int numWords = threadNum2numWords [tNum];
156 Event[] stack = threadNum2eventStack[tNum];
157 Hashtable<Integer, Counter> eid2c = threadNum2eid2c [tNum];
163 while( i < numWords ) {
165 int event = readInt ( stream );
166 timeStamp = readLong( stream );
169 int eventType = event & CP_EVENT_MASK;
170 int eventID = event >> CP_EVENT_BASESHIFT;
172 switch( eventType ) {
174 case CP_EVENTTYPE_BEGIN: {
175 depth = pushEvent( stack, depth, eid2c, eventID, timeStamp );
178 case CP_EVENTTYPE_END: {
179 depth = popEvent( stack, depth, eventID, timeStamp );
186 // worker threads currently do not exit gracefully, and therefore
187 // never register their MAIN END event, so if the mismatch is with
188 // MAIN BEGIN then treat it as fine, otherwise warn.
190 // the value of timestamp will be equal to whatever the last
191 // properly registered event for this thread was
192 depth = popEvent( stack, depth, CP_EVENTID_MAIN, timeStamp );
194 System.out.println( "Warning: unmatched event begin/end\n" );
200 protected int pushEvent( Event[] stack,
202 Hashtable<Integer, Counter> eid2c,
206 Counter counter = eid2c.get( eventID );
207 if( counter == null ) {
208 counter = new Counter();
209 eid2c.put( eventID, counter );
212 if( stack[depth] == null ) {
213 stack[depth] = new Event( timeStamp, eventID, counter );
215 stack[depth].timeStamp = timeStamp;
216 stack[depth].eventID = eventID;
217 stack[depth].counter = counter;
220 if( depth == STACKMAX ) {
221 throw new Error( "Event stack overflow\n" );
227 protected int popEvent( Event[] stack,
234 throw new Error( "Event stack underflow\n" );
236 Event e = stack[depth];
237 long elapsedTime = timeStamp - e.timeStamp;
238 Counter c = e.counter;
239 c.totalTime += elapsedTime;
240 c.selfTime += elapsedTime;
241 if( depth - 1 >= 0 ) {
242 Counter cParent = stack[depth-1].counter;
243 cParent.selfTime -= elapsedTime;
245 if( elapsedTime > programDuration ) {
246 programDuration = elapsedTime;
253 public static int readInt( InputStream is ) {
260 int retval = (b4<<24)|(b3<<16)|(b2<<8)|b1;
267 } catch( Exception e ) {
273 public static long readLong( InputStream is ) {
285 (b8<<56)|(b7<<48)|(b6<<40)|(b5<<32)|
286 (b4<<24)|(b3<<16)|(b2<< 8)|b1;
293 } catch( Exception e ) {
299 public void printStats() {
301 for( int i = 0; i < numThreads; ++i ) {
303 System.out.println( "Thread "+i );
305 for( Iterator<Integer> evit = threadNum2eid2c[i].keySet().iterator();
308 Integer event = evit.next();
309 Counter c = threadNum2eid2c[i].get( event );
310 String eventname = eid2name.containsKey( event ) ?
311 eid2name.get( event ) :
312 Integer.toString( event );
314 // time stamps are measured in processor ticks, so don't bother converting
315 // to time in secs, just figure out how much time events take in terms of
316 // other events, or the total program time
320 new Long( c.selfTime ).floatValue() /
321 new Long( c.totalTime ).floatValue();
323 System.out.println( "Event: "+eventname+
324 " total time(ticks)="+c.totalTime+
325 " self time(%)=" +tSelf_perc+
329 System.out.println("----------------------------------------------------");