Panda3D
|
00001 // Filename: profileTimer.cxx 00002 // Created by: 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "profileTimer.h" 00016 00017 #include "pmap.h" 00018 00019 using namespace std; 00020 00021 // See ProfileTimer.h for documentation. 00022 00023 00024 EXPCL_PANDAEXPRESS ProfileTimer Skyler_timer_global=ProfileTimer("startup"); 00025 00026 ProfileTimer* ProfileTimer::_head; 00027 00028 ProfileTimer:: 00029 ProfileTimer(const char* name, int maxEntries) : 00030 _entries(0), 00031 _autoTimerCount(0) { 00032 // Keep a list of the ProfileTimers, so we can print them: 00033 _next=_head; 00034 _head=this; 00035 if (name) { 00036 init(name, maxEntries); 00037 } 00038 } 00039 00040 ProfileTimer:: 00041 ProfileTimer(const ProfileTimer& other) { 00042 // Add to list: 00043 _next=_head; 00044 _head=this; 00045 // init it: 00046 _name=other._name; 00047 _maxEntries=other._maxEntries; 00048 if (_name) { 00049 init(_name, _maxEntries); 00050 } 00051 // Copy other entries: 00052 _on=other._on; 00053 _elapsedTime=other._elapsedTime; 00054 _autoTimerCount=other._autoTimerCount; 00055 _entryCount=other._entryCount; 00056 if (other._entries) { 00057 memcpy(_entries, other._entries, _entryCount * sizeof(TimerEntry)); 00058 } 00059 } 00060 00061 ProfileTimer:: 00062 ~ProfileTimer() { 00063 PANDA_FREE_ARRAY(_entries); 00064 // Remove this from the list: 00065 if (_head==this) { 00066 _head=_next; 00067 } else { 00068 ProfileTimer* p=_head; 00069 ProfileTimer* prior=p; 00070 while (p) { 00071 if (p==this) { 00072 prior->_next=_next; 00073 break; 00074 } 00075 prior=p; 00076 p=p->_next; 00077 } 00078 } 00079 } 00080 00081 void ProfileTimer:: 00082 init(const char* name, int maxEntries) { 00083 _name=name; 00084 _maxEntries=maxEntries; 00085 _entries = (TimerEntry *)PANDA_MALLOC_ARRAY(_maxEntries * sizeof(TimerEntry)); 00086 _entryCount=0; 00087 _elapsedTime=0.0; 00088 _on=0.0; 00089 } 00090 00091 double ProfileTimer:: 00092 getTotalTime() const { 00093 double total=0; 00094 int i; 00095 for (i=0; i<_entryCount; ++i) { 00096 TimerEntry& te=_entries[i]; 00097 total+=te._time; 00098 } 00099 return total; 00100 } 00101 00102 void ProfileTimer:: 00103 consolidateAllTo(ostream &out) { 00104 ProfileTimer* p=_head; 00105 while (p) { 00106 p->consolidateTo(out); 00107 p=p->_next; 00108 } 00109 } 00110 00111 void ProfileTimer:: 00112 consolidateTo(ostream &out) const { 00113 pmap<string, double> entries; 00114 int i; 00115 for (i=0; i<_entryCount; ++i) { 00116 TimerEntry& te=_entries[i]; 00117 entries[te._tag]+=te._time; 00118 } 00119 out << "-------------------------------------------------------------------\n" 00120 << "Profile Timing of " << _name 00121 << "\n\n"; // ...should print data and time too. 00122 double total=0; 00123 { 00124 pmap<string, double>::const_iterator i=entries.begin(); 00125 for (;i!=entries.end(); ++i) { 00126 out << " " << setw(50) << i->first << ": " 00127 << setiosflags(ios::fixed) << setprecision(6) << setw(10) << i->second << "\n"; 00128 total+=i->second; 00129 } 00130 } 00131 out << "\n [Total Time: " 00132 << setiosflags(ios::fixed) << setprecision(6) << total 00133 << " seconds]\n" 00134 << "-------------------------------------------------------------------\n"; 00135 out << endl; 00136 } 00137 00138 void ProfileTimer:: 00139 printAllTo(ostream &out) { 00140 ProfileTimer* p=_head; 00141 while (p) { 00142 p->printTo(out); 00143 p=p->_next; 00144 } 00145 } 00146 00147 void ProfileTimer:: 00148 printTo(ostream &out) const { 00149 out << "-------------------------------------------------------------------\n" 00150 << "Profile Timing of " << _name 00151 << "\n\n"; // ...should print data and time too. 00152 double total=0; 00153 int i; 00154 for (i=0; i<_entryCount; ++i) { 00155 TimerEntry& te=_entries[i]; 00156 out << " " << setw(50) << te._tag << ": " 00157 << setiosflags(ios::fixed) << setprecision(6) << setw(10) << te._time << "\n"; 00158 total+=te._time; 00159 } 00160 out << "\n [Total Time: " 00161 << setiosflags(ios::fixed) << setprecision(6) << total 00162 << " seconds]\n" 00163 << "-------------------------------------------------------------------\n"; 00164 out << endl; 00165 } 00166 00167 ProfileTimer::AutoTimer::AutoTimer(ProfileTimer& profile, const char* tag) : 00168 _profile(profile) { 00169 _tag=tag; 00170 if (_profile._autoTimerCount) { 00171 // ...this is a nested call to another AutoTimer. 00172 // Assign the time to the prior AutoTimer: 00173 _profile.mark(_profile._entries[_profile._entryCount-1]._tag); 00174 } else { 00175 // ...this is not a nested call. 00176 _profile.mark("other"); 00177 } 00178 // Tell the profile that it's in an AutoTimer: 00179 ++_profile._autoTimerCount; 00180 _profile.mark(_tag); 00181 } 00182 00183 00184