added explicit code for handling traceBegin and traceEnd.
[charm.git] / src / ck-perf / trace-summary.h
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /**
9  * \addtogroup CkPerf
10 */
11 /*@{*/
12
13 #ifndef _SUMMARY_H
14 #define _SUMMARY_H
15
16 #include <stdio.h>
17 #include <errno.h>
18
19 #include "trace.h"
20 #include "envelope.h"
21 #include "register.h"
22 #include "trace-common.h"
23
24 // initial bin size, time in seconds
25 #define  BIN_SIZE       0.001
26
27 #define  MAX_MARKS       256
28
29 #define  MAX_PHASES       100
30
31 /// Bin entry record CPU time in an interval
32 class BinEntry {
33   public:
34     void *operator new(size_t s) {void*ret=malloc(s);_MEMCHECK(ret);return ret;}
35     void *operator new(size_t, void *ptr) { return ptr; }
36     void operator delete(void *ptr) { free(ptr); }
37 #if defined(WIN32) || CMK_MULTIPLE_DELETE
38     void operator delete(void *, void *) { }
39 #endif
40     BinEntry(): _time(0.), _idleTime(0.) {}
41     BinEntry(double t, double idleT): _time(t), _idleTime(idleT) {}
42     double &time() { return _time; }
43     double &getIdleTime() { return _idleTime; }
44     void write(FILE *fp);
45     int  getU();
46     int getUIdle();
47   private:
48     double _time;
49     double _idleTime;
50 };
51
52 /// a phase entry for trace summary
53 class PhaseEntry {
54   private:
55     int nEPs;
56     int *count;
57     double *times;
58     double *maxtimes;
59   public:
60     PhaseEntry();
61     ~PhaseEntry() { delete [] count; delete [] times; delete [] maxtimes; }
62     /// one entry is called for 'time' seconds.
63     void setEp(int epidx, double time) {
64         if (epidx>=nEPs) CmiAbort("Too many entry functions!\n");
65         count[epidx]++;
66         times[epidx] += time;
67         if (maxtimes[epidx] < time) maxtimes[epidx] = time;
68     }
69     /**
70         write two lines for each phase:
71         1. number of calls for each entry;
72         2. time in us spent for each entry.
73     */
74     void write(FILE *fp, int seq) {
75         int i;
76         fprintf(fp, "[%d] ", seq);
77         int _numEntries=_entryTable.size();
78         for (i=0; i<_numEntries; i++) 
79             fprintf(fp, "%d ", count[i]);
80         fprintf(fp, "\n");
81
82         fprintf(fp, "[%d] ", seq);
83         for (i=0; i<_numEntries; i++) 
84             fprintf(fp, "%ld ", (long)(times[i]*1.0e6) );
85         fprintf(fp, "\n");
86
87         fprintf(fp, "[%d] ", seq);
88         for (i=0; i<_numEntries; i++) 
89             fprintf(fp, "%ld ", (long)(maxtimes[i]*1.0e6) );
90         fprintf(fp, "\n");
91     }
92 };
93
94 /// table of PhaseEntry
95 class PhaseTable {
96   private:
97     PhaseEntry **phases;
98     int numPhase;         /**< phase table size */
99     int cur_phase;        /**< current phase */
100     int phaseCalled;      /**< total number of phases */
101   public:
102     PhaseTable(int n): numPhase(n) {
103         phases = new PhaseEntry*[n];
104         _MEMCHECK(phases);
105         for (int i=0; i<n; i++) phases[i] = NULL;
106         cur_phase = -1;
107         phaseCalled = 0;
108     }
109     ~PhaseTable() {
110         for (int i=0; i<numPhase; i++) delete phases[i];
111         delete [] phases;
112     }
113     inline int numPhasesCalled() { return phaseCalled; };
114     /**
115       start a phase. If new, create a new PhaseEntry
116     */
117     void startPhase(int p) { 
118         if (p<0 && p>=numPhase) CmiAbort("Invalid Phase number. \n");
119         cur_phase = p; 
120         if (phases[cur_phase] == NULL) {
121             phases[cur_phase] = new PhaseEntry;
122             _MEMCHECK(phases[cur_phase]);
123             phaseCalled ++;
124         }
125     }
126     void setEp(int epidx, double time) {
127         if (cur_phase == -1) return;
128         if (phases[cur_phase] == NULL) CmiAbort("No current phase!\n");
129         phases[cur_phase]->setEp(epidx, time);
130     }
131     void write(FILE *fp) {
132         for (int i=0; i<numPhase; i++ )
133             if (phases[i]) { 
134                 phases[i]->write(fp, i);
135             }
136     }
137 };
138
139 double epThreshold;
140 double epInterval;
141
142 /// info for each entry
143 class SumEntryInfo {
144 public:
145   double epTime;
146   double epMaxTime;
147   int epCount;
148   enum {HIST_SIZE = 10};
149   int hist[HIST_SIZE];
150 public:
151   SumEntryInfo(): epTime(0.), epMaxTime(0.), epCount(0) {}
152   void clear() {
153     epTime = epMaxTime = 0.;
154     epCount = 0;
155     for (int i=0; i<HIST_SIZE; i++) hist[i]=0;
156   }
157   void setTime(double t) {
158     epTime += t;
159     epCount ++;
160     if (epMaxTime < t) epMaxTime = t;
161     for (int i=HIST_SIZE-1; i>=0; i--) {
162       if (t>epThreshold+i*epInterval) {
163         hist[i]++; break;
164       }
165     }
166   }
167 };
168
169 /// summary log pool
170 class SumLogPool {
171   private:
172     UInt poolSize;
173     UInt numBins;
174     BinEntry *pool;     /**< bins */
175     FILE *fp, *stsfp, *sdfp ;
176     char *pgm;
177
178     SumEntryInfo  *epInfo;
179     UInt epInfoSize;
180
181     /// a mark entry for trace summary
182     typedef struct {
183       double time;
184     } MarkEntry;
185     CkVec<MarkEntry *> events[MAX_MARKS];
186     int markcount;
187
188     /// for phases
189     PhaseTable phaseTab;
190
191     /// for Summary-Detail
192     double *cpuTime;    //[MAX_INTERVALS * MAX_ENTRIES];
193     int *numExecutions; //[MAX_INTERVALS * MAX_ENTRIES];
194
195   public:
196     SumLogPool(char *pgm);
197     ~SumLogPool();
198     void initMem();
199     void write(void) ;
200     void writeSts(void);
201     void add(double time, double idleTime, int pe);
202     void setEp(int epidx, double time);
203     void clearEps() {
204       for(int i=0; i < epInfoSize; i++) {
205         epInfo[i].clear();
206       }
207     }
208     void shrink(void);
209     void addEventType(int eventType, double time);
210     void startPhase(int phase) { phaseTab.startPhase(phase); }
211     BinEntry *bins() { return pool; }
212     int getNumEntries() const { return numBins; }
213
214     // accessors to normal summary data
215     inline double getTime(unsigned int interval) {
216       return pool[interval].time();
217     }
218
219
220     inline double getCPUtime(unsigned int interval, unsigned int ep){
221       if(cpuTime != NULL)
222         return cpuTime[interval*epInfoSize+ep]; 
223       else 
224         return 0.0;
225     }
226     
227     inline void setCPUtime(unsigned int interval, unsigned int ep, double val){
228         cpuTime[interval*epInfoSize+ep] = val; }
229     inline double addToCPUtime(unsigned int interval, unsigned int ep, double val){
230         cpuTime[interval*epInfoSize+ep] += val;
231         return cpuTime[interval*epInfoSize+ep]; }
232     inline int getNumExecutions(unsigned int interval, unsigned int ep){
233         return numExecutions[interval*epInfoSize+ep]; }
234     inline void setNumExecutions(unsigned int interval, unsigned int ep, unsigned int val){
235         numExecutions[interval*epInfoSize+ep] = val; }
236     inline int incNumExecutions(unsigned int interval, unsigned int ep){
237         ++numExecutions[interval*epInfoSize+ep];
238         return numExecutions[interval*epInfoSize+ep]; }
239     inline int getUtilization(int interval, int ep);
240
241
242     void updateSummaryDetail(int epIdx, double startTime, double endTime);
243
244
245 };
246
247 /// class for recording trace summary events 
248 /**
249   TraceSummary calculate CPU utilizations in bins, and will record
250   number of calls and total wall time for each entry. 
251 */
252 class TraceSummary : public Trace {
253     SumLogPool*  _logPool;
254     int execEvent;
255     int execEp;
256     int execPe;
257
258     /* per-log metadata maintained to derive cross-event information */
259     double binStart; /* time of last filled bin? */
260     double start, packstart, unpackstart, idleStart;
261     double binTime, binIdle;
262     int msgNum; /* used to handle multiple endComputation calls?? */
263   public:
264     TraceSummary(char **argv);
265     void creation(envelope *e, int epIdx, int num=1) {}
266
267     void beginExecute(envelope *e);
268     void beginExecute(CmiObjId  *tid);
269     void beginExecute(int event,int msgType,int ep,int srcPe, int mlen=0, CmiObjId *idx=NULL);
270     void endExecute(void);
271     void beginIdle(double currT);
272     void endIdle(double currT);
273     void traceBegin(void);
274     void traceEnd(void);
275     void beginPack(void);
276     void endPack(void);
277     void beginUnpack(void);
278     void endUnpack(void);
279     void beginComputation(void);
280     void endComputation(void);
281
282     void traceClearEps();
283     void traceWriteSts();
284     void traceClose();
285
286     /**
287        for trace summary event mark
288     */
289     void addEventType(int eventType);
290     /** 
291        for starting a new phase
292     */
293     void startPhase(int phase);
294
295     /**
296        query utilities
297     */
298     SumLogPool *pool() { return _logPool; }
299
300     /**
301      *  Supporting methods for CCS queries
302      */
303     void traceEnableCCS();
304     void fillData(double *buffer, double reqStartTime, 
305                   double reqBinSize, int reqNumBins);
306 };
307
308 #endif
309
310 /*@}*/