温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

性能剖析器项目

发布时间:2020-06-15 23:24:56 来源:网络 阅读:464 作者:zgw285763054 栏目:编程语言

PerformanceProfiler.h

#pragma once #include <iostream> #include <string> #include <map> #include <algorithm> #include <stdarg.h> #include <time.h> #include <assert.h> //C++ 11 #include <unordered_map> #include <thread> #include <mutex> #ifdef _WIN32	#include <windows.h> #else	#include <pthread.h> #endif using namespace std; //////////////////////////////////////////////////////// typedef long long LongType; //单例的基类——饿汉模式 template<class T> class Singleton { public:	static T* GetInstance()	{	assert(_sInstance);	return _sInstance;	} protected:	static T* _sInstance; }; template<class T> T* Singleton::_sInstance = new T; //////////////////////////////////////////////////// class SaveAdapter { public:	virtual void Save(const char* format, ...) = 0; }; class ConsoleSaveAdapter :public SaveAdapter { public:	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 = fopen(filename, "w");	assert(_fout);	}	~FileSaveAdapter()	{	if (_fout)	fclose(_fout);	} protected:	//防拷贝	FileSaveAdapter(FileSaveAdapter&);	FileSaveAdapter& operator=(FileSaveAdpter&); protected:	FILE* _fout; }; class SqlSaveAdapter : public SaveAdapter {}; //配置管理 enum ConfigOptions {	NONE = 0,	//不作剖析	PERFORMANCE_PROFILER = 1,	//开启剖析	SAVE_TO_CONSOLE = 2,	//保存到控制台	SAVE_TO_FILE = 4,	//保存到文件	SORT_BY_COSTTIME = 8,	//按调用次数排序	SORT_BY_CALLCOUNT = 16,	//按花费时间排序 }; class ConfigManager : public Singleton<ConfigManager> { public:	void SetOptions(int options)	{	_options = options;	}	void AddOption(int option)	{	_options |= option;	}	void DelOption(int option)	{	_options &= (~option);	}	int GetOptions()	{	return _options;	} protected:	friend class Singleton<ConfigManager>;	ConfigManager()	:_options(NONE)	{}	ConfigManager(const ConfigManager&);	ConfigManager& operator=(const ConfigManager); protected:	int _options }; //Performance Profiler struct PPNode {	string _filename;	string _function;	size_t _line;	string _desc; //附加描述信息	PPNode(const char* filename, const char* function,\	size_t line, const char* desc)	:_filename(filename)	,_function(function)	,_line(line)	,_desc(desc)	{}	bool operator==(const PPNode& node) const	{	if (_line == node._line &&\	_function == node._function &&\	_filename == node._filename)	return true;	else	return false;	} }; struct PPSection {	PPSection()	:_totalCostTime(0)	,_totalCallCount(0)	,_totalRefCount(0)	{}	void Begin(int id);	void End(int id);	map<int, LongType> _beginTimeMap;	map<int, LongType> _costTimeMap;	map<int, LongType> _callCountMap;	map<int, LongType> _refCountMap;	LongType _totalBeginTime; //开始时间	LongType _totalCostTime;  //花费时间	LongType _totalCallCount; //调用次数	LongType _totalRefCount;  //引用计数,解决递归问题	mutex _mtx; }; //PPNode计算哈希值的仿函数 struct PPNodeHash {	static size_t BKDRHash(const char * str)	{	unsigned int seed = 131; // 31 131 1313 13131 131313	unsigned int hash = 0;	while (*str)	{	hash = hash * seed + (*str++);	}	return (hash & 0x7FFFFFFF);	}	size_t operator()(const PPNode& node) const	{	static string hash;	hash = node._desc;	hash += node._function;	return BKDRHash(hash.c_str());	} }; class PerformanceProfiler : public Singleton<PerformanceProfiler> {	typedef unordered_map<PPNode, PPSection*, PPNodeHash> PP_MAP; public:	PPSection* CreateSection(const char* filename, const char* function, \	size_t line, const char* desc);	void OutPut(); protected:	void _OutPut(SaveAdapter& sa);	friend class Singleton<PerformanceProfiler>;	PerformanceProfiler(){}	PerformanceProfiler(const PerformanceProfiler&);	PerformanceProfiler& operator=(const PerformanceProfiler&); protected:	//map<PPNode, PPSection*> _ppMap; //统计资源信息的容器	PP_MAP _ppMap;	mutex _mtx; }; struct Report {	~Report()	{	PerformanceProfiler::GetInstance()->OutPut();	} }; static int GetTheadId() { #ifdef _WIN32	return GetCurrentThreadId(); #else	return thread_self(); #endif // _WIN32 } //剖析单线程场景 #define PERFORMANCE_PROFILER_EE_ST_BEGIN(sign, desc) \	PPSection* ps##sign = NULL;	\	if (ConfigManager::GetInstance()->GetOptions() & PERFORMANCE_PROFILER)	\	{	\	ps##sign = PerformanceProfiler::GetInstance()->CreateSection(__FILE__, __FUNCTION__, __LINE__, desc);\	ps##sign->Begin(-1);	\	}	\ #define PERFORMANCE_PROFILER_ST_END(sign) \	if (ps##sign)	\	ps##sign->End(-1);	\ //剖析多线程场景 #define PERFORMANCE_PROFILER_EE_MT_BEGIN(sign, desc) \	PPSection* ps##sign = NULL;	\	if (ConfigManager::GetInstance()->GetOptions() & PERFORMANCE_PROFILER)	\	{	\	ps##sign = PerformanceProfiler::GetInstance()->CreateSection(__FILE__, __FUNCTION__, __LINE__, desc);\	ps##sign->Begin(GetTheadId());	\	}	\ #define PERFORMANCE_PROFILER_ST_END(sign) \	if (ps##sign)	\	\	ps##sign->End(GetTheadId()); #define SET_CONFIG_OPTIONS(option)	\	ConfigManager::GetInstance()->SetOptions(option);

PerformanceProfiler.cpp

#include "PerformanceProfiler.h" void PPSection::Begin(int id) {	if (id != -1) //多线程	{	lock_guard<mutex> lock(_mtx);	//统计线程总的花费时间和调用次数	if (_refCountMap[id]++ == 0)	_beginTimeMap[id] = clock();	}	else //单线程	{	if (_totalRefCount++ == 0)	_totalBeginTime = clock();	} } void PPSection::End(int id) {	if (id != -1) //多线程	{	lock_guard<mutex> lock(_mtx);	if (--_refCountMap[id] == 0)	_costTimeMap[id] += clock() - _beginTimeMap[id];	++_callCountMap[id];	}	else //单线程	{	if (--_totalRefCount == 0)	_totalCostTime += clock() - _totalBeginTime;	++_totalCallCount;	} } PPSection* PerformanceProfiler::CreateSection(const char* filename, const char* function,	size_t line, const char* desc) {	PPNode node(filename, function, line, desc);	PPSection* section = NULL;	//RAII	lock_guard<mutex> lock(_mtx);	PP_MAP::iterator it = _ppMap.find(node);	if (it != _ppMap.end())	{	section = it->second;	}	else	{	section = new PPSection;	_ppMap.insert(pair<PPNode, PPSection*>(node, section));	}	return section; } void PerformanceProfiler::OutPut() {	int options = ConfigManager::GetInstance()->GetOptions();	if (options & SAVE_TO_CONSOLE)	{	ConsoleSaveAdapter csa;	_OutPut(csa);	}	if (options & SAVE_TO_FILE)	{	FileSaveAdapter fsa("PerformanceProfilerReport.txt");	_OutPut(fsa);	} } void PerformanceProfiler::_OutPut(SaveAdapter& sa) {	vector<PP_MAP::iterator> vInfos;	PP_MAP::iterator ppIt = _ppMap.begin();	while (ppIt != _ppMap.end())	{	PPSection* section = ppIt->second;	map<int, LongType>::iterator timeIt;	timeIt = section->_costTimeMap.begin();	while (timeIt != section->_costTimeMap.end())	{	section->_totalCostTime += timeIt->second;	section->_totalCallCount += section->_callCountMap[timeIt->first];	++timeIt;	}	vInfos.push_back(ppIt);	++ppIt;	}	struct SortByCostTime	{	bool operator()(PP_MAP::iterator l, PP_MAP::iterator r) const	{	return (l->second->_totalCostTime) > (r->second->_totalCostTime);	}	};	//按花费时间排序	sort(vInfos.begin(), vInfos.end(), SortByCostTime());	int num = 1;	for (size_t i = 0; i < vInfos.size(); ++i)	{	ppIt = vInfos[i];	const PPNode& node = ppIt->first;	PPSection* section = ppIt->second;	//node信息	sa.Save("No.%d, Desc:%s\n", num++, node._desc.c_str());	sa.Save("Filename:%s, Line:%d, Function:%s\n",	node._filename.c_str(),	node._line,	node._function.c_str());	//section信息	map<int, LongType>::iterator timeIt;	timeIt = section->_costTimeMap.begin();	while (timeIt != section->_costTimeMap.end())	{	int id = timeIt->first;	sa.Save("Thread:%d, CostTime:%.2f s, CallCount:%lld\n",	id,	(double)timeIt->second / 1000,	section->_callCountMap[id]);	section->_totalCostTime += timeIt->second;	section->_totalCallCount += section->_callCountMap[id];	++timeIt;	}	sa.Save("TotalCostTime:%.2f s, TotalCallCount:%lld, AverCostTime:%lld ms\n\n",	(double)section->_totalCostTime / 1000,	section->_totalCallCount,	section->_totalCostTime / section->_totalCallCount);	++ppIt;	} }



向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++
AI