00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <map>
00021 #include <stdio.h>
00022 #include "timer.h"
00023 #include <string.h>
00024 #include <assert.h>
00025
00026 typedef std::list<TaskTimer *> TaskStack;
00027
00028 #ifdef _OPENMP
00029 #include <omp.h>
00030
00031 #define MAX_THREADS 256
00032 static TaskStack thread_stacks[MAX_THREADS];
00033
00034 #else
00035 static TaskStack stack;
00036 #endif
00037
00038 #ifdef WIN32
00039 time_type get_time(){
00040 time_type r;
00041 QueryPerformanceCounter(&r);
00042 return r;
00043 }
00044
00045 double time_to_msec(time_type &t) {
00046 time_type freq;
00047 QueryPerformanceFrequency(&freq);
00048 return (double)(t.QuadPart) / (double)freq.QuadPart;
00049 }
00050
00051 time_type operator-(const time_type &a, const time_type &b) {
00052 time_type r;
00053 r.QuadPart = a.QuadPart - b.QuadPart;
00054 return r;
00055 }
00056 #else
00057 time_type get_time(){
00058 time_type r;
00059 gettimeofday(&r,0);
00060 return r;
00061 }
00062
00063 double time_to_msec(time_type &t) {
00064 return t.tv_sec * 1000.0 + t.tv_usec/1000.0;
00065 }
00066
00067 time_type operator-(const time_type &a, const time_type &b) {
00068 time_type r;
00069 timersub(&a,&b, &r);
00070 return r;
00071 }
00072 #endif
00073
00074
00075 void Timer::start() {
00076 total=0;
00077 running=true;
00078 s = get_time();
00079 }
00080
00081 double Timer::stop() {
00082 double r = value();
00083 running = false;
00084 return r;
00085 }
00086
00087 double Timer::value() {
00088 if (running)
00089 total += duration();
00090 return total;
00091 }
00092
00093
00094 void Timer::resume() {
00095 if (!running) {
00096 s = get_time();
00097 running = true;
00098 }
00099 }
00100
00101
00102 double Timer::duration() {
00103 time_type end, dt;
00104 end = get_time();
00105 dt = end - s;
00106 s = end;
00107 return time_to_msec(dt);
00108 }
00109
00110 TaskTimer::TaskTimer(const char *name) : name(name), currentTask(subtasks.end()) {
00111 }
00112
00113 #ifdef ENABLE_PROFILE
00114 double TaskTimer::stop() {
00115 if (subtasks.size()>0 && currentTask != subtasks.end()) currentTask->stop();
00116 return Timer::stop();
00117 }
00118
00119 TaskTimer *TaskTimer::setTask(const char *task) {
00120
00121 if (subtasks.size()>0 && currentTask != subtasks.end()) {
00122 currentTask->stop();
00123 }
00124 currentTask=subtasks.end();
00125 if (!task) return 0;
00126
00127 for (TaskList::iterator it = subtasks.begin(); it!=subtasks.end(); ++it) {
00128 if (strcmp(task, it->name)==0) {
00129 currentTask = it;
00130 break;
00131 }
00132 }
00133 if (currentTask != subtasks.end()) {
00134 currentTask->resume();
00135 return &(*currentTask);
00136 } else {
00137 TaskTimer t(task);
00138 subtasks.push_front(t);
00139 currentTask = subtasks.begin();
00140 assert(currentTask->name == task);
00141 return &(*currentTask);
00142 }
00143 }
00144
00145 #ifdef _OPENMP
00146
00147 void TaskTimer::addThreadTask(ThreadedTask &task)
00148 {
00149 task.tot_time += value();
00150 task.nb_thread++;
00151
00152 double sub = 0;
00153 for (TaskList::iterator it = subtasks.begin(); it!=subtasks.end(); ++it) {
00154 it->addThreadTask(task.subtasks[it->name]);
00155 sub += it->value();
00156 }
00157 task.self += value() - sub;
00158 }
00159 void TaskTimer::ThreadedTask::cmpFlatProfile(const char *name, CharDoubleMap &flatProfile)
00160 {
00161 flatProfile[name].incl += tot_time;
00162 flatProfile[name].self += self;
00163
00164 for (SubTaskMap::iterator it = subtasks.begin();
00165 it!=subtasks.end();
00166 ++it) {
00167 it->second.cmpFlatProfile(it->first, flatProfile);
00168 }
00169 }
00170
00171 void TaskTimer::ThreadedTask::print(const char *name, int indent, double total)
00172 {
00173
00174 printf("% 10.1fms % 7.2f%% %10.1fms % 7.2f%%", tot_time, 100.0*tot_time/total,
00175 self, 100.0f*self/total);
00176
00177 for (int i=1; i<indent; i++)
00178 printf(" | ");
00179 if (indent>=1)
00180 printf (" +-");
00181 printf(" %s\n", name);
00182
00183 for (SubTaskMap::iterator it = subtasks.begin();
00184 it!=subtasks.end();
00185 ++it)
00186 {
00187 it->second.print(it->first, indent+1,total);
00188 }
00189 }
00190
00191 double TaskTimer::printThreadTreeInfo(CharDoubleMap &flatProfile)
00192 {
00193 ThreadedTask tasks;
00194
00195 for (int i=0; i< MAX_THREADS; i++) {
00196 if (thread_stacks[i].size() > 0) {
00197 thread_stacks[i].front()->addThreadTask(tasks);
00198
00199 }
00200 }
00201 tasks.cmpFlatProfile("Root", flatProfile);
00202 tasks.print("Root", 0, tasks.tot_time);
00203 return tasks.tot_time;
00204 }
00205
00206 #endif
00207
00208 void TaskTimer::printStats(int indent, double total, CharDoubleMap &flatProfile) {
00209
00210 double incl = value();
00211
00212 double self= incl;
00213 for (TaskList::iterator it = subtasks.begin(); it!=subtasks.end(); ++it) {
00214 self -= it->value();
00215 }
00216 printf("% 10.1fms % 7.2f%% %10.1fms % 7.2f%%", incl, 100.0*incl/total,
00217 self, 100.0f*self/total);
00218
00219 flatProfile[name].self += self;
00220 flatProfile[name].incl += incl;
00221
00222 for (int i=1; i<indent; i++)
00223 printf(" | ");
00224 if (indent>=1)
00225 printf (" +-");
00226 printf(" %s\n", name);
00227
00228 for (TaskList::iterator it = subtasks.begin(); it!=subtasks.end(); ++it) {
00229 it->printStats(indent+1, total, flatProfile);
00230 }
00231 }
00232
00233 void TaskTimer::pushTask(const char *task) {
00234 #ifdef _OPENMP
00235 TaskStack &stack = thread_stacks[omp_get_thread_num()];
00236 #endif
00237 if (stack.size() == 0)
00238 stack.push_back(new TaskTimer("Other/Idle"));
00239
00240 stack.push_back(stack.back()->setTask(task));
00241 }
00242
00243 void TaskTimer::popTask()
00244 {
00245 #ifdef _OPENMP
00246 TaskStack &stack = thread_stacks[omp_get_thread_num()];
00247 #endif
00248
00249 assert(stack.size()>1);
00250 stack.back()->stop();
00251 stack.pop_back();
00252 stack.back()->resume();
00253 }
00254
00255 void TaskTimer::printStats()
00256 {
00257 CharDoubleMap flatProfile;
00258
00259 double total=0;
00260
00261 printf("Tree Profile:\n Incl-Abs Incl-%% Self-Abs Self-%% Name\n");
00262
00263 #ifdef _OPENMP
00264 total = printThreadTreeInfo(flatProfile);
00265 #else
00266 TaskTimer *root = (stack.size()>0 ? stack.front() : 0);
00267
00268 if (root) {
00269 total += root->value();
00270 root->printStats(0, root->value(), flatProfile);
00271 }
00272 #endif
00273
00274 printf("Flat Profile:\n Incl-Abs Incl-%% Self-Abs Self-%% Name\n");
00275 for (CharDoubleMap::iterator it=flatProfile.begin(); it!=flatProfile.end(); ++it) {
00276 printf("% 10.1fms % 7.2f%% %10.1fms % 7.2f%% %s\n",
00277 it->second.incl, 100.0f*it->second.incl/total,
00278 it->second.self, 100.0f*it->second.self/total,
00279 it->first);
00280 }
00281 }
00282 #else
00283 double TaskTimer::stop() { return 0; }
00284 TaskTimer *TaskTimer::setTask(const char *task) {return 0;}
00285 void TaskTimer::printStats(int indent, double total, CharDoubleMap &flatProfile) {}
00286 void TaskTimer::pushTask(const char *task) {}
00287 void TaskTimer::popTask() {}
00288 void TaskTimer::printStats() {}
00289 #endif