PerformanceProfiler.h: #include<iostream> using namespace std; #include<map> #include<windows.h> #include<time.h> #include<string> #include<assert.h> #include<stdarg.h> #include<thread> #include<mutex> #include<algorithm> #include<vector> typedef long long LongType; ////////////保存适配器抽象基类////////////// class SaveAdapter { public: //纯虚函数,强制要求派生类重写,重新实现 virtual void Save(const char* fmt, ...) = 0; }; //控制台保存适配器 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: //设置为保护类型,造成scopedPtr,防拷贝 FileSaveAdapter( const FileSaveAdapter & f); FileSaveAdapter& operator=(const FileSaveAdapter& f); private: FILE* _fout; }; /////////////单例基类/////////////////// //单例模式的是指就是全局的静态指针,这个指针只能生成一个对象 template<class T> class Singleton { public: static T * GetInstance() { if (_sInstance == NULL ) { lock_guard<mutex > lock(_mutex); if (_sInstance == NULL ) { _sInstance = new T (); } } return _sInstance; } protected: //默认构造函数 Singleton() {} //成员变量 static T * _sInstance; static mutex _mutex; }; //静态成员初始化 template<class T> T* Singleton <T>::_sInstance = NULL; template<class T> mutex Singleton <T>::_mutex; enum PP_CONFIG_OPTION { PPCO_NONE = 0, //不做剖析 PPCO_PROFILER = 2, //开启剖析 PPCO_SAVE_TO_CONSOLE = 4, //保存到控制台 PPCO_SAVE_TO_FILE = 8, //保存到文件 PPCO_SAVE_BY_CALL_COUNT = 16,//按调用次数降序保存 PPCO_SAVE_BY_COST_TIME=32, //按调用花费时间降序保存 }; /////////////配置管理//////////////// class ConfigManager :public Singleton<ConfigManager > { 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); } } /////////性能剖析节点/////////// struct PPNode { string _filename;//文件名 string _function;//函数名 int _line; //行号 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节点信息 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)//开始函数 { lock_guard<mutex > lock(_mutex); ++_callCountMap[ id]; if (_refCountMap[id ] == 0) { _beginTimeMap[ id] = clock();//计时函数 } ++_refCountMap[ id]; ++_totalCallCount; ++_totalRefCount; } void End(int id) { lock_guard<mutex > lock(_mutex); LongType refCount = --_refCountMap[id ]; --_totalRefCount; //先将总的引用计数减1 //引用计数<=0时,更新剖析段花费的时间 if (refCount <= 0) { map<int , LongType>:: 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) { //如果总的引用计数不等于0,表示剖析段不匹配 if (_totalRefCount) sa.Save("Performance Profiler Not Match!\n" ); //序列化效率统计信息 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函数时间转化为以秒为单位 sa.Save("Total CostTime:%.2f,Total Call Count:%d\n" , ( double)_totalCostTime / CLOCKS_PER_SEC , _totalCallCount); } private: //加锁 //<threadid,资源统计> //多个线程同时访问时,每个线程的开始时间,花费时间,访问次数都不相同 map<int , LongType> _beginTimeMap; map<int , LongType> _costTimeMap; map<int , LongType> _callCountMap; map<int , LongType> _refCountMap; //利用引用计数方式解决递归时的计时问题 //总的 int _beginTime;//总的开始时间 LongType _totalCostTime; //花费时间 LongType _totalCallCount;//调用次数 LongType _totalRefCount;//引用次数 //锁 mutex _mutex; }; ///////////获取当前线程id//////////////// static int GetThreadId() { #ifdef _WIN32 return ::GetCurrentThreadId(); #else return ::thread_self(); #endif } //性能剖析器 class PerformanceProfiler :public Singleton<PerformanceProfiler > { 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() { //程序结束时输出剖析结果 atexit(OutPut); time(&_beginTime); } //输出序列化信息 //为了有效使用了vector能够调用sort排序,只要自己添加Compare仿函数 void _Output(SaveAdapter & sa) { sa.Save("=====================Performance Profiler Report====================\n\n"); sa.Save("Profiler Begin Time:%s\n",ctime(&_beginTime)); unique_lock<mutex > lock(_mutex); vector<map <PPNode, PPSection*>::iterator > vInfos; //PPSection作为查询值,里面保存运行时间,运行次数,开始时间和结束时间 auto it = _ppMap.begin(); for (; it != _ppMap.end(); ++it) { vInfos.push_back(it); } //按配置条件对剖析结果进行排序输出 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<PPNode , PPSection*> _ppMap; time_t _beginTime; mutex _mutex; }; //////////atexit函数///////// struct Release { ~Release() { PerformanceProfiler::GetInstance()->OutPut(); } }; /////性能剖析阶段开始///// #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()); //设置剖析选项 #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 ) { //第一次必须进行查找 PPSection* pps = NULL ; PPNode node(filename , function, line, desc ); unique_lock<mutex > lock(_mutex); map<PPNode , PPSection*> :: 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<PPNode , PPSection*>:: iterator rhs ) { return lhs ->second->_totalCallCount > rhs->second->_totalCallCount; } bool PerformanceProfiler ::CompareByCostTime(map< PPNode, PPSection*>::iterator lhs, map<PPNode , PPSection*>:: iterator rhs ) { return lhs ->second->_totalCostTime > rhs->second->_totalCostTime; } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% test.cpp: void Run(int n) { while(n --) { PERFORMANCE_PROFILER_EE_BEGIN(ntwork, "网络传输" ); Sleep(1000); PERFORMANCE_PROFILER_EE_END(ntwork); PERFORMANCE_PROFILER_EE_BEGIN(mid, "中间逻辑" ); Sleep(500); PERFORMANCE_PROFILER_EE_END(mid); PERFORMANCE_PROFILER_EE_BEGIN(sql, "数据库" ); 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; }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。