Commit patch to not break on spaces.
[bowtie.git] / SeqAn-1.1 / seqan / basic / basic_profile.h
1  /*==========================================================================
2                 SeqAn - The Library for Sequence Analysis
3                           http://www.seqan.de 
4  ============================================================================
5   Copyright (C) 2007
6
7   This library is free software; you can redistribute it and/or
8   modify it under the terms of the GNU Lesser General Public
9   License as published by the Free Software Foundation; either
10   version 3 of the License, or (at your option) any later version.
11
12   This library is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17  ============================================================================
18   $Id: basic_profile.h,v 1.1 2008/08/25 16:20:02 langmead Exp $
19  ==========================================================================*/
20
21 //SEQAN_NO_GENERATED_FORWARDS: no forwards are generated for this file
22
23 #ifndef SEQAN_HEADER_BASIC_PROFILE_H
24 #define SEQAN_HEADER_BASIC_PROFILE_H
25
26 // todo: substitute defines with inlines
27 #ifndef SEQAN_PROFILE
28
29     #define SEQAN_PROSET(i,v)
30     #define SEQAN_PROADD(i,v)
31     #define SEQAN_PROSUB(i,v)
32         #define SEQAN_PROVAL(i)                         0
33     #define SEQAN_PROEXTRAS(i)
34     #define SEQAN_PROMARK(m)
35     #define SEQAN_PROENDMARK(m)
36     #define SEQAN_PRORESET
37         #define SEQAN_PROGETTIME                        0
38     #define SEQAN_PROTIMESTART(a)
39     #define SEQAN_PROTIMEDIFF(a)                0
40         // replace malloc and free in external tools
41         // with SEQAN_PROMALLOC and SEQAN_PROFREE to profile
42         // their memory usage
43     #define SEQAN_PROMALLOC(s)                  malloc(s)
44     #define SEQAN_PROFREE(p)                    free(p)
45
46 #else
47
48     #define SEQAN_PROSET(i,v)                   _proSet(i,v)
49     #define SEQAN_PROADD(i,v)                   _proAdd(i,v)
50     #define SEQAN_PROSUB(i,v)                   _proSub(i,v)
51         #define SEQAN_PROVAL(i)                         (_proData<>::_proValue[i])
52     #define SEQAN_PROEXTRAS(i)                  {_proData<>::_proExtraCount = i;}
53     #define SEQAN_PROMARK(m)                    _proMark(m)
54     #define SEQAN_PROENDMARK(m)                 _proEndMark(m)
55     #define SEQAN_PRORESET                              _proReset()
56         #define SEQAN_PROGETTIME                        sysTime()
57     #define SEQAN_PROTIMESTART(a)               _proFloat a = sysTime()
58     #define SEQAN_PROTIMEDIFF(a)                (sysTime() - a)
59     #define SEQAN_PROMALLOC(s)                  _proMalloc(s)
60     #define SEQAN_PROFREE(p)                    _proFree(p)
61
62 #endif
63
64 #ifdef PLATFORM_WINDOWS
65     typedef __int64   _proInt;
66 #else
67     typedef int64_t _proInt;
68 #endif
69
70     typedef double    _proFloat;
71
72
73     typedef _proFloat _proTValue;
74
75     enum _proConsts {
76         SEQAN_PROPAGESIZE         = 4096, // B in byte
77         SEQAN_PROFLOAT            = 0,
78         SEQAN_PROINT              = 1,
79         SEQAN_PROTIME             = 2,
80         SEQAN_PROTYPEMASK         = 3,
81         SEQAN_PROSTATE            = 4
82     };
83
84     enum _proValueIndex {
85                 SEQAN_PROSYSTIME                  = 0,
86                 SEQAN_PROCPUTIME                  = 1,
87         SEQAN_PROMEMORY           = 2,    // current memory usage (state value)
88         SEQAN_PROIO               = 3,    // IOs done (measured in Blocks of size B)
89         SEQAN_PROIORANDOM         = 4,    // IOs calls done (read/write calls done)
90         SEQAN_PROIOVOLUME         = 5,    // current disk usage (state value)
91         SEQAN_PRODEPTH            = 6,    // algorithmic rec. depth or loop count
92                 SEQAN_PROOPENFILES                = 7,    // currently opened files
93         SEQAN_PROIWAIT            = 8,    // waiting time (initiating)
94         SEQAN_PROCWAIT            = 9,    // waiting time (completing)
95                 SEQAN_PROEXTRA1           = 10,
96                 SEQAN_PROEXTRA2           = 11,
97                 SEQAN_PROEXTRA3           = 12,
98                 SEQAN_PROINDEXCOUNT       = 13,
99                 SEQAN_PROEXTRACOUNT       = 3
100     };
101
102     const char _proValueType[] = {
103                 SEQAN_PROTIME, 
104                 SEQAN_PROTIME, 
105         SEQAN_PROINT + SEQAN_PROSTATE, 
106         SEQAN_PROINT,
107         SEQAN_PROINT,
108         SEQAN_PROINT + SEQAN_PROSTATE, 
109         SEQAN_PROINT + SEQAN_PROSTATE, 
110         SEQAN_PROINT + SEQAN_PROSTATE, 
111         SEQAN_PROFLOAT,
112         SEQAN_PROFLOAT,
113         SEQAN_PROFLOAT + SEQAN_PROSTATE,
114         SEQAN_PROFLOAT + SEQAN_PROSTATE,
115         SEQAN_PROFLOAT + SEQAN_PROSTATE
116     };
117
118     typedef _proTValue _proTStates[SEQAN_PROINDEXCOUNT];
119     typedef _proFloat  _proTTimes[SEQAN_PROINDEXCOUNT];
120
121
122
123     struct _proFile;
124
125         template <typename T = void>
126         struct _proData
127         {
128                 static _proTStates      _proValue;
129                 static _proTTimes       _proLastUpdate;
130                 static int                      _proExtraCount;
131             
132                 static clock_t          _proCpuTimeLast;                        // clock_t wraps around every 72mins
133                 static _proInt          _proCpuTimeOffset;                      // we have to work around this
134
135                 static _proFile*        _proPFile;
136                 static _proFile*        _proPFileStream;
137         };
138
139         template <typename T> _proTStates       _proData<T>::_proValue = {};
140         template <typename T> _proTStates       _proData<T>::_proLastUpdate = {};
141         template <typename T> int                       _proData<T>::_proExtraCount = 0;
142         template <typename T> clock_t           _proData<T>::_proCpuTimeLast = 0;
143         template <typename T> _proInt           _proData<T>::_proCpuTimeOffset = 0;
144         template <typename T> _proFile*         _proData<T>::_proPFile = NULL;
145         template <typename T> _proFile*         _proData<T>::_proPFileStream = NULL;
146
147
148         inline _proFile* & _proPFile()                  { return _proData<>::_proPFile; }
149         inline _proFile* & _proPFileStream()    { return _proData<>::_proPFileStream; }
150
151
152 // HINT: The unit of all time functions is second.
153     inline _proFloat cpuTime() {
154         clock_t now = clock();
155         if (_proData<>::_proCpuTimeLast > now) {                // test for time wrap
156                 _proData<>::_proCpuTimeOffset += (~0u);         // got one
157                 _proData<>::_proCpuTimeOffset ++;
158 //              printf("\n!!WRAP!! old:%d, now:%d    ofs:%d\n",_proData<>::_proCpuTimeLast,now,_proData<>::_proCpuTimeOffset);
159         }
160                 _proData<>::_proCpuTimeLast = now;
161         return (_proData<>::_proCpuTimeOffset + now) / (_proFloat)CLOCKS_PER_SEC;
162         }
163
164     #ifdef PLATFORM_WINDOWS
165 //        inline _proFloat sysTime() { return GetTickCount() * 1e-3; }
166                 inline _proFloat sysTime() { return ( (_proFloat) clock() ) / CLOCKS_PER_SEC; }
167     #else
168
169                 #include <unistd.h>
170                 #if _POSIX_TIMERS > 0
171                         #ifndef SEQAN_USE_CLOCKGETTIME
172                         #define SEQAN_USE_CLOCKGETTIME
173                         #endif
174                 #endif
175                 
176                 #ifndef SEQAN_USE_CLOCKGETTIME
177                 /* some systems e.g. darwin have no clock_gettime */
178                 
179                         #include <sys/time.h>
180                         
181                         inline _proFloat sysTime() {
182                                 struct timeval tp;
183                                 gettimeofday(&tp, NULL);
184                                 return tp.tv_sec + tp.tv_usec * 1e-6;
185                         }
186
187                 #else
188
189                         inline _proFloat sysTime() {
190                           /*struct timespec tp;
191                                 clock_gettime(CLOCK_MONOTONIC, &tp);
192                                   return tp.tv_sec + tp.tv_nsec * 1e-9;*/
193                                 return 0; // BTL: to compile under cygwin
194                         }
195
196             #endif
197
198     #endif
199
200     
201     struct _proFile {
202
203         FILE   *out;
204         bool   running;
205
206         _proFloat dumpStep;            // 0 .. manual dump mode, >0 .. live stream
207         _proFloat dumpNext;        
208
209         _proTStates all, last;
210         ::std::string mark;
211         unsigned        lines;
212
213         _proFile() {
214             running = false;
215         }
216
217         _proFile(char const *fname, _proFloat _dumpStep = 300.0) { // five minutes default dump interval
218             running = false;
219             start(fname, _dumpStep);
220         }
221
222         ~_proFile() {
223             if (running) stop();
224         }
225
226         inline void start(char const *fname, _proFloat _dumpStep = 300.0, bool append = false) {
227             if (append)
228                 out = fopen(fname, "a");
229             else {
230                 out = fopen(fname, "w");
231                 dumpHeader();
232             }
233
234             if (!out) printf("WARNING: proFile could not be opened.\n");
235
236                         setTime(_proData<>::_proValue);
237             syncAll(all);
238             syncAll(last);
239             running      = true;
240             lines                = 0;
241             dumpStep     = _dumpStep;
242             dumpNext     = sysTime();
243             dump(last);
244         }
245
246         inline void stop() {
247             dump(last);
248             maximize(all, last);
249             if (dumpStep == 0) {
250                 mark = "Zusammenfassung";
251                 dump(all);
252             }
253             fclose(out);
254             running = false;
255         }
256
257         inline void syncTime(_proTStates &dst) {
258             memcpy(dst, _proData<>::_proValue, 2 * sizeof(_proTValue));
259         }
260
261         inline void sync(_proTStates &dst) {
262             memcpy(&(dst[2]), &(_proData<>::_proValue[2]), sizeof(_proTStates) - 2 * sizeof(_proTValue));
263         }
264
265         inline void syncAll(_proTStates &dst) {
266             memcpy(dst, _proData<>::_proValue, sizeof(_proTStates));
267         }
268
269                 inline static void setTime(_proTStates &dst) {
270             dst[0] = sysTime();
271                         dst[1] = cpuTime();
272                 }
273
274         inline void maximize(_proTStates &dst, _proTStates const &src) {
275             for(int i = 0; i < SEQAN_PROINDEXCOUNT; ++i)
276                 if (((_proValueType[i] & SEQAN_PROSTATE) != 0))
277                     if (dst[i] < src[i])
278                         dst[i] = src[i];
279         }
280
281         inline void dumpTab() {
282             if (!bol)
283                 fprintf(out, " \t");
284             bol = false;
285         }
286
287         inline void dumpEndl() { fprintf(out, "\n"); }
288
289         inline void dumpHeader() {
290             fprintf(out, "\"Echtzeit\"\t\"CPU-Zeit\"\t\"Speicher\"\t\"I/O-Zugriffe\"\t\"wahlfreie I/Os\"\t\"I/O-Volumen\"\t\"Rekursionstiefe\"\t\"Offene Dateien\"\t\"Idle-Zeit vor I/O\"\t\"Idle-Zeit nach I/O\"\n");
291         }
292
293         inline void dumpTime(_proFloat seconds) {
294                         if (seconds < 0) {
295                                 fputc('-', out);
296                                 seconds = -seconds;
297                         }
298             int secs    = (int)seconds;
299             int mins    = secs/60;  secs -= 60*mins;
300             int hours   = mins/60;  mins -= 60*hours;
301             fprintf(out, "%d:%02d:%02d", hours, mins, secs);
302         }
303
304         inline void dumpTimeEx(_proFloat seconds) {
305             int milli   = (int)(seconds * 1000.0);
306             int secs    = (int)seconds;
307             int mins    = secs/60;  secs -= 60*mins;
308             int hours   = mins/60;  mins -= 60*hours;
309             fprintf(out, "%d:%02d:%02d.%03d", hours, mins, secs, milli);
310         }
311
312         inline void dumpValue(_proTStates &stat, int valNum) {
313                         _proFloat f = stat[valNum];
314             if ((_proValueType[valNum] & SEQAN_PROSTATE) == 0)
315                                 f = _proData<>::_proValue[valNum] - f;
316
317                         switch (_proValueType[valNum] & SEQAN_PROTYPEMASK) {
318                                 case SEQAN_PROINT:                                                                      // state value -> print last seen maximum
319                                         fprintf(out, "%.0f", f);
320                                         break;
321
322                                 case SEQAN_PROFLOAT:
323                                         fprintf(out, "%f", f);
324                                         break;
325
326                                 case SEQAN_PROTIME:
327                                         dumpTimeEx(f);
328                         }
329         }
330
331         inline void dumpSysValues(_proTStates &stat) {
332             for(int i = 0; i < SEQAN_PROINDEXCOUNT - SEQAN_PROEXTRACOUNT; ++i) {
333                 dumpTab();
334                 dumpValue(stat, i);
335             }
336         }
337
338         inline void dumpExtraValues(_proTStates &stat) {
339             for(int i = 0; i < _proData<>::_proExtraCount; ++i) {
340                 dumpTab();
341                 dumpValue(stat, SEQAN_PROINDEXCOUNT - SEQAN_PROEXTRACOUNT + i);
342             }
343         }
344         
345         inline void dumpMark() {
346             if (!mark.empty()) {
347                 dumpTab();
348                 fprintf(out, "\"%s\"", mark.c_str());
349                 mark.erase();
350             }
351         }
352
353         inline void dump(_proTStates &stat) {
354                         setTime(_proData<>::_proValue);
355             dumpNext += dumpStep;
356             bol = true;
357             bool _flush = ((dumpStep == 0.0)) || ((lines & 16) == 0);
358
359             dumpSysValues(stat);
360             dumpExtraValues(stat);
361             dumpMark();
362             dumpEndl();
363             if (_flush) fflush(out);
364             ++lines;
365         }
366
367         inline void signalDumpTest(_proFloat now) {
368             if (dumpStep > 0 && now > dumpNext && running) {
369                 dump(last);
370                 maximize(all, last);
371                 sync(last);
372             }
373         }
374
375         inline void signalNewMax(int valNum) {
376             if (running)
377                 if (last[valNum] < _proData<>::_proValue[valNum])
378                     last[valNum] = _proData<>::_proValue[valNum];
379         }
380
381         inline void setMark(const char *text) {
382             if (running) {
383                 mark = text;
384                 if (dumpStep == 0.0) {
385                     dump(last);                 // manual dump;
386                     maximize(all, last);
387                     sync(last);
388                 }
389             }
390         }
391         
392         inline void reset() {
393                 syncTime(last);
394         }
395
396         inline void setEndMark(const char *text) {
397             if (running) {
398                                 setMark(text);
399                                 reset();
400                         }
401         }
402
403     private:
404         
405         bool bol;   // begin of line
406     };
407
408
409
410 /*
411     inline void _proSignalDumpTest(_proFloat now);
412     inline void _proSignalNewMax(int valNum);
413     inline void _proMark(const char *text);
414     inline void _proEndMark(const char *text);
415     inline void _proReset();
416
417     inline void _proSet(int valNum, _proFloat value);
418     inline void _proAdd(int valNum, _proFloat value);
419     inline void _proSub(int valNum, _proFloat value);
420     
421     // simple interface for external programs
422     inline void *_proMalloc(size_t size);
423     inline void _proFree(void *_ptr);
424 */
425
426     inline void _proSignalDumpTest(_proFloat now) {
427         if (_proData<>::_proPFileStream) _proData<>::_proPFileStream->signalDumpTest(now);
428     }
429
430     inline void _proSignalNewMax(int valNum) {
431         if (((_proValueType[valNum] & SEQAN_PROSTATE) != 0)) {
432             if (_proData<>::_proPFileStream) _proData<>::_proPFileStream->signalNewMax(valNum);
433             if (_proData<>::_proPFile)       _proData<>::_proPFile->signalNewMax(valNum);
434         }
435     }
436
437     inline void _proMark(const char *text) {
438         if (_proData<>::_proPFileStream) _proData<>::_proPFileStream->setMark(text);
439         if (_proData<>::_proPFile)       _proData<>::_proPFile->setMark(text);
440     }
441
442     inline void _proEndMark(const char *text) {
443         if (_proData<>::_proPFileStream) { _proData<>::_proPFileStream->setEndMark(text); }
444         if (_proData<>::_proPFile)       { _proData<>::_proPFile->setEndMark(text); }
445     }
446
447     inline void _proReset() {
448         if (_proData<>::_proPFileStream) { _proData<>::_proPFileStream->reset(); }
449         if (_proData<>::_proPFile)       { _proData<>::_proPFile->reset(); }
450     }
451
452
453
454
455     inline void _proSet(_proValueIndex valNum, _proFloat value) {
456         _proFloat now = sysTime();
457         _proData<>::_proLastUpdate[valNum] = now;
458         if (_proData<>::_proValue[valNum] < value) {
459             _proData<>::_proValue[valNum] = value;
460             _proSignalNewMax(valNum);
461         } else
462             _proData<>::_proValue[valNum] = value;
463         _proSignalDumpTest(now);
464     }
465
466     inline void _proAdd(_proValueIndex valNum, _proFloat value) {
467         _proFloat now = sysTime();
468         _proData<>::_proValue[valNum] += value;
469         _proData<>::_proLastUpdate[valNum] = now;
470         if (valNum == SEQAN_PROIO) _proAdd(SEQAN_PROIORANDOM, 1);
471         _proSignalNewMax(valNum);
472         _proSignalDumpTest(now);
473     }
474
475     inline void _proSub(_proValueIndex valNum, _proFloat value) {
476         _proFloat now = sysTime();
477         _proData<>::_proValue[valNum] -= value;
478         _proData<>::_proLastUpdate[valNum] = now;
479         _proSignalDumpTest(now);
480     }
481     
482     // simple interface for external programs
483     inline void *_proMalloc(size_t size) {
484         size_t *ptr = reinterpret_cast<size_t*>(malloc(size + sizeof(size_t)));
485         if (ptr) {
486                 _proAdd(SEQAN_PROMEMORY, *ptr = size);
487 //                      printf("_proMalloc %x size %d\n", ptr, size);
488                 ++ptr;
489         }
490         return ptr;
491     }
492
493     inline void _proFree(void *_ptr) {
494         size_t *ptr = reinterpret_cast<size_t*>(_ptr);
495         if (ptr) {
496                 --ptr;
497 //                      printf("_proFree   %x size %d\n", _ptr, *ptr);
498                 _proSub(SEQAN_PROMEMORY, *ptr);
499         }
500         free(ptr);
501     }
502
503 #endif