Changed parsing of coreprof data to keep parent/child event relationships, breaks...
[IRC.git] / Robust / CoreProf / Trace.java
index 0abfb4041f9b054a775eea30c66c03cf31f00821..54c4288b788f390e3bc0cc227ee305879c83c05d 100644 (file)
@@ -1,10 +1,5 @@
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.BufferedInputStream;
-import java.util.Vector;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Set;
+import java.io.*;
+import java.util.*;
 
 public class Trace {
 
@@ -36,41 +31,88 @@ public class Trace {
     eid2name.put( CP_EVENTID_TASKSTALLVAR, "TASKSTALLVAR" );
     eid2name.put( CP_EVENTID_TASKSTALLMEM, "TASKSTALLMEM" );
   }
+
+  Hashtable<Integer, String> eid2name;
   
 
+
   public static void main( String args[] ) {
-    if( args.length != 1 ) {
-      System.out.println( "usage: <coreprof.dat file>" );
+    if( args.length != 2 ) {
+      System.out.println( "usage: <coreprof.dat file> <trace out file>" );
       System.exit( 0 );
     }
-    Trace t = new Trace( args[0] );    
-    t.printStats();
+    Trace t = new Trace( args[0], args[1] );
   }
 
 
+
   // event IDs are a word, timestamps are long ints
   public static final int WORD_SIZE      = 4;
   public static final int EVENT_SIZE     = WORD_SIZE;
   public static final int TIMESTAMP_SIZE = WORD_SIZE*2;
-  public static final int STACKMAX       = 512;
 
-  int                           numThreads;
-  BufferedInputStream[]         threadNum2stream;
-  int[]                         threadNum2numWords;
-  Event[][]                     threadNum2eventStack;
-  Hashtable<Integer, Counter>[] threadNum2eid2c;
-  Hashtable<Integer, String>    eid2name;
+  int          numThreads;
+  ThreadData[] threadData;
+
+
 
-  // calculate this as the single-longest running event
-  // and use it as the parent of all other events
-  long programDuration;
+  public Trace( String inFile, String outFile ) {
 
+    openInputStreams( inFile );
 
-  public Trace( String filename ) {  
-    programDuration = 0;
-    openInputStreams( filename );
     initNames();
-    readThreads();
+
+    for( int i = 0; i < numThreads; i++ ) {
+      readThread( i );
+    }
+
+    printStats( outFile );
+  }
+
+
+  public static int readInt( InputStream is ) {
+    try {
+      int b1 = is.read();
+      int b2 = is.read();
+      int b3 = is.read();
+      int b4 = is.read();
+
+      int retval = (b4<<24)|(b3<<16)|(b2<<8)|b1;
+
+      if( retval < 0 ) {
+       throw new Error();
+      }
+      return retval;
+
+    } catch( Exception e ) {
+      throw new Error();
+    }
+  }
+
+
+  public static long readLong( InputStream is ) {
+    try {
+      long b1 = is.read();
+      long b2 = is.read();
+      long b3 = is.read();
+      long b4 = is.read();
+      long b5 = is.read();
+      long b6 = is.read();
+      long b7 = is.read();
+      long b8 = is.read();
+
+      long retval = 
+        (b8<<56)|(b7<<48)|(b6<<40)|(b5<<32)|
+       (b4<<24)|(b3<<16)|(b2<< 8)|b1;
+      
+      if( retval < 0 ) {
+        throw new Error();
+      }
+      return retval;
+      
+    } catch( Exception e ) {
+      throw new Error();
+    }
   }
 
 
@@ -88,22 +130,19 @@ public class Trace {
       System.exit( -1 );
     }
 
-    threadNum2stream = new BufferedInputStream[numThreads];
-    
     for( int i = 0; i < numThreads; ++i ) {
       try {
-
         // point a thread's event stream to the
         // beginning of its data within the input file
-       threadNum2stream[i] = 
+       threadData[i].dataStream = 
           new BufferedInputStream( new FileInputStream( filename ) );
 
        int skip = offset;
        while( skip > 0 ) {
-         skip -= threadNum2stream[i].skip( skip );
+         skip -= threadData[i].dataStream.skip( skip );
        }
 
-       offset += WORD_SIZE*threadNum2numWords[i];
+       offset += WORD_SIZE*threadData[i].numDataWords;
 
       } catch( Exception e ) {
        e.printStackTrace();
@@ -126,70 +165,76 @@ public class Trace {
     numThreads = readInt( bis );
     offset += WORD_SIZE;
 
+    threadData = new ThreadData[numThreads];
+
     // read number of words used for all events, per thread
-    threadNum2numWords   = new int[numThreads];
-    threadNum2eventStack = new Event[numThreads][STACKMAX];
     for( int i = 0; i < numThreads; ++i ) {
-      threadNum2numWords[i] = readInt( bis );
+      threadData[i] = new ThreadData();
+      threadData[i].numDataWords = readInt( bis );
       offset += WORD_SIZE;
     }
     return offset;
   }
 
-
-  public void readThreads() {
-    // cannot have array of generics, so this line generates
-    // a compiler warning, just grimace and move on  :oP
-    threadNum2eid2c = new Hashtable[numThreads];
-
-    for( int i = 0; i < numThreads; i++ ) {
-      threadNum2eid2c[i] = new Hashtable<Integer, Counter>();
-      readThread( i );
-    }
-  }
-
   
   public void readThread( int tNum ) {
 
-    BufferedInputStream         stream   = threadNum2stream    [tNum];
-    int                         numWords = threadNum2numWords  [tNum];
-    Event[]                     stack    = threadNum2eventStack[tNum];
-    Hashtable<Integer, Counter> eid2c    = threadNum2eid2c     [tNum];
+    System.out.print( "Reading thread "+tNum );
 
-    int  depth     = 0;
-    long timeStamp = 0;
-    int  i         = 0;
+    ThreadData tdata = threadData[tNum];
+    tdata.stackDepth = 0;
+    long timeStamp   = 0;
+    int  i           = 0;
+    int numProgress  = 10;
 
-    while( i < numWords ) {
+    int progressChunk = tdata.numDataWords / numProgress;
+    int j;
+    boolean[] progress = new boolean[numProgress];
+    for( j = 0; j < numProgress; ++j ) {
+      progress[j] = false;
+    }
+    j = 0;
+    
+    while( i < tdata.numDataWords ) {
       
-      int event = readInt ( stream );
-      timeStamp = readLong( stream );
+      if( !progress[j] && i > j*progressChunk ) {
+        System.out.print( "." );
+        progress[j] = true;
+        if( j < numProgress - 1 ) {
+          ++j;
+        }
+      }
+
+      int eventRaw = readInt ( tdata.dataStream );
+      timeStamp    = readLong( tdata.dataStream );
       i += 3;
 
-      int eventType = event &  CP_EVENT_MASK;
-      int eventID   = event >> CP_EVENT_BASESHIFT;
+      int eventType = eventRaw &  CP_EVENT_MASK;
+      int eventID   = eventRaw >> CP_EVENT_BASESHIFT;
 
       switch( eventType ) {
 
         case CP_EVENTTYPE_BEGIN: {
-          depth = pushEvent( stack, depth, eid2c, eventID, timeStamp );
+          pushEvent( tdata, eventID, timeStamp );
         } break;
 
         case CP_EVENTTYPE_END: {
-          depth = popEvent( stack, depth, eventID, timeStamp );
+          popEvent( tdata, eventID, timeStamp );
         } break;    
     
       }
     }
 
-    if( depth != 0 ) {
+    System.out.println( "" );
+
+    if( tdata.stackDepth != 0 ) {
       // worker threads currently do not exit gracefully, and therefore
       // never register their MAIN END event, so if the mismatch is with
       // MAIN BEGIN then treat it as fine, otherwise warn.
-      if( depth == 1 ) {
+      if( tdata.stackDepth == 1 ) {
         // the value of timestamp will be equal to whatever the last
         // properly registered event for this thread was
-        depth = popEvent( stack, depth, CP_EVENTID_MAIN, timeStamp );
+        popEvent( tdata, CP_EVENTID_MAIN, timeStamp );
       } else {
         System.out.println( "Warning: unmatched event begin/end\n" );
       }
@@ -197,137 +242,171 @@ public class Trace {
   }
 
 
-  protected int pushEvent( Event[] stack,
-                           int d,
-                           Hashtable<Integer, Counter> eid2c,
-                           int eventID,
-                           long timeStamp ) {
-    int depth = d;
-    Counter counter = eid2c.get( eventID );
-    if( counter == null ) {
-      counter = new Counter();
-      eid2c.put( eventID, counter );
-    }
-    counter.count++;
-    if( stack[depth] == null ) {
-      stack[depth] = new Event( timeStamp, eventID, counter );
+  protected void pushEvent( ThreadData tdata,
+                            int        eventID,
+                            long       timeStamp ) {
+
+    EventSummary eventSummary = null;
+
+    if( tdata.stackDepth == 0 ) {
+      // there are no parents, so look in the rootEvents
+      // for an existing EventSummary of this type
+      for( Iterator<EventSummary> itr = tdata.rootEvents.iterator();
+           itr.hasNext();
+           ) {
+        EventSummary es = itr.next();
+        if( es.eventID == eventID ) {
+          eventSummary = es;
+          break;
+        }
+      }
+      if( eventSummary == null ) {
+        // there is no summary for this event type yet,
+        // so add it
+        eventSummary = new EventSummary( eventID );
+        tdata.rootEvents.add( eventSummary );
+      }
+
     } else {
-      stack[depth].timeStamp = timeStamp;
-      stack[depth].eventID   = eventID;
-      stack[depth].counter   = counter;
+      // look through the parent's children for an existing
+      // EventSummary of this type
+      EventSummary esParent = tdata.eventStack.get( tdata.stackDepth - 1 );
+      for( Iterator<EventSummary> itr = esParent.children.iterator();
+           itr.hasNext();
+           ) {
+        EventSummary es = itr.next();
+        if( es.eventID == eventID ) {
+          eventSummary = es;
+          break;
+        }
+      }
+      if( eventSummary == null ) {
+        // there is no summary for this event type yet,
+        // under this parent, so add it
+        eventSummary = new EventSummary( eventID );
+        esParent.children.add( eventSummary );
+        eventSummary.parent = esParent;
+      }
     }
-    depth++;
-    if( depth == STACKMAX ) {
-      throw new Error( "Event stack overflow\n" );
+
+    eventSummary.timeStampBeginLatestInstance = timeStamp;
+    
+    eventSummary.instanceCount++;
+
+    if( tdata.eventStack.size() <= tdata.stackDepth ) {
+      tdata.eventStack.setSize( 2*tdata.stackDepth + 20 );
     }
-    return depth;
+    tdata.eventStack.set( tdata.stackDepth, eventSummary );
+
+    tdata.stackDepth++;
   }
 
 
-  protected int popEvent( Event[] stack,
-                          int d,
-                          int eventID,
-                          long timeStamp ) {
-    int depth = d;
-    depth--;
-    if( depth < 0 ) {
+  protected void popEvent( ThreadData tdata,
+                           int        eventID,
+                           long       timeStamp ) {
+    tdata.stackDepth--;
+    if( tdata.stackDepth < 0 ) {
       throw new Error( "Event stack underflow\n" );
     }
-    Event   e           = stack[depth];
-    long    elapsedTime = timeStamp - e.timeStamp;
-    Counter c           = e.counter;
-    c.totalTime += elapsedTime;
-    c.selfTime  += elapsedTime;    
-    if( depth - 1 >= 0 ) {
-      Counter cParent = stack[depth-1].counter;
-      cParent.selfTime -= elapsedTime;
-    }
-    if( elapsedTime > programDuration ) {
-      programDuration = elapsedTime;
-    }
-    return depth;
-  }
 
+    EventSummary eventSummary = tdata.eventStack.get( tdata.stackDepth );
+    assert eventSummary != null;
 
+    long elapsedTime = 
+      timeStamp - eventSummary.timeStampBeginLatestInstance;
 
-  public static int readInt( InputStream is ) {
-    try {
-      int b1 = is.read();
-      int b2 = is.read();
-      int b3 = is.read();
-      int b4 = is.read();
+    eventSummary.totalTime_ticks += elapsedTime;
+    eventSummary.selfTime_ticks  += elapsedTime;
+    
+    if( tdata.stackDepth - 1 >= 0 ) {
+      EventSummary esParent = tdata.eventStack.get( tdata.stackDepth-1 );
+      esParent.selfTime_ticks -= elapsedTime;
+    }
+  }
 
-      int retval = (b4<<24)|(b3<<16)|(b2<<8)|b1;
 
-      if( retval < 0 ) {
-       throw new Error();
-      }
-      return retval;
 
-    } catch( Exception e ) {
-      throw new Error();
-    }
-  }
+  public void printStats( String filename ) {
 
+    System.out.println( "Printing..." );
 
-  public static long readLong( InputStream is ) {
     try {
-      long b1 = is.read();
-      long b2 = is.read();
-      long b3 = is.read();
-      long b4 = is.read();
-      long b5 = is.read();
-      long b6 = is.read();
-      long b7 = is.read();
-      long b8 = is.read();
+      BufferedWriter bw = 
+        new BufferedWriter( new FileWriter( filename ) );
+      
+      for( int i = 0; i < numThreads; ++i ) {
 
-      long retval = 
-        (b8<<56)|(b7<<48)|(b6<<40)|(b5<<32)|
-       (b4<<24)|(b3<<16)|(b2<< 8)|b1;
+        ThreadData tdata = threadData[i];
+
+        bw.write( "----------------------------------\n" );
+        bw.write( "Thread "+i+"\n" );
       
-      if( retval < 0 ) {
-        throw new Error();
+        for( Iterator<EventSummary> itr = tdata.rootEvents.iterator();
+             itr.hasNext();
+             ) {
+          EventSummary es = itr.next();
+          printEventSummary( bw, es, 0 );
+        }
+
+        bw.write( "\n" );
       }
-      return retval;
-      
-    } catch( Exception e ) {
-      throw new Error();
-    }
+
+      bw.close();
+
+    } catch( IOException e ) {}
   }
+  
 
+  public void printEventSummary( BufferedWriter bw,
+                                 EventSummary   es, 
+                                 int            depth ) 
+    throws IOException {
 
-  public void printStats() {
-    
-    for( int i = 0; i < numThreads; ++i ) {
+    String strIndent = "";
+    for( int i = 0; i < depth; ++i ) {
+      strIndent += "--";
+    }
 
-      System.out.println( "Thread "+i );
+    String strEventName = 
+      eid2name.containsKey( es.eventID ) ?
+      eid2name.get( es.eventID )         :
+      Integer.toString( es.eventID );
+        
+    float tOfParent_perc;
+    String strPercParent = "";
+    if( es.parent != null ) {
+      tOfParent_perc =
+        100.0f *
+        new Long( es.totalTime_ticks        ).floatValue() /
+        new Long( es.parent.totalTime_ticks ).floatValue();
       
-      for( Iterator<Integer> evit = threadNum2eid2c[i].keySet().iterator();
-           evit.hasNext();
-           ) {
-       Integer event     = evit.next();
-       Counter c         = threadNum2eid2c[i].get( event );
-       String  eventname = eid2name.containsKey( event ) ?
-                            eid2name.get( event )         :
-                            Integer.toString( event );
-
-        // time stamps are measured in processor ticks, so don't bother converting
-        // to time in secs, just figure out how much time events take in terms of
-        // other events, or the total program time
-
-        float tSelf_perc = 
-          100.0f *
-          new Long( c.selfTime  ).floatValue() /
-          new Long( c.totalTime ).floatValue();
-
-       System.out.println( "Event: "+eventname+
-                            " total time(ticks)="+c.totalTime+
-                            " self time(%)=" +tSelf_perc+
-                            " count="+c.count
-                            );
-      }
-      System.out.println("----------------------------------------------------");
+      strPercParent = String.format( " %%ofParent=%5.1f",
+                                     tOfParent_perc );
     }
+    
+    float tSelf_perc = 
+      100.0f *
+      new Long( es.selfTime_ticks  ).floatValue() /
+      new Long( es.totalTime_ticks ).floatValue();      
+
+    String strSelfStats =
+      String.format( " total(ticks)=%12dK, %%self=%5.1f, count=%d",
+                     es.totalTime_ticks/1000,
+                     tSelf_perc,
+                     es.instanceCount );
+
+    bw.write( strIndent+
+              strEventName+
+              strPercParent+
+              strSelfStats+
+              "\n" );
+
+    for( Iterator<EventSummary> itr = es.children.iterator();
+         itr.hasNext();
+         ) {
+      EventSummary esChild = itr.next();
+      printEventSummary( bw, esChild, depth + 1 );
+    }    
   }
-
 }