lugre_profile.cpp

Go to the documentation of this file.
00001 #include "lugre_prefix.h"
00002 #include "lugre_profile.h"
00003 #include <vector>
00004 #include <map>
00005 #include <set>
00006 
00007 #include "lugre_shell.h"    // only needed for timer
00008 
00009 namespace Lugre {
00010 
00011 std::vector<void*> gCallStack;
00012 std::vector<void*> gHistory;
00013 bool gDoInit = true;
00014 
00015 #define GET_TIMESTAMP ((unsigned int)(cShell::GetTicks()))
00016 
00017 //#define PROFILE_CALLCOUNT // counts how often functions are called
00018 // #define PROFILE_CALLTIME // keeps a history of function calls, to do call-count and call-time profiling
00019 // #define KEEP_HISTORY // keeps a history of function calls, to do call-count and call-time profiling
00020 
00021 #ifdef PROFILE_CALLTIME
00022     #define CALLSTACK_ELEM_SIZE 4
00023 #else
00024     #define CALLSTACK_ELEM_SIZE 3
00025 #endif
00026 
00027 //#define MEGALOGPATH "megalog.txt"   // logs EVERY functioncall start and end to a logfile (sloooow, biiiig)
00028 
00029 #ifdef PROFILE_CALLCOUNT
00030     class cCallCountProfileIndex { public:
00031         const char*     a;
00032         const int       b;
00033         const char*     c;
00034         cCallCountProfileIndex (const char* a,const int b,const char* c) : a(a), b(b), c(c) {} 
00035     };
00036     struct cCallCountProfileMapCmpSimple {
00037       inline bool operator() (const cCallCountProfileIndex x, const cCallCountProfileIndex y) const {
00038         // don't use lexico compare here, that would be far too slow
00039         return      (x.a < y.a) ||
00040                     (x.a == y.a && x.b < y.b) ||
00041                     (x.a == y.a && x.b == y.b && x.c < y.c);
00042       }
00043     };
00044     struct cCallCountProfileSetCmp {
00045       inline bool operator() (const std::pair<cCallCountProfileIndex,int>& x,const  std::pair<cCallCountProfileIndex,int>& y) const {
00046         return x.second > y.second;
00047       }
00048     };
00049     std::map<cCallCountProfileIndex,int,cCallCountProfileMapCmpSimple> gmCallCountProfileMap;
00050     typedef std::map<cCallCountProfileIndex,int,cCallCountProfileMapCmpSimple>::iterator tCallCountProfileMapItor;
00051 #endif
00052 
00053 #ifdef ENABLE_PROFILING
00054 cProfiler::cProfiler(const char* sFile,const int iLine,const char* sFunc) {
00055     if (!Lugre_IsMainThread()) return;
00056     if (gDoInit) {
00057         gCallStack.reserve(1024*4*sizeof(void*));
00058         #ifdef KEEP_HISTORY 
00059             gHistory.reserve(1024*1024*4*sizeof(void*));
00060         #endif
00061         gDoInit = false;
00062     }
00063     gCallStack.push_back((void*)sFile);
00064     gCallStack.push_back(reinterpret_cast<void*>((long)iLine));
00065     gCallStack.push_back((void*)sFunc);
00066     #ifdef PROFILE_CALLTIME
00067         gCallStack.push_back((void*)GET_TIMESTAMP);
00068     #endif
00069     #ifdef MEGALOGPATH
00070         FILE* fp = fopen(MEGALOGPATH,"a");
00071         int i = gCallStack.size()-CALLSTACK_ELEM_SIZE;
00072         for (int j=0;j<i/CALLSTACK_ELEM_SIZE;++j) fprintf(fp," ");
00073         fprintf(fp,"START %s:%ld:%s\n", (const char*) gCallStack[i],
00074                                         static_cast<long>(gCallStack[i+1]),
00075                                         (const char*) gCallStack[i+2]);
00076         fclose(fp);
00077     #endif
00078     #ifdef PROFILE_CALLCOUNT
00079         ++gmCallCountProfileMap[cCallCountProfileIndex(sFile,iLine,sFunc)];
00080     #endif
00081 }
00082 
00083 cProfiler::~cProfiler() {
00084     if (!Lugre_IsMainThread()) return;
00085     #ifdef MEGALOGPATH
00086         FILE* fp = fopen(MEGALOGPATH,"a");
00087         int i = gCallStack.size()-CALLSTACK_ELEM_SIZE;
00088         for (int j=0;j<i/CALLSTACK_ELEM_SIZE;++j) fprintf(fp," ");
00089         fprintf(fp,"END   %s:%ld:%s\n", (const char*) gCallStack[i],
00090                                         static_cast<long>(gCallStack[i+1]),
00091                                         (const char*) gCallStack[i+2]);
00092         fclose(fp);
00093     #endif
00094     #ifdef KEEP_HISTORY 
00095         gHistory.push_back(gCallStack[0+gCallStack.size()-CALLSTACK_ELEM_SIZE]);
00096         gHistory.push_back(gCallStack[1+gCallStack.size()-CALLSTACK_ELEM_SIZE]);
00097         gHistory.push_back(gCallStack[2+gCallStack.size()-CALLSTACK_ELEM_SIZE]);
00098         #ifdef PROFILE_CALLTIME
00099             gHistory.push_back(GET_TIMESTAMP - gCallStack.back());
00100         #endif
00101     #endif
00102     gCallStack.pop_back();
00103     gCallStack.pop_back();
00104     gCallStack.pop_back();
00105     #ifdef PROFILE_CALLTIME
00106         gCallStack.pop_back();
00107     #endif
00108 }
00109 
00110 void        cProfiler::PrintStackTrace  () {
00111     if (!Lugre_IsMainThread()) { printf("cProfiler::PrintStackTrace() called from non-main-thread!\n"); return; }
00112     for (int i=0;i<gCallStack.size();i+=CALLSTACK_ELEM_SIZE) {
00113         for (int j=0;j<i/CALLSTACK_ELEM_SIZE;++j) printf(" ");
00114         printf("%s:%ld:%s\n",   (const char*) gCallStack[i],
00115                                 reinterpret_cast<long>(gCallStack[i+1]),
00116                                 (const char*) gCallStack[i+2]);
00117     }
00118 }
00119 
00120 void        cProfiler::PrintStackTrace  (const char *filename) {
00121     FILE *f = fopen(filename,"a");
00122     if(f){
00123         if (!Lugre_IsMainThread()) {
00124             fprintf(f,"cProfiler::PrintStackTrace(filename) called from non-main-thread!\n");
00125         } else {
00126             for (int i=0;i<gCallStack.size();i+=CALLSTACK_ELEM_SIZE) {
00127                 for (int j=0;j<i/CALLSTACK_ELEM_SIZE;++j) fprintf(f," ");
00128                 fprintf(f,"%s:%ld:%s\n",(const char*) gCallStack[i],
00129                                         reinterpret_cast<long>(gCallStack[i+1]),
00130                                         (const char*) gCallStack[i+2]);
00131             }
00132         }
00133         fclose(f);
00134     }
00135 }
00136 
00137 
00138 #endif
00139 
00140 void    ProfileDumpCallCount    () {
00141     #ifdef PROFILE_CALLCOUNT
00142     if (!Lugre_IsMainThread()) return;
00143     std::multiset<std::pair<cCallCountProfileIndex,int>,cCallCountProfileSetCmp> myCallCountProfileSet;
00144     typedef std::multiset<std::pair<cCallCountProfileIndex,int>,cCallCountProfileSetCmp>::iterator tCallCountProfileSetItor;
00145     { for (tCallCountProfileMapItor itor=gmCallCountProfileMap.begin();itor != gmCallCountProfileMap.end();++itor)
00146         myCallCountProfileSet.insert(std::make_pair((*itor).first,(*itor).second)); 
00147     }
00148     
00149     int i=0;
00150     for (tCallCountProfileSetItor itor=myCallCountProfileSet.begin();itor != myCallCountProfileSet.end();++itor) {
00151         //if (++i > 10) break;
00152         const cCallCountProfileIndex& myIdx = (*itor).first;
00153         printf("CallCount %16d %s:%d %s()\n",(*itor).second,myIdx.a,myIdx.b,myIdx.c);
00154     }
00155     #endif
00156 }
00157 
00158 
00159 };

Generated on Wed May 23 06:00:15 2012 for cpp by  doxygen 1.5.6