00001 #ifndef Impala_Util_TimeStats_h 00002 #define Impala_Util_TimeStats_h 00003 00004 #include <vector> 00005 #include "Basis/Timer.h" 00006 00007 00008 namespace Impala 00009 { 00010 namespace Util 00011 { 00012 00018 class TimeStats 00019 { 00020 public: 00021 00022 class Group 00023 { 00024 public: 00025 00026 Group(CString name) : mName(name) 00027 { 00028 Clear(); 00029 } 00030 00031 void 00032 AddMeasurement(double time) 00033 { 00034 mMeasurements.push_back(time); 00035 mTotal += time; 00036 } 00037 00038 void 00039 Clear() 00040 { 00041 mTotal = 0; 00042 mMeasurements.clear(); 00043 } 00044 00045 String mName; 00046 std::vector<double> mMeasurements; 00047 double mTotal; 00048 double mPercentage; // only valid when ComputePercentages 00049 // of the TimeStats object is called 00050 }; 00051 00052 TimeStats(bool relative = false) : mClock(1) 00053 { 00054 mIsTiming = false; 00055 mCurrentGroup = 0; 00056 mRelative = relative; 00057 } 00058 00059 void 00060 AddGroup(CString name) 00061 { 00062 mGroups.push_back(new Group(name)); 00063 } 00064 00065 void 00066 AddGroupsFromSub(TimeStats* sub) 00067 { 00068 for (int i=0 ; i<sub->NrGroups() ; i++) 00069 AddGroup(sub->GetGroup(i)->mName); 00070 } 00071 00072 void 00073 MeasureFirst() 00074 { 00075 StopTime(); 00076 SelectGroup(0); 00077 StartTime(); 00078 } 00079 00080 void 00081 MeasureNext() 00082 { 00083 StopTime(); 00084 SelectGroup(mCurrentGroup + 1); 00085 StartTime(); 00086 } 00087 00088 void 00089 MeasureFromSub(TimeStats* sub) 00090 { 00091 mIsTiming = false; 00092 for (int i=0 ; i<sub->NrGroups() ; i++) 00093 { 00094 Group* g = sub->GetGroup(i); 00095 GetCurrentGroup()->AddMeasurement(g->mTotal); 00096 SelectGroup(mCurrentGroup + 1); 00097 } 00098 sub->Reset(); 00099 StartTime(); 00100 } 00101 00102 void 00103 MeasureLast() 00104 { 00105 StopTime(); 00106 if (mCurrentGroup != NrGroups() - 1) 00107 ILOG_ERROR("[MeasureLast] Not at last group"); 00108 } 00109 00110 void 00111 Print(std::ostream& os) 00112 { 00113 StopTime(); 00114 ComputePercentages(); 00115 os << "timestats: total = " << mGrandTotal << " (" 00116 << Timer::Format(mGrandTotal) << ") - " << NrGroups() << " groups" 00117 << std::endl; 00118 for (int i=0 ; i<NrGroups() ; i++) 00119 { 00120 Group* g = mGroups[i]; 00121 int nr = g->mMeasurements.size(); 00122 os << " " << g->mName << ": " << g->mPercentage << " % = " 00123 << g->mTotal << " (" << Timer::Format(g->mTotal) 00124 << ") (avg of " << nr << " is " << g->mTotal/nr << ")" 00125 << std::endl; 00126 } 00127 } 00128 00129 String 00130 AsString() 00131 { 00132 std::ostringstream oss; 00133 Print(oss); 00134 return oss.str(); 00135 } 00136 00137 int 00138 NrGroups() const 00139 { 00140 return mGroups.size(); 00141 } 00142 00143 Group* 00144 GetCurrentGroup() 00145 { 00146 return mGroups[mCurrentGroup]; 00147 } 00148 00149 Group* 00150 GetGroup(int number) 00151 { 00152 return mGroups[number]; 00153 } 00154 00155 const Group* 00156 SelectGroup(CString name) 00157 { 00158 if (mIsTiming) 00159 StopTime(); 00160 for (int i=0 ; i<NrGroups() ; i++) 00161 if (mGroups[i]->mName == name) 00162 return SelectGroup(i); 00163 ILOG_ERROR("[SelectGroup} group not found: " << name); 00164 return 0; 00165 } 00166 00167 const Group* 00168 SelectGroup(int number) 00169 { 00170 if (mIsTiming) 00171 StopTime(); 00172 if (number < NrGroups()) 00173 mCurrentGroup = number; 00174 else 00175 ILOG_ERROR("[SelectGroup] no group " << number); 00176 return GetCurrentGroup(); 00177 } 00178 00179 void 00180 StartTime() 00181 { 00182 mIsTiming = true; 00183 mClock.Start(); 00184 } 00185 00186 void 00187 StopTime() 00188 { 00189 if (mIsTiming) 00190 GetCurrentGroup()->AddMeasurement(mClock.Stop()); 00191 mIsTiming = false; 00192 } 00193 00194 void 00195 Reset() 00196 { 00197 if (mIsTiming) 00198 StopTime(); 00199 for (int i=0 ; i<NrGroups() ; i++) 00200 mGroups[i]->Clear(); 00201 } 00202 00203 void 00204 ComputePercentages() 00205 { 00206 mGrandTotal = 0; 00207 if (mRelative) 00208 { 00209 mGrandTotal = mGroups[0]->mTotal; 00210 } 00211 else 00212 { 00213 for (int i=0 ; i<NrGroups() ; i++) 00214 mGrandTotal += mGroups[i]->mTotal; 00215 } 00216 for (int i=0 ; i<NrGroups() ; i++) 00217 mGroups[i]->mPercentage = 100. * mGroups[i]->mTotal / mGrandTotal; 00218 } 00219 00220 protected: 00221 00222 Timer mClock; 00223 std::vector<Group*> mGroups; 00224 int mCurrentGroup; 00225 bool mIsTiming; 00226 bool mRelative; 00227 double mGrandTotal; // only valid after ComputePercentages 00228 00229 ILOG_VAR_DEC; 00230 00231 friend std::ostream& operator<< (std::ostream& os, TimeStats& stats); 00232 }; 00233 00234 ILOG_VAR_INIT(TimeStats, Impala.Util); 00235 00236 std::ostream& 00237 operator<< (std::ostream& os, TimeStats& stats) 00238 { 00239 stats.Print(os); 00240 return os; 00241 } 00242 00243 }//namespace Util 00244 }//namespace Impala 00245 00246 #endif