TORCS  1.3.9
The Open Racing Car Simulator
profiler.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 
3  file : profiler.cpp
4  author : Henrik Enqvist IB (henqvist@abo.fi)
5 
6  ***************************************************************************/
7 
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #ifdef PROFILER
18 
19 #include <algorithm>
20 #include <iostream>
21 #include <iomanip>
22 
23 #include <tgf.h>
24 
25 
27 
28 ProfileInstance::ProfileInstance(const char * pname) {
29  strncpy(this->name, pname, 255);
30  this->calls = 0;
31  this->addTime = 0.0;
32  this->totalTime = 0.0;
33  this->subTime = 0.0;
34  this->openCalls = 0;
35 }
36 
38 
39 Profiler * Profiler::profiler = NULL;
40 
41 Profiler::Profiler() {
42  fStartTime = GfTimeClock();
43  curProfile = NULL;
44 }
45 
46 Profiler::~Profiler() {
47  profiler = NULL;
48 }
49 
50 Profiler * Profiler::getInstance() {
51  if (profiler == NULL) {
52  profiler = new Profiler();
53  }
54  return profiler;
55 }
56 
57 void Profiler::startProfile(const char * name) {
58  ProfileInstance * newProfile;
59  // find or create profile instance
60  std::vector<ProfileInstance *>::iterator iter = vecProfiles.begin();
61  std::vector<ProfileInstance *>::iterator end = vecProfiles.end();
62  for (; iter != end; ++iter) {
63  if (strncmp((*iter)->name, name, 255) == 0) {
64  newProfile = (*iter);
65  goto found;
66  }
67  }
68  newProfile = new ProfileInstance(name);
69  vecProfiles.push_back(newProfile);
70  found:
71  newProfile->tmpStart = GfTimeClock();
72  ++(newProfile->openCalls);
73  ++(newProfile->calls);
74 
75  // add child and push current profile to stack
76  if (curProfile != NULL) {
77  curProfile->mapChildren.insert(std::pair<ProfileInstance*, void *>(newProfile, NULL));
78  stkProfiles.push_back(curProfile);
79  assert(stkProfiles.size() < 100);
80  }
81  curProfile = newProfile;
82 }
83 
84 void Profiler::stopProfile() {
85  assert(curProfile != NULL);
86  assert(curProfile->openCalls > 0);
87 
88  double elapsed = 0.0;
89  elapsed = GfTimeClock() - curProfile->tmpStart;
90  // add a warning if time to short
91  if (elapsed < 0.00001) {
92  this->mapWarning.insert(std::pair<ProfileInstance *, void*>(curProfile, NULL));
93  }
94  curProfile->addTime += elapsed;
95  // recursive call check
96  --(curProfile->openCalls);
97  if (curProfile->openCalls == 0) {
98  curProfile->totalTime += elapsed;
99  }
100 
101  // add child time to parent
102  std::vector<ProfileInstance *>::reverse_iterator last = stkProfiles.rbegin();
103  if (last != stkProfiles.rend()) {
104  curProfile = (*last);
105  curProfile->subTime += elapsed;
106  stkProfiles.pop_back();
107  } else {
108  curProfile = NULL;
109  }
110 }
111 
112 void Profiler::stopActiveProfiles() {
113  while (curProfile != NULL) {
114  this->stopProfile();
115  }
116 }
117 
118 bool instanceLess(const ProfileInstance * p1, const ProfileInstance * p2) {
119  return p1->totalTime < p2->totalTime;
120 }
121 
122 #define TRUNC(a) ( (a) < 0.001 ? 0.0 : (a) )
123 
124 void Profiler::printProfile() {
125  double total = GfTimeClock() - fStartTime;
126  std::cerr << "****************** PROFILE ***********************" << std::endl;
127  std::cerr << "Total : " << total << std::endl;
128  std::cerr << "| TOTAL % | OWN % | % of PA | CALLS | NAME" << std::endl;
129  std::cerr << "|---------|---------|---------|---------|---------" << std::endl;
130  sort(vecProfiles.begin(), vecProfiles.end(), instanceLess);
131  std::vector<ProfileInstance *>::reverse_iterator iter = vecProfiles.rbegin();
132  std::vector<ProfileInstance *>::reverse_iterator end = vecProfiles.rend();
133  for (; iter != end; ++iter) {
134  std::cerr << "| " << std::setprecision(3) << std::setw(7)
135  << TRUNC( (*iter)->totalTime * 100 / total )
136  << " | " << std::setprecision(3) << std::setw(7)
137  << TRUNC( ((*iter)->addTime -
138  (*iter)->subTime) * 100.0 / total )
139  << " | | "
140  << std::setw(7) << (*iter)->calls << " | " << (*iter)->name << std::endl;
141  std::map<ProfileInstance *, void*>::iterator childiter =
142  (*iter)->mapChildren.begin();
143  std::map<ProfileInstance *, void*>::iterator childend =
144  (*iter)->mapChildren.end();
145  for (; childiter != childend; ++childiter) {
146  std::cerr << "| " << std::setprecision(3) << std::setw(7)
147  << TRUNC( (*childiter).first->totalTime * 100 / total )
148  << " | " << std::setprecision(3) << std::setw(7)
149  << TRUNC( ((*childiter).first->addTime - (*childiter).first->subTime) * 100.0 / total )
150  << " | " << std::setprecision(3) << std::setw(7)
151  << TRUNC( 100 * (*childiter).first->totalTime / (*iter)->totalTime )
152  << " | " << std::setw(7) << (*childiter).first->calls
153  << " | " << (*childiter).first->name << std::endl;
154  }
155  std::cerr << "----------------------------------------------------------" << std::endl;
156  }
157  std::map<ProfileInstance *, void*>::iterator warniter = mapWarning.begin();
158  std::map<ProfileInstance *, void*>::iterator warnend = mapWarning.end();
159  for (; warniter != warnend; ++warniter) {
160  std::cerr << "Warning: Profile " << (*warniter).first->name << " may be to short" << std::endl;
161  }
162 }
163 
164 #endif /* PROFILER */
The Gaming Framework API.
char * name
Name of the parameter.
Definition: params.cpp:65
static int last
Definition: Convex.cpp:59
double GfTimeClock(void)
Get the time in seconds.
Definition: os.cpp:50