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;
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。