PerformanceProfiler.h: #include using namespace std; #include #include #include #include #include #include #include #include #include #include typedef long long LongType; ////////////保存適配器抽象基類////////////// class SaveAdapter { public: //純虛函數(shù),強(qiáng)制要求派生類重寫,重新實(shí)現(xiàn) virtual void Save(const char* fmt, ...) = 0; }; //控制臺(tái)保存適配器 class ConsoleSaveAdapter :public SaveAdapter//公有繼承 { virtual void Save(const char* format , ...) { va_list args; va_start(args, format); vfprintf( stdout, format , args);//輸出重定向 va_end(args); } }; //文件保存適配器 class FileSaveAdapter :public SaveAdapter { public: FileSaveAdapter( const char * filename) :_fout(0) { _fout = fopen( filename, "w" ); assert(_fout); } ~FileSaveAdapter() { if (_fout) { fclose(_fout); } } virtual void Save(const char* format , ...) { if (_fout) { va_list args; va_start(args, format); vfprintf(_fout, format, args);//輸出重定向到_fout va_end(args); } } protected: //設(shè)置為保護(hù)類型,造成scopedPtr,防拷貝 FileSaveAdapter( const FileSaveAdapter & f); FileSaveAdapter& operator=(const FileSaveAdapter& f); private: FILE* _fout; }; /////////////單例基類/////////////////// //單例模式的是指就是全局的靜態(tài)指針,這個(gè)指針只能生成一個(gè)對(duì)象 template class Singleton { public: static T * GetInstance() { if (_sInstance == NULL ) { lock_guard lock(_mutex); if (_sInstance == NULL ) { _sInstance = new T (); } } return _sInstance; } protected: //默認(rèn)構(gòu)造函數(shù) Singleton() {} //成員變量 static T * _sInstance; static mutex _mutex; }; //靜態(tài)成員初始化 template T* Singleton ::_sInstance = NULL; template mutex Singleton ::_mutex; enum PP_CONFIG_OPTION { PPCO_NONE = 0, //不做剖析 PPCO_PROFILER = 2, //開(kāi)啟剖析 PPCO_SAVE_TO_CONSOLE = 4, //保存到控制臺(tái) PPCO_SAVE_TO_FILE = 8, //保存到文件 PPCO_SAVE_BY_CALL_COUNT = 16,//按調(diào)用次數(shù)降序保存 PPCO_SAVE_BY_COST_TIME=32, //按調(diào)用花費(fèi)時(shí)間降序保存 }; /////////////配置管理//////////////// class ConfigManager :public Singleton { public: void SetOptions(int flag) { _flag = flag; } int GetOptions() { return _flag; } ConfigManager() :_flag( PPCO_PROFILER | PPCO_SAVE_TO_CONSOLE | PPCO_SAVE_TO_FILE) {} private: int _flag; }; ///////////////獲取路徑中最后的文件名/////////////////// static string GetFileName(const string& path ) { char ch = '/' ; #ifdef _WIN32 ch = '\\'; #endif size_t pos = path .rfind(ch);//逆序查找 if (pos == string ::npos) { return path ; } else { return path .substr(pos + 1); } } /////////性能剖析節(jié)點(diǎn)/////////// struct PPNode { string _filename;//文件名 string _function;//函數(shù)名 int _line; //行號(hào) string _desc; //描述 PPNode( const char * filename, const char * function, int line , const char * desc) :_filename( filename) , _function( function) , _line( line) , _desc( desc) {} bool operator<(const PPNode& node)const { if (_line > node ._line) return false ; if (_line < node ._line) return true ; if (_filename > node ._filename) return false ; if (_filename < node ._filename) return true ; if (_function > node ._function) return false ; if (_function < node ._function) return true ; return false ; } //比較相等 bool operator==(const PPNode& node)const { return _function == node ._function &&_line == node._line &&_filename == node._filename; } //打印PPNode節(jié)點(diǎn)信息 void Serialize(SaveAdapter & sa)const { sa.Save("Filename:%s,Function:%s,Line:%d\n" , _filename.c_str(), _function.c_str(), _line); } }; ///////////////性能剖析段/////////////////////// struct PPSection { friend class PerformanceProfiler; public: PPSection() :_beginTime(0) , _totalCostTime(0) , _totalCallCount(0) , _totalRefCount(0) {} void Begin(int id)//開(kāi)始函數(shù) { lock_guard lock(_mutex); ++_callCountMap[ id]; if (_refCountMap[id ] == 0) { _beginTimeMap[ id] = clock();//計(jì)時(shí)函數(shù) } ++_refCountMap[ id]; ++_totalCallCount; ++_totalRefCount; } void End(int id) { lock_guard lock(_mutex); LongType refCount = --_refCountMap[id ]; --_totalRefCount; //先將總的引用計(jì)數(shù)減1 //引用計(jì)數(shù)<=0時(shí),更新剖析段花費(fèi)的時(shí)間 if (refCount <= 0) { map:: iterator it = _beginTimeMap.find(id ); if (it != _beginTimeMap.end()) { LongType costTime = clock() - it->second; if (_refCountMap[id ] == 0) { _costTimeMap[ id] += costTime; } else { _costTimeMap[ id] = costTime; } _totalCostTime += costTime; } } } //線程打印信息 void Serialize(SaveAdapter & sa) { //如果總的引用計(jì)數(shù)不等于0,表示剖析段不匹配 if (_totalRefCount) sa.Save("Performance Profiler Not Match!\n" ); //序列化效率統(tǒng)計(jì)信息 auto costTimeIt = _costTimeMap.begin(); for (; costTimeIt != _costTimeMap.end(); ++costTimeIt) { LongType callCount = _callCountMap[costTimeIt->first]; sa.Save("Thread Id:%d,Cost Time:%.2f,Call Count:%d\n", costTimeIt->first, (double)costTimeIt->second / CLOCKS_PER_SEC , callCount); } //CLOCKS_PER_SEC將clock函數(shù)時(shí)間轉(zhuǎn)化為以秒為單位 sa.Save("Total CostTime:%.2f,Total Call Count:%d\n" , ( double)_totalCostTime / CLOCKS_PER_SEC , _totalCallCount); } private: //加鎖 // //多個(gè)線程同時(shí)訪問(wèn)時(shí),每個(gè)線程的開(kāi)始時(shí)間,花費(fèi)時(shí)間,訪問(wèn)次數(shù)都不相同 map _beginTimeMap; map _costTimeMap; map _callCountMap; map _refCountMap; //利用引用計(jì)數(shù)方式解決遞歸時(shí)的計(jì)時(shí)問(wèn)題 //總的 int _beginTime;//總的開(kāi)始時(shí)間 LongType _totalCostTime; //花費(fèi)時(shí)間 LongType _totalCallCount;//調(diào)用次數(shù) LongType _totalRefCount;//引用次數(shù) //鎖 mutex _mutex; }; ///////////獲取當(dāng)前線程id//////////////// static int GetThreadId() { #ifdef _WIN32 return ::GetCurrentThreadId(); #else return ::thread_self(); #endif } //性能剖析器 class PerformanceProfiler :public Singleton { public: friend class Singleton< PerformanceProfiler>; PPSection* CreateSection(const char* filename, const char * function, int line, const char* desc); static void OutPut(); protected: static bool CompareByCallCount(map< PPNode, PPSection*>::iterator lhs, map< PPNode, PPSection *>::iterator rhs); static bool CompareByCostTime(map< PPNode, PPSection*>::iterator lhs, map< PPNode, PPSection *>::iterator rhs); PerformanceProfiler() { //程序結(jié)束時(shí)輸出剖析結(jié)果 atexit(OutPut); time(&_beginTime); } //輸出序列化信息 //為了有效使用了vector能夠調(diào)用sort排序,只要自己添加Compare仿函數(shù) void _Output(SaveAdapter & sa) { sa.Save("=====================Performance Profiler Report====================\n\n"); sa.Save("Profiler Begin Time:%s\n",ctime(&_beginTime)); unique_lock lock(_mutex); vector::iterator > vInfos; //PPSection作為查詢值,里面保存運(yùn)行時(shí)間,運(yùn)行次數(shù),開(kāi)始時(shí)間和結(jié)束時(shí)間 auto it = _ppMap.begin(); for (; it != _ppMap.end(); ++it) { vInfos.push_back(it); } //按配置條件對(duì)剖析結(jié)果進(jìn)行排序輸出 int flag = ConfigManager ::GetInstance()->GetOptions(); if (flag&PPCO_SAVE_BY_COST_TIME ) sort(vInfos.begin(), vInfos.end(), CompareByCostTime); else sort(vInfos.begin(), vInfos.end(), CompareByCallCount); for (int index = 0; index < vInfos.size(); ++index) { sa.Save("NO%d. Delciption:%s\n" , index + 1, vInfos[index]->first._desc.c_str()); vInfos[index]->first.Serialize( sa); vInfos[index]->second->Serialize( sa); sa.Save("\n" ); } sa.Save("================================end==============================\n\n" ); } private: map _ppMap; time_t _beginTime; mutex _mutex; }; //////////atexit函數(shù)///////// struct Release { ~Release() { PerformanceProfiler::GetInstance()->OutPut(); } }; /////性能剖析階段開(kāi)始///// #define PERFORMANCE_PROFILER_EE_BEGIN (sign,desc) \ PPSection* sign##section = NULL ; \ if (ConfigManager::GetInstance()->GetOptions()&PPCO_PROFILER)\ {\ sign##section = PerformanceProfiler ::GetInstance()->CreateSection(__FILE__, __FUNCTION__, __LINE__ , desc); \ sign##section->Begin(GetThreadId()); \ } #define PERFORMANCE_PROFILER_EE_END (sign) \ if (sign##section)\ sign##section->End(GetThreadId()); //設(shè)置剖析選項(xiàng) #define SET_PERFORMANCE_PROFILER_OPTIONS (flag)\ ConfigManager::GetInstance()->SetOptions(flag); ########################################################################################### PerformanceProfiler.cpp: #include"performanceProfiler.h" PPSection* PerformanceProfiler ::CreateSection(const char* filename, const char* function, int line , const char* desc ) { //第一次必須進(jìn)行查找 PPSection* pps = NULL ; PPNode node(filename , function, line, desc ); unique_lock lock(_mutex); map :: iterator it = _ppMap.find(node); if (it != _ppMap.end()) { return it->second; } else { pps = new PPSection ; _ppMap[node] = pps; } return pps; } void PerformanceProfiler ::OutPut() { int flag = ConfigManager ::GetInstance()->GetOptions(); if (flag&PPCO_SAVE_TO_CONSOLE ) { ConsoleSaveAdapter csa; PerformanceProfiler::GetInstance()->_Output(csa); } if (flag&PPCO_SAVE_TO_FILE ) { FileSaveAdapter fsa("PerformanceProfilerReport.txt" ); PerformanceProfiler::GetInstance()->_Output(fsa); } } bool PerformanceProfiler ::CompareByCallCount(map< PPNode, PPSection*>::iterator lhs, map:: iterator rhs ) { return lhs ->second->_totalCallCount > rhs->second->_totalCallCount; } bool PerformanceProfiler ::CompareByCostTime(map< PPNode, PPSection*>::iterator lhs, map:: iterator rhs ) { return lhs ->second->_totalCostTime > rhs->second->_totalCostTime; } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% test.cpp: void Run(int n) { while(n --) { PERFORMANCE_PROFILER_EE_BEGIN(ntwork, "網(wǎng)絡(luò)傳輸" ); Sleep(1000); PERFORMANCE_PROFILER_EE_END(ntwork); PERFORMANCE_PROFILER_EE_BEGIN(mid, "中間邏輯" ); Sleep(500); PERFORMANCE_PROFILER_EE_END(mid); PERFORMANCE_PROFILER_EE_BEGIN(sql, "數(shù)據(jù)庫(kù)" ); Sleep(500); PERFORMANCE_PROFILER_EE_END(sql); } } void Test() { thread t1(Run, 1); thread t2(Run, 2); thread t3(Run, 3); t1.join(); t2.join(); t3.join(); } int main() { Test(); PerformanceProfiler::GetInstance()->OutPut(); system( "pause"); return 0; }
全國(guó)免費(fèi)咨詢:
業(yè)務(wù)咨詢:028-86922220 / 13518219792
節(jié)假值班:18980820575 / 13518219792
聯(lián)系地址:成都市太升南路288號(hào)錦天國(guó)際A幢1002號(hào)
在線咨詢
微信咨詢
電話咨詢
028-86922220(工作日)
18980820575(7×24)
提交需求
返回頂部