46712fe93920f422247a28f670e49911a06ac9c8
[charm.git] / src / ck-perf / trace-projections.h
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /**
9  * \addtogroup CkPerf
10 */
11 /*@{*/
12
13 #ifndef _PROJECTIONS_H
14 #define _PROJECTIONS_H
15
16 #include <stdio.h>
17 #include <errno.h>
18 #include <unistd.h>
19
20 #include "trace.h"
21 #include "trace-common.h"
22 #include "ckhashtable.h"
23
24
25
26 #if CMK_HAS_COUNTER_PAPI
27 #include <papi.h>
28 #endif
29
30 #if CMK_PROJECTIONS_USE_ZLIB
31 #include <zlib.h>
32 #endif
33
34 #include "pup.h"
35
36 #define PROJECTION_VERSION  "7.0"
37
38 // Macro to make projections check for errors before an fprintf succeeds.
39 #define CheckAndFPrintF(f,string,data) \
40 { \
41   int result = fprintf(f,string,data); \
42   if (result == -1) { \
43     CmiAbort("Projections I/O error!"); \
44   } \
45 }
46
47 /// a log entry in trace projection
48 class LogEntry {
49   public:
50     double time;
51     double endTime; // Should be used for all bracketed events. Currently only used for bracketed user supplied note
52     double cputime;
53     double recvTime;
54     int event;
55     int pe;
56     unsigned short mIdx;
57     unsigned short eIdx;
58     int msglen;
59     CmiObjId   id;
60     int numpes;
61     int *pes;
62     int userSuppliedData;
63     char *userSuppliedNote;
64     unsigned long memUsage;
65
66     // this is taken out so as to provide a placeholder value for non-PAPI
67     // versions (whose value is *always* zero).
68     int numPapiEvents;
69 #if CMK_HAS_COUNTER_PAPI
70     int *papiIDs;
71     LONG_LONG_PAPI *papiValues;
72 #endif
73     unsigned char type; 
74     char *fName;
75     int flen;
76
77   public:
78     
79     LogEntry() {
80       fName=NULL;flen=0;pes=NULL;numpes=0;userSuppliedNote = NULL;
81     }
82
83     LogEntry(double tm, unsigned char t, unsigned short m=0, 
84              unsigned short e=0, int ev=0, int p=0, int ml=0, 
85              CmiObjId *d=NULL, double rt=0., double cputm=0., int numPe=0) {
86       type = t; mIdx = m; eIdx = e; event = ev; pe = p; 
87       time = tm; msglen = ml;
88       if (d) id = *d; else {id.id[0]=id.id[1]=id.id[2]=id.id[3]=0; };
89       recvTime = rt; cputime = cputm;
90       // initialize for papi as well as non papi versions.
91       numPapiEvents = 0;
92       userSuppliedNote = NULL;
93 #if CMK_HAS_COUNTER_PAPI
94       papiIDs = NULL;
95       papiValues = NULL;
96 #endif
97       fName = NULL;
98       flen=0;
99       pes=NULL;
100       numpes=numPe;
101     }
102
103     LogEntry(double _time,unsigned char _type,unsigned short _funcID,
104              int _lineNum,char *_fileName){
105       time = _time;
106       type = _type;
107       mIdx = _funcID;
108       event = _lineNum;
109       userSuppliedNote = NULL;      
110       pes=NULL;
111       numpes=0;
112       setFName(_fileName);
113     }
114
115     // Constructor for User Supplied Data
116     LogEntry(double _time,unsigned char _type, int value,
117              int _lineNum,char *_fileName){
118       time = _time;
119       type = _type;
120       userSuppliedData = value;
121       userSuppliedNote = NULL;
122       pes=NULL;
123       numpes=0;
124       setFName(_fileName);
125     }
126
127     // Constructor for User Supplied Data
128     LogEntry(double _time,unsigned char _type, char* note,
129              int _lineNum,char *_fileName){
130       time = _time;
131       type = _type;
132       pes=NULL;
133       numpes=0;
134       setFName(_fileName);
135       if(note != NULL)
136         setUserSuppliedNote(note);
137     }
138
139
140    // Constructor for bracketed user supplied note
141     LogEntry(double bt, double et, unsigned char _type, char *note, int eventID){
142       time = bt;
143       endTime = et;
144       type = _type;
145       pes=NULL;
146       numpes=0;
147       event = eventID;
148       if(note != NULL)
149         setUserSuppliedNote(note);
150     }
151
152
153     // Constructor for multicast data
154     LogEntry(double tm, unsigned short m, unsigned short e, int ev, int p,
155              int ml, CmiObjId *d, double rt, int numPe, int *pelist){
156
157       type = CREATION_MULTICAST; 
158       mIdx = m; 
159       eIdx = e; 
160       event = ev; 
161       pe = p; 
162       time = tm; 
163       msglen = ml;
164       
165       if (d) id = *d; else {id.id[0]=id.id[1]=id.id[2]=id.id[3]=-1; };
166       recvTime = rt; 
167       numpes = numPe;
168       userSuppliedNote = NULL;
169       if (pelist != NULL) {
170         pes = new int[numPe];
171         for (int i=0; i<numPe; i++) {
172           pes[i] = pelist[i];
173         }
174       } else {
175         pes= NULL;
176       }
177
178     }
179
180
181     void setFName(char *_fileName){
182       if(_fileName == NULL){
183         fName = NULL;
184         flen = 0;
185       }else{
186         fName = new char[strlen(_fileName)+2];
187         fName[0] = ' ';
188         memcpy(fName+1,_fileName,strlen(_fileName)+1);
189         flen = strlen(fName)+1;
190       } 
191     }
192
193
194
195     // complementary function for adding papi data
196     void addPapi( int numPapiEvts, int *papi_ids, LONG_LONG_PAPI *papiVals);
197    
198     void setUserSuppliedData(int data){
199       userSuppliedData = data;
200     }
201
202     void setUserSuppliedNote(char *note){
203
204       int length = strlen(note)+1;
205       userSuppliedNote = new char[length];
206       memcpy(userSuppliedNote,note,length);
207       for(int i=0;i<length;i++){
208         if(userSuppliedNote[i] == '\n' || userSuppliedNote[i] == '\r'){
209           userSuppliedNote[i] = ' ';
210         }
211       }
212           
213     }
214         
215
216     /// A constructor for a memory usage record
217     LogEntry(unsigned char _type, double _time, long _memUsage) {
218       time = _time;
219       type = _type;
220       memUsage = _memUsage;
221       fName = NULL;
222       flen = 0;
223       pes=NULL;
224       numpes=0;
225     }
226
227
228     void *operator new(size_t s) {void*ret=malloc(s);_MEMCHECK(ret);return ret;}
229     void *operator new(size_t, void *ptr) { return ptr; }
230     void operator delete(void *ptr) {free(ptr); }
231 #if defined(WIN32) || CMK_MULTIPLE_DELETE
232     void operator delete(void *, void *) { }
233 #endif
234     void pup(PUP::er &p);
235     ~LogEntry(){
236       if (fName) delete [] fName;
237       if (userSuppliedNote) delete [] userSuppliedNote;
238     }
239 };
240
241 class TraceProjections;
242
243 /// log pool in trace projection
244 class LogPool {
245   friend class TraceProjections;
246   friend class TraceProjectionsBOC;
247   friend class controlPointManager;
248
249   private:
250     bool writeData;
251     unsigned int poolSize;
252     unsigned int numEntries;
253     LogEntry *pool;
254     FILE *fp;
255     FILE *deltafp;
256     FILE *stsfp;
257     FILE *rcfp;
258     char *fname;
259     char *dfname;
260     char *pgmname;
261     int binary;
262 #if CMK_PROJECTIONS_USE_ZLIB
263     gzFile deltazfp;
264     gzFile zfp;
265     int compressed;
266 #endif
267     // **CW** prevTime stores the timestamp of the last event
268     // written out to log. This allows the implementation of
269     // simple delta encoding and should only be used when
270     // writing out logs.
271     double prevTime;
272     double timeErr;
273     double globalEndTime; // used at the end on Pe 0 only
274
275     int headerWritten;
276     bool fileCreated;
277     void writeHeader();
278   public:
279     LogPool(char *pgm);
280     ~LogPool();
281     void setBinary(int b) { binary = b; }
282 #if CMK_PROJECTIONS_USE_ZLIB
283     void setCompressed(int c) { compressed = c; }
284 #endif
285     void createFile(const char *fix="");
286     void createSts(const char *fix="");
287     void createRC();
288     void openLog(const char *mode);
289     void closeLog(void);
290     void writeLog(void);
291     void write(int writedelta);
292     void writeSts(void);
293     void writeSts(TraceProjections *traceProj);
294     void writeRC(void);
295
296     void add(unsigned char type, unsigned short mIdx, unsigned short eIdx,
297              double time, int event, int pe, int ml=0, CmiObjId* id=0, 
298              double recvT=0.0, double cpuT=0.0, int numPe=0);
299
300     // complementary function to set papi info to current log entry
301     // must be called after an add()
302     void addPapi(int numPap, int *pap_ids, LONG_LONG_PAPI *papVals) {
303       pool[numEntries-1].addPapi(numPap, pap_ids, papVals);
304     }
305
306         /** add a record for a user supplied piece of data */
307         void addUserSupplied(int data);
308
309         /** add a record for a user supplied piece of data */
310         void addUserSuppliedNote(char *note);
311
312
313         void add(unsigned char type,double time,unsigned short funcID,int lineNum,char *fileName);
314   
315         void addMemoryUsage(unsigned char type,double time,double memUsage);
316         void addUserSuppliedBracketedNote(char *note, int eventID, double bt, double et);
317
318     void addCreationMulticast(unsigned short mIdx,unsigned short eIdx,double time,int event,int pe, int ml=0, CmiObjId* id=0, double recvT=0., int numPe=0, int *pelist=NULL);
319     void flushLogBuffer();
320     void postProcessLog();
321
322     void setWriteData(bool b){
323       writeData = b;
324     }
325
326 };
327
328 /*
329         class that represents a key in a CkHashtable with a string as a key
330 */
331 class StrKey {
332         char *str;
333         int len;
334         unsigned int key;
335         public:
336         StrKey(char *_str,int _len){
337                 str = _str;
338                 len = _len;
339                 key = 0;
340                 for(int i=0;i<len;i++){
341                         key += str[i];
342                 }
343         }
344         static CkHashCode staticHash(const void *k,size_t){
345                 return ((StrKey *)k)->key;
346         }
347         static int staticCompare(const void *a,const void *b,size_t){
348                 StrKey *p,*q;
349                 p = (StrKey *)a;
350                 q = (StrKey *)b;
351                 if(p->len != q->len){
352                         return 0;
353                 }
354                 for(int i=0;i<p->len;i++){
355                         if(p->str[i] != q->str[i]){
356                                 return 0;
357                         }
358                 }
359                 return 1;
360         }
361         inline CkHashCode hash() const{
362                 return key;
363         }
364         inline int compare(const StrKey &t) const {
365                 if(len != t.len){
366                         return 0;
367                 }
368                 for(int i=0;i<len;i++){
369                         if(str[i] != t.str[i]){
370                                 return 0;
371                         }       
372                 }
373                 return 1;
374         }
375         inline char *getStr(){
376                 return str;
377         }
378 };
379
380 class NestedEvent {
381  public:
382   int event, msgType, ep, srcPe, ml;
383   CmiObjId *idx;
384   NestedEvent() {}
385   NestedEvent(int _event, int _msgType, int _ep, int _srcPe, int _ml, CmiObjId *_idx) :
386     event(_event), msgType(_msgType), ep(_ep), srcPe(_srcPe), ml(_ml), idx(_idx) { }
387 };
388
389 /// class for recording trace projections events 
390 /**
391   TraceProjections will log Converse/Charm++ events and write into .log files;
392   events descriptions will be written into .sts file.
393 */
394 class TraceProjections : public Trace {
395   friend class TraceProjectionsBOC;
396  private:
397     LogPool* _logPool;        /**<  logpool for all events */
398     int curevent;
399     int execEvent;
400     int execEp;
401     int execPe;
402     int inEntry;
403     int computationStarted;
404
405     int funcCount;
406     CkHashtableT<StrKey,int> funcHashtable;
407
408         int traceNestedEvents;
409     CkQ<NestedEvent> nestedEvents;
410     
411     //as user now can specify the idx, it's possible that user may specify an existing idx
412     //so that we need a data structure to track idx. --added by Chao Mei
413     CkVec<int> idxVec;
414     int idxRegistered(int idx);    
415 #if CMK_HAS_COUNTER_PAPI
416     int papiEventSet;
417     LONG_LONG_PAPI *papiValues;
418 #endif
419
420   public:
421     int converseExit; // used for exits that bypass CkExit.
422     double endTime;
423
424     TraceProjections(char **argv);
425     void userEvent(int e);
426     void userBracketEvent(int e, double bt, double et);
427     void userSuppliedBracketedNote(char*, int, double, double);
428
429     void userSuppliedData(int e);
430     void userSuppliedNote(char* note);
431     void memoryUsage(double m);
432     void creation(envelope *e, int epIdx, int num=1);
433     void creationMulticast(envelope *e, int epIdx, int num=1, int *pelist=NULL);
434     void creationDone(int num=1);
435     void beginExecute(envelope *e);
436     void beginExecute(CmiObjId  *tid);
437     void beginExecute(int event,int msgType,int ep,int srcPe,int ml,CmiObjId *idx=NULL);
438     void beginExecuteLocal(int event,int msgType,int ep,int srcPe,int ml,CmiObjId *idx=NULL);
439     void endExecute(void);
440     void endExecuteLocal(void);
441     void messageRecv(char *env, int pe);
442     void beginIdle(double curWallTime);
443     void endIdle(double curWallTime);
444     void beginPack(void);
445     void endPack(void);
446     void beginUnpack(void);
447     void endUnpack(void);
448     void enqueue(envelope *e);
449     void dequeue(envelope *e);
450     void beginComputation(void);
451     void endComputation(void);
452
453     int traceRegisterUserEvent(const char*, int);
454     void traceClearEps();
455     void traceWriteSts();
456     void traceClose();
457     void traceBegin();
458     void traceEnd();
459     void traceFlushLog() { _logPool->flushLogBuffer(); }
460
461     //functions that perform function tracing
462     CkHashtableIterator *getfuncIterator(){return funcHashtable.iterator();};
463     int getFuncNumber(){return funcHashtable.numObjects();};
464     void regFunc(const char *name, int &idx, int idxSpecifiedByUser=0);
465     void beginFunc(char *name,char *file,int line);
466     void beginFunc(int idx,char *file,int line);
467     void endFunc(char *name);
468     void endFunc(int num);
469
470     /* This is for moving projections to being a charm++ module */
471     void closeTrace(void);
472
473     void setWriteData(bool b){
474       _logPool->setWriteData(b);
475     }
476
477     /* for overiding basic thread listener support in Trace class */
478     virtual void traceAddThreadListeners(CthThread tid, envelope *e);
479 };
480
481 using namespace PUP;
482
483 class toProjectionsFile : public toTextFile {
484  protected:
485   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
486  public:
487   //Begin writing to this file, which should be opened for ascii write.
488   toProjectionsFile(FILE *f_) :toTextFile(f_) {}
489 };
490 class fromProjectionsFile : public fromTextFile {
491  protected:
492   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
493  public:
494   //Begin writing to this file, which should be opened for ascii read.
495   fromProjectionsFile(FILE *f_) :fromTextFile(f_) {}
496 };
497
498 #if CMK_PROJECTIONS_USE_ZLIB
499 class toProjectionsGZFile : public PUP::er {
500   gzFile f;
501  protected:
502   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
503  public:
504   //Begin writing to this gz file, which should be opened for gz write.
505   toProjectionsGZFile(gzFile f_) :er(IS_PACKING), f(f_) {}
506 };
507 #endif
508
509
510
511
512
513 /// Disable the outputting of the trace logs
514 void disableTraceLogOutput();
515
516 /// Enable the outputting of the trace logs
517 void enableTraceLogOutput();
518
519
520 #endif
521
522 /*@}*/