性能剖析器
PerformanceProfiler.h:#include<iostream>usingnamespacestd;#include<map>#include<windows.h>#include<time.h>#include<string>#include<assert.h>#include<stdarg.h>#include<thread>#include<mutex>#include<algorithm>#include<vector>typedeflonglongLongType;////////////保存适配器抽象基类//////////////classSaveAdapter{public://纯虚函数,强制要求派生类重写,重新实现virtualvoidSave(constchar*fmt,...)=0;};//控制台保存适配器classConsoleSaveAdapter:publicSaveAdapter//公有继承{virtualvoidSave(constchar*format,...){va_listargs;va_start(args,format);vfprintf(stdout,format,args);//输出重定向va_end(args);}};//文件保存适配器classFileSaveAdapter:publicSaveAdapter{public:FileSaveAdapter(constchar*filename):_fout(0){_fout=fopen(filename,"w");assert(_fout);}~FileSaveAdapter(){if(_fout){fclose(_fout);}}virtualvoidSave(constchar*format,...){if(_fout){va_listargs;va_start(args,format);vfprintf(_fout,format,args);//输出重定向到_foutva_end(args);}}protected://设置为保护类型,造成scopedPtr,防拷贝FileSaveAdapter(constFileSaveAdapter&f);FileSaveAdapter&operator=(constFileSaveAdapter&f);private:FILE*_fout;};/////////////单例基类/////////////////////单例模式的是指就是全局的静态指针,这个指针只能生成一个对象template<classT>classSingleton{public:staticT*GetInstance(){if(_sInstance==NULL){lock_guard<mutex>lock(_mutex);if(_sInstance==NULL){_sInstance=newT();}}return_sInstance;}protected://默认构造函数Singleton(){}//成员变量staticT*_sInstance;staticmutex_mutex;};//静态成员初始化template<classT>T*Singleton<T>::_sInstance=NULL;template<classT>mutexSingleton<T>::_mutex;enumPP_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,//按调用花费时间降序保存};/////////////配置管理////////////////classConfigManager:publicSingleton<ConfigManager>{public:voidSetOptions(intflag){_flag=flag;}intGetOptions(){return_flag;}ConfigManager():_flag(PPCO_PROFILER|PPCO_SAVE_TO_CONSOLE|PPCO_SAVE_TO_FILE){}private:int_flag;};///////////////获取路径中最后的文件名///////////////////staticstringGetFileName(conststring&path){charch='/';#ifdef_WIN32ch='\\';#endifsize_tpos=path.rfind(ch);//逆序查找if(pos==string::npos){returnpath;}else{returnpath.substr(pos+1);}}/////////性能剖析节点///////////structPPNode{string_filename;//文件名string_function;//函数名int_line;//行号string_desc;//描述PPNode(constchar*filename,constchar*function,intline,constchar*desc):_filename(filename),_function(function),_line(line),_desc(desc){}booloperator<(constPPNode&node)const{if(_line>node._line)returnfalse;if(_line<node._line)returntrue;if(_filename>node._filename)returnfalse;if(_filename<node._filename)returntrue;if(_function>node._function)returnfalse;if(_function<node._function)returntrue;returnfalse;}//比较相等booloperator==(constPPNode&node)const{return_function==node._function&&_line==node._line&&_filename==node._filename;}//打印PPNode节点信息voidSerialize(SaveAdapter&sa)const{sa.Save("Filename:%s,Function:%s,Line:%d\n",_filename.c_str(),_function.c_str(),_line);}};///////////////性能剖析段///////////////////////structPPSection{friendclassPerformanceProfiler;public:PPSection():_beginTime(0),_totalCostTime(0),_totalCallCount(0),_totalRefCount(0){}voidBegin(intid)//开始函数{lock_guard<mutex>lock(_mutex);++_callCountMap[id];if(_refCountMap[id]==0){_beginTimeMap[id]=clock();//计时函数}++_refCountMap[id];++_totalCallCount;++_totalRefCount;}voidEnd(intid){lock_guard<mutex>lock(_mutex);LongTyperefCount=--_refCountMap[id];--_totalRefCount;//先将总的引用计数减1//引用计数<=0时,更新剖析段花费的时间if(refCount<=0){map<int,LongType>::iteratorit=_beginTimeMap.find(id);if(it!=_beginTimeMap.end()){LongTypecostTime=clock()-it->second;if(_refCountMap[id]==0){_costTimeMap[id]+=costTime;}else{_costTimeMap[id]=costTime;}_totalCostTime+=costTime;}}}//线程打印信息voidSerialize(SaveAdapter&sa){//如果总的引用计数不等于0,表示剖析段不匹配if(_totalRefCount)sa.Save("PerformanceProfilerNotMatch!\n");//序列化效率统计信息autocostTimeIt=_costTimeMap.begin();for(;costTimeIt!=_costTimeMap.end();++costTimeIt){LongTypecallCount=_callCountMap[costTimeIt->first];sa.Save("ThreadId:%d,CostTime:%.2f,CallCount:%d\n",costTimeIt->first,(double)costTimeIt->second/CLOCKS_PER_SEC,callCount);}//CLOCKS_PER_SEC将clock函数时间转化为以秒为单位sa.Save("TotalCostTime:%.2f,TotalCallCount:%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////////////////staticintGetThreadId(){#ifdef_WIN32return::GetCurrentThreadId();#elsereturn::thread_self();#endif}//性能剖析器classPerformanceProfiler:publicSingleton<PerformanceProfiler>{public:friendclassSingleton<PerformanceProfiler>;PPSection*CreateSection(constchar*filename,constchar*function,intline,constchar*desc);staticvoidOutPut();protected:staticboolCompareByCallCount(map<PPNode,PPSection*>::iteratorlhs,map<PPNode,PPSection*>::iteratorrhs);staticboolCompareByCostTime(map<PPNode,PPSection*>::iteratorlhs,map<PPNode,PPSection*>::iteratorrhs);PerformanceProfiler(){//程序结束时输出剖析结果atexit(OutPut);time(&_beginTime);}//输出序列化信息//为了有效使用了vector能够调用sort排序,只要自己添加Compare仿函数void_Output(SaveAdapter&sa){sa.Save("=====================PerformanceProfilerReport====================\n\n");sa.Save("ProfilerBeginTime:%s\n",ctime(&_beginTime));unique_lock<mutex>lock(_mutex);vector<map<PPNode,PPSection*>::iterator>vInfos;//PPSection作为查询值,里面保存运行时间,运行次数,开始时间和结束时间autoit=_ppMap.begin();for(;it!=_ppMap.end();++it){vInfos.push_back(it);}//按配置条件对剖析结果进行排序输出intflag=ConfigManager::GetInstance()->GetOptions();if(flag&PPCO_SAVE_BY_COST_TIME)sort(vInfos.begin(),vInfos.end(),CompareByCostTime);elsesort(vInfos.begin(),vInfos.end(),CompareByCallCount);for(intindex=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函数/////////structRelease{~Release(){PerformanceProfiler::GetInstance()->OutPut();}};/////性能剖析阶段开始/////#definePERFORMANCE_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());\}#definePERFORMANCE_PROFILER_EE_END(sign)\if(sign##section)\sign##section->End(GetThreadId());//设置剖析选项#defineSET_PERFORMANCE_PROFILER_OPTIONS(flag)\ConfigManager::GetInstance()->SetOptions(flag);###########################################################################################PerformanceProfiler.cpp:#include"performanceProfiler.h"PPSection*PerformanceProfiler::CreateSection(constchar*filename,constchar*function,intline,constchar*desc){//第一次必须进行查找PPSection*pps=NULL;PPNodenode(filename,function,line,desc);unique_lock<mutex>lock(_mutex);map<PPNode,PPSection*>::iteratorit=_ppMap.find(node);if(it!=_ppMap.end()){returnit->second;}else{pps=newPPSection;_ppMap[node]=pps;}returnpps;}voidPerformanceProfiler::OutPut(){intflag=ConfigManager::GetInstance()->GetOptions();if(flag&PPCO_SAVE_TO_CONSOLE){ConsoleSaveAdaptercsa;PerformanceProfiler::GetInstance()->_Output(csa);}if(flag&PPCO_SAVE_TO_FILE){FileSaveAdapterfsa("PerformanceProfilerReport.txt");PerformanceProfiler::GetInstance()->_Output(fsa);}}boolPerformanceProfiler::CompareByCallCount(map<PPNode,PPSection*>::iteratorlhs,map<PPNode,PPSection*>::iteratorrhs){returnlhs->second->_totalCallCount>rhs->second->_totalCallCount;}boolPerformanceProfiler::CompareByCostTime(map<PPNode,PPSection*>::iteratorlhs,map<PPNode,PPSection*>::iteratorrhs){returnlhs->second->_totalCostTime>rhs->second->_totalCostTime;}%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%test.cpp:voidRun(intn){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);}}voidTest(){threadt1(Run,1);threadt2(Run,2);threadt3(Run,3);t1.join();t2.join();t3.join();}intmain(){Test();PerformanceProfiler::GetInstance()->OutPut();system("pause");return0;}
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。