Newer
Older
/* Time_Tracer.h
Mark Woolrich, FMRIB Image Analysis Group
Copyright (C) 1999-2000 University of Oxford */
/* CCOPYRIGHT */
#if !defined(Time_Tracer_h)
#define Time_Tracer_h
#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include <set>
namespace Utilities{
class TimingFunction
{
public:
TimingFunction(const char * pstr):
str(pstr),
{
public:
bool operator()(const TimingFunction* t1, const TimingFunction* t2) const
{
return strcmp(t1->str, t2->str) < 0;
}
};
class comparer_time_taken
{
public:
bool operator()(const TimingFunction* t1, const TimingFunction* t2) const
{
return t1->time_taken > t2->time_taken;
}
};
void start() {start_time = clock();}
void end() {time_taken += clock()-start_time; times_called++;}
friend comparer_name;
friend comparer_time_taken;
friend ostream& operator<<(ostream& ostr, const TimingFunction* t);
protected:
const char* str;
clock_t time_taken;
int times_called;
clock_t start_time;
private:
TimingFunction();
const TimingFunction& operator=(TimingFunction&);
TimingFunction(TimingFunction&);
};
inline ostream& operator<<(ostream& ostr, const TimingFunction* t)
{
ostr << "<tr><td>" << t->str;
ostr.setf(0, ios::floatfield);
ostr << "<td align=center>" << float(t->time_taken)/CLOCKS_PER_SEC;
ostr << "<td align=center>" << t->times_called << "<td align=center>" << (t->time_taken/float(t->times_called))/CLOCKS_PER_SEC;
ostr << "</tr>";
return ostr;
}
// Non Newmat Tracer:
class Time_Tracer
{
public:
Time_Tracer(char* str)
{
{
tmp = "";
pad++;
for(unsigned int i = 0; i < pad; i++)
tmp = tmp + " ";
stk.push(string(str));
if(runningstack)
cout << tmp << str << endl;
}
if(timingon)
{
// see if already in list:
timingFunction = new TimingFunction(str);
set<TimingFunction*, TimingFunction::comparer_name>::iterator it = timingFunctions.find(timingFunction);
if(it== timingFunctions.end())
{
timingFunctions.insert(timingFunction);
}
else
{
timingFunction = *it;
}
timingFunction->start();
}
}
virtual ~Time_Tracer()
{
if(instantstack)
stk.pop();
if(runningstack && pad > 0)
{
cout << tmp << "finished" << endl;
pad--;
}
if(timingon)
{
timingFunction->end();
}
}
static void dump_times(const string& dir)
{
multiset<TimingFunction*, TimingFunction::comparer_time_taken> timingFunctionsByTimeTaken(timingFunctions.begin(), timingFunctions.end());
ofstream out;
out.open((dir + "/timings.html").c_str(), ios::out);
out << "<HTML><TITLE>Tracer Timings</TITLE><BODY><table border=3 cellspacing=5>" << endl;
out << "<tr><td>Function<td align=center>Total Time(secs)<td align=center>Num of calls<td align=center>Time per call(secs)</tr>" << endl;
copy(timingFunctionsByTimeTaken.begin(), timingFunctionsByTimeTaken.end(), ostream_iterator<TimingFunction*>(out, "\n"));
out << "</table></BODY></HTML>" << endl;
out.close();
}
static void dump_instant_stack()
{
// tmp stack to put values into for restoring stack after outputting
stack<string> tmpstk;
while(!stk.empty())
{
cout << stk.top() << endl;
tmpstk.push(stk.top());
stk.pop();
}
while(!tmpstk.empty())
{
stk.push(tmpstk.top());
tmpstk.pop();
}
}
static void setinstantstackon() {instantstack = true;}
static void setrunningstackon() {runningstack = true;}
static void settimingon() {timingon = true;}
protected:
static bool instantstack;
static bool runningstack;
static set<TimingFunction*, TimingFunction::comparer_name> timingFunctions;