Merge branch 'charm' of charmgit:charm into charm
[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     double *getCpuTime() {return cpuTime;}
199     void initMem();
200     void write(void) ;
201     void writeSts(void);
202     void add(double time, double idleTime, int pe);
203     void setEp(int epidx, double time);
204     void clearEps() {
205       for(int i=0; i < epInfoSize; i++) {
206         epInfo[i].clear();
207       }
208     }
209     void shrink(void);
210     void shrink(double max);
211     void addEventType(int eventType, double time);
212     void startPhase(int phase) { phaseTab.startPhase(phase); }
213     BinEntry *bins() { return pool; }
214     UInt getNumEntries() { return numBins; }
215     UInt getEpInfoSize() {return epInfoSize;} 
216     UInt getPoolSize() {return poolSize;}
217     // accessors to normal summary data
218     inline double getTime(unsigned int interval) {
219       return pool[interval].time();
220     }
221
222
223     inline double getCPUtime(unsigned int interval, unsigned int ep){
224       if(cpuTime != NULL)
225         return cpuTime[interval*epInfoSize+ep]; 
226       else 
227         return 0.0;
228     }
229     
230     inline void setCPUtime(unsigned int interval, unsigned int ep, double val){
231         cpuTime[interval*epInfoSize+ep] = val; }
232     inline double addToCPUtime(unsigned int interval, unsigned int ep, double val){
233         cpuTime[interval*epInfoSize+ep] += val;
234         return cpuTime[interval*epInfoSize+ep]; }
235     inline int getNumExecutions(unsigned int interval, unsigned int ep){
236         return numExecutions[interval*epInfoSize+ep]; }
237     inline void setNumExecutions(unsigned int interval, unsigned int ep, unsigned int val){
238         numExecutions[interval*epInfoSize+ep] = val; }
239     inline int incNumExecutions(unsigned int interval, unsigned int ep){
240         ++numExecutions[interval*epInfoSize+ep];
241         return numExecutions[interval*epInfoSize+ep]; }
242     inline int getUtilization(int interval, int ep);
243
244
245     void updateSummaryDetail(int epIdx, double startTime, double endTime);
246
247
248 };
249
250 /// class for recording trace summary events 
251 /**
252   TraceSummary calculate CPU utilizations in bins, and will record
253   number of calls and total wall time for each entry. 
254 */
255 class TraceSummary : public Trace {
256     SumLogPool*  _logPool;
257     int execEvent;
258     int execEp;
259     int execPe;
260
261     /* per-log metadata maintained to derive cross-event information */
262     double binStart; /* time of last filled bin? */
263     double start, packstart, unpackstart, idleStart;
264     double binTime, binIdle;
265     int msgNum; /* used to handle multiple endComputation calls?? */
266     int inIdle;
267     int inExec;
268   public:
269     TraceSummary(char **argv);
270     void creation(envelope *e, int epIdx, int num=1) {}
271
272     void beginExecute(envelope *e);
273     void beginExecute(char *msg);
274     void beginExecute(CmiObjId  *tid);
275     void beginExecute(int event,int msgType,int ep,int srcPe, int mlen=0, CmiObjId *idx=NULL);
276     void endExecute(void);
277     void endExecute(char *msg);
278     void beginIdle(double currT);
279     void endIdle(double currT);
280     void traceBegin(void);
281     void traceEnd(void);
282     void beginPack(void);
283     void endPack(void);
284     void beginUnpack(void);
285     void endUnpack(void);
286     void beginComputation(void);
287     void endComputation(void);
288
289     void traceClearEps();
290     void traceWriteSts();
291     void traceClose();
292
293     /**
294        for trace summary event mark
295     */
296     void addEventType(int eventType);
297     /** 
298        for starting a new phase
299     */
300     void startPhase(int phase);
301
302     /**
303        query utilities
304     */
305     SumLogPool *pool() { return _logPool; }
306
307     /**
308      *  Supporting methods for CCS queries
309      */
310     void traceEnableCCS();
311     void fillData(double *buffer, double reqStartTime, 
312                   double reqBinSize, int reqNumBins);
313 };
314
315 #endif
316
317 /*@}*/