性能剖析器项目-创新互联

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;
	}
}

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。

新闻标题:性能剖析器项目-创新互联
当前路径:https://www.cdcxhl.com/article4/depioe.html

成都网站建设公司_创新互联,为您提供响应式网站网站内链App开发面包屑导航移动网站建设域名注册

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

商城网站建设