00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <iostream>
00033 #include <utility>
00034 #include <cstdio>
00035 #include <cmath>
00036 #include <algorithm>
00037 #include "walltimer.h"
00038 #include "walltime_c.h"
00039 #include "error_handling.h"
00040
00041 using namespace std;
00042
00043 void wallTimer::start()
00044 { start(wallTime()); }
00045 void wallTimer::stop()
00046 { stop(wallTime()); }
00047 double wallTimer::acc() const
00048 { return acc(wallTime()); }
00049
00050 int wallTimerSet::getIndex(const string &name)
00051 {
00052 maptype::const_iterator it = lut.find(name);
00053 if (it!=lut.end())
00054 return it->second;
00055 timer.push_back(wallTimer());
00056 lut[name]=timer.size()-1;
00057 return timer.size()-1;
00058 }
00059
00060 void wallTimerSet::start(int index)
00061 { timer[index].start(); }
00062 void wallTimerSet::stop(int index)
00063 { timer[index].stop(); }
00064 void wallTimerSet::stopstart(int index1, int index2)
00065 { double t=wallTime(); timer[index1].stop(t); timer[index2].start(t); }
00066 void wallTimerSet::reset(int index)
00067 { timer[index].reset(); }
00068 double wallTimerSet::acc(int index)
00069 { return timer[index].acc(); }
00070 void wallTimerSet::start(const string &name)
00071 { start(getIndex(name)); }
00072 void wallTimerSet::stop(const string &name)
00073 { stop(getIndex(name)); }
00074 void wallTimerSet::stopstart(const string &name1, const string &name2)
00075 { stopstart(getIndex(name1),getIndex(name2)); }
00076 void wallTimerSet::reset(const string &name)
00077 { reset(getIndex(name)); }
00078 double wallTimerSet::acc(const string &name)
00079 { return acc(getIndex(name)); }
00080
00081 void wallTimerSet::report() const
00082 {
00083 cout << "\nWall clock timer report:" << endl;
00084 for (maptype::const_iterator it=lut.begin(); it!=lut.end(); ++it)
00085 printf(" %-15s: %10.5fs\n", it->first.c_str(), timer[it->second].acc());
00086 cout << "End wall clock timer report\n" << endl;
00087 }
00088
00089 wallTimerSet wallTimers;
00090
00091 namespace {
00092
00093 class tstack_node;
00094
00095 typedef map<string,tstack_node>::iterator Ti;
00096 typedef map<string,tstack_node>::const_iterator Tci;
00097 typedef pair<Tci,double> Tipair;
00098
00099 class tstack_node
00100 {
00101 public:
00102 tstack_node *parent;
00103 wallTimer wt;
00104 string name;
00105 map<string,tstack_node> child;
00106
00107 tstack_node(const string &name_, tstack_node *parent_)
00108 : parent(parent_), name(name_) {}
00109
00110 int max_namelen() const
00111 {
00112 int res=name.length();
00113 for (Tci it=child.begin(); it!=child.end(); ++it)
00114 res=max(res,it->second.max_namelen());
00115 return res;
00116 }
00117 };
00118
00119 tstack_node tstack_root("root",0);
00120 tstack_node *curnode=0;
00121 double overhead=0.;
00122
00123 struct timecomp
00124 {
00125 bool operator() (const Tipair &a, const Tipair &b) const
00126 { return a.second>b.second; }
00127 };
00128
00129 void tstack_report(const tstack_node &node, const string &indent, int twidth,
00130 int slen)
00131 {
00132 double total=node.wt.acc();
00133 vector<Tipair> tmp;
00134 for (Tci it=node.child.begin(); it!=node.child.end(); ++it)
00135 tmp.push_back(make_pair(it,it->second.wt.acc()));
00136
00137 if (tmp.size()>0)
00138 {
00139 sort(tmp.begin(),tmp.end(),timecomp());
00140 double tsum=0;
00141 printf("%s|\n", indent.c_str());
00142 for (unsigned i=0; i<tmp.size(); ++i)
00143 {
00144 printf("%s+- %-*s:%6.2f%% (%*.4fs)\n",indent.c_str(),slen,
00145 (tmp[i].first->first).c_str(), 100*tmp[i].second/total,twidth,
00146 tmp[i].second);
00147 tstack_report(tmp[i].first->second,indent+"| ",twidth,slen);
00148 tsum+=tmp[i].second;
00149 }
00150 printf("%s+- %-*s:%6.2f%% (%*.4fs)\n%s\n",indent.c_str(),slen,
00151 "<unaccounted>",100*(total-tsum)/total,twidth,total-tsum,indent.c_str());
00152 }
00153 }
00154
00155 }
00156
00157 void tstack_push(const string &name)
00158 {
00159 double t0=wallTime();
00160 if (curnode==0) curnode=&tstack_root;
00161 Ti it=curnode->child.find(name);
00162 if (it==curnode->child.end())
00163 it=curnode->child.insert (make_pair(name,tstack_node(name,curnode))).first;
00164 curnode=&(it->second);
00165 double t1=wallTime();
00166 curnode->wt.start(0.5*(t0+t1));
00167 overhead+=t1-t0;
00168 }
00169 void tstack_pop(const string &name)
00170 {
00171 double t0=wallTime();
00172 planck_assert(curnode && (curnode->name==name), "invalid tstack operation");
00173 double t1=wallTime();
00174 curnode->wt.stop(0.5*(t0+t1));
00175 curnode=curnode->parent;
00176 overhead+=t1-t0;
00177 }
00178 void tstack_pop()
00179 {
00180 double t0=wallTime();
00181 planck_assert(curnode, "invalid tstack operation");
00182 double t1=wallTime();
00183 curnode->wt.stop(0.5*(t0+t1));
00184 curnode=curnode->parent;
00185 overhead+=t1-t0;
00186 }
00187 void tstack_replace(const string &name2)
00188 {
00189 double t0=wallTime();
00190 planck_assert(curnode, "invalid tstack operation");
00191 tstack_node *savenode=curnode;
00192 curnode=curnode->parent;
00193 Ti it=curnode->child.find(name2);
00194 if (it==curnode->child.end())
00195 it=curnode->child.insert(make_pair(name2,tstack_node(name2,curnode))).first;
00196 curnode=&(it->second);
00197 double t1=wallTime();
00198 double t=0.5*(t0+t1);
00199 savenode->wt.stop(t);
00200 curnode->wt.start(t);
00201 overhead+=t1-t0;
00202 }
00203 void tstack_replace(const string &name1, const string &name2)
00204 {
00205 planck_assert(curnode && (curnode->name==name1), "invalid tstack operation");
00206 tstack_replace(name2);
00207 }
00208
00209 void tstack_report(const string &stem)
00210 {
00211 const tstack_node *ptr = 0;
00212 for (Tci it=tstack_root.child.begin(); it!=tstack_root.child.end(); ++it)
00213 if (it->first==stem) ptr=&(it->second);
00214 planck_assert(ptr,"invalid stem");
00215 int slen=string("<unaccounted>").size();
00216 slen = max(slen,ptr->max_namelen());
00217
00218 double total=ptr->wt.acc();
00219 printf("\nTotal wall clock time for '%s': %1.4fs\n",stem.c_str(),total);
00220
00221 int logtime=max(1,int(log10(total)+1));
00222 tstack_report(*ptr,"",logtime+5,slen);
00223
00224 printf("\nAccumulated timing overhead: approx. %1.4fs\n",overhead);
00225 }