PerformanceProfiler.h
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<mutex>
#include<stdarg.h>
#include<assert.h>
#include<time.h>
#include <thread> // std::this_thread::sleep_for
#include <chrono> // std::chrono::seconds
#ifdef _WIN32
#include<windows.h>
#else
#include<pthread.h>
#endif
typedef long long LongType;
using namespace std;
////////////////////////////////////////////////////////////////////////
//单例模式(饿汉模式)
template<class T>
class EagerSingleton
{
public:
static T* GetInstance()
{
assert(_instance);
return _instance;
}
protected:
/*EagerSingleton(); // ?
EagerSingleton(const EagerSingleton& s);
EagerSingleton& operator = (const EagerSingleton& s);*/
protected:
static T* _instance;
};
template<class T>
T* EagerSingleton<T>::_instance = new T;
//////////////////////////////////////////////////////////////////////////
//配置管理
enum ConifgOptions
{
NONE = 0,
PERFORMANCE_PROFILER_EE = 1, // 开启效率剖析
PERFORMANCE_PROFILER_RS = 2, // 开启资源剖析
SAVE_TO_CONSOLE = 4, // 保存到控制台
SAVE_TO_FILE = 8, // 保存到文件
SORT_BY_CALL_COUNT = 16, // 结果按调用次数排序
SORT_BY_COST_TIME = 32, // 结果按花费时间排序
};
class ConifgManager :public EagerSingleton<ConifgManager>
{
friend class EagerSingleton<ConifgManager>;
public:
int SetOption(int flag);
int GetOption();
void AddOption(int flag);
void DelOption(int flag);
protected:
ConifgManager()
:_flag(NONE)
{
// 读取配置文件,设置选选项
}
protected:
int _flag;
};
//////////////////////////////////////////////////////////////////////////
//保存适配器
class SaveAdapter
{
public:
//基类为纯虚函数,子类重写
virtual void Save(const char* fmt, ...) = 0;
};
class ConsoleSaveAdapter :public SaveAdapter
{
public:
virtual void Save(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
};
class FileSaveAdapter :public SaveAdapter
{
public:
FileSaveAdapter(const char* filename)
{
fout = fopen(filename, "w");
assert(fout);
}
virtual void Save(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(fout, fmt, args);
va_end(args);
}
~FileSaveAdapter()
{
if (fout)
{
fclose(fout);
}
}
protected:
FileSaveAdapter(const FileSaveAdapter&);
FileSaveAdapter& operator=(const FileSaveAdapter&);
protected:
FILE* fout;
};
//////////////////////////////////////////////////////////////////////////
//性能剖析器->节点信息
static int GetThreadId()
{
#ifdef _WIN32
return GetCurrentThreadId();
#else
return thread_self();
#endif
}
struct PPNode
{
string _filename; //文件名
string _function; //函数名
size_t _line; //行号
string _desc; //附加项描述
//字符串为空得写“”而不能省略不写
PPNode(const char* filename = "", const char* function = "", size_t line = 0, const char* desc = "")
: _filename(filename)
, _function(function)
, _line(line)
, _desc(desc)
{}
//红黑树得支持operator<()
bool operator<(const PPNode& node) const;
};
//剖析段
typedef map<int, LongType> StatisticsMap;
struct PPSection
{
public:
PPSection()
{}
void Begin(int id);
void End(int id);
StatisticsMap _beginTimeMap;
StatisticsMap _costTimeMap;
StatisticsMap _callCountMap;
StatisticsMap _refCountMap; //递归引用计数
LongType _totalCostTime;
mutex _mtx;
};
class PerformanceProfiler :public EagerSingleton<PerformanceProfiler>
{
friend class EagerSingleton<PerformanceProfiler>;
typedef map<PPNode, PPSection*> PPMap;
public:
PPSection* CreateSection(const char* filename, const char* function, size_t line, const char* desc);
void OutPut();
void _OutPut(SaveAdapter& sa);
protected:
PerformanceProfiler()
{}
PerformanceProfiler(const PerformanceProfiler&);
PerformanceProfiler& operator=(const PerformanceProfiler&);
protected:
PPMap _ppMap;
};
//?
//struct Release
//{
// ~Release()
// {
// PerformanceProfiler::GetInstance()->OutPut();
// }
//};
//static Release gR;
#define PERFORMANCE_PROFILER_EE_BEGIN(sign, desc) \
PPSection* sign##section = NULL; \
int sign##flag = ConifgManager::GetInstance()->GetOption(); \
if(sign##flag & PERFORMANCE_PROFILER_EE) \
{ \
sign##section = performanceProfiler::GetInstance() \
->CreateSection(__FILE__, __FUNCTION__, __LINE__, desc); \
sign##section->Begin(GetThreadId()); \
}
#define PERFORMANCE_PROFILEER_EE_END(sign) \
if (sign##flag&PERFORMANCE_PROFILEER_EE) \
sign##section->End(GetthreadId());
#define SET_CONFIG_OPTION(flag) \
ConifgManager::GetInstance()->SetOption(flag);
PerformanceProfiler.cpp
using namespace std;
#include "PerformanceProfiler.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//配置管理
int ConifgManager::SetOption(int flag)
{
int old = _flag;
_flag = flag;
return old;
}
int ConifgManager::GetOption()
{
return _flag;
}
void ConifgManager::AddOption(int flag)
{
_flag |= flag;
}
void ConifgManager::DelOption(int flag)
{
_flag &= (~flag);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//剖析节点
inline bool PPNode::operator<(const PPNode& node) const
{
return (_line < node._line) || (_filename < node._filename) || (_function < node._function);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//剖析段
void PPSection::Begin(int id)
{
lock_guard<mutex> lock(_mtx);
//id用来分辨不同线程
if (_refCountMap[id]++ == 0)
{
_beginTimeMap[id] = clock();
}
_callCountMap[id]++;
}
void PPSection::End(int id)
{
lock_guard<mutex> lock(_mtx);
if (--_refCountMap[id] == 0)
{
LongType costTime = clock() - _beginTimeMap[id];
_costTimeMap[id] += costTime;
_totalCostTime += costTime;
}
}
PPSection* PerformanceProfiler::CreateSection(const char* filename, const char* function, size_t line, const char* desc)
{
PPNode node(filename, function, line, desc);
PPSection*& section = _ppMap[node];
if (section == NULL)
{
section = new PPSection;
}
return section;
}
void PerformanceProfiler::OutPut()
{
int flag = ConifgManager::GetInstance()->GetOption();
if (flag&SAVE_TO_CONSOLE)
{
ConsoleSaveAdapter csa;
_OutPut(csa);
}
if (flag&SAVE_TO_FILE)
{
FileSaveAdapter fsa("PerformanceProfilerReport.txt");
_OutPut(fsa);
}
}
void PerformanceProfiler::_OutPut(SaveAdapter& sa)
{
vector<PPMap::iterator> vInfos;
int num = 1;
PPMap::iterator ppIt = _ppMap.begin();
while (ppIt != _ppMap.end())
{
vInfos.push_back(ppIt);
++ppIt;
}
struct SortByCostTime
{
bool operator()(PPMap::iterator left, PPMap::iterator right)
{
return left->second->_totalCostTime > right->second->_totalCostTime;
}
};
sort(vInfos.begin(), vInfos.end(), SortByCostTime());
vector<PPMap::iterator>::iterator it = vInfos.begin();
while (it != vInfos.end())
{
const PPNode& node = (*it)->first;
PPSection* section = (*it)->second;
sa.Save("NO.%d,Desc:%s\n", num++, node._desc.c_str());
sa.Save("Filename:%s,Function:%s,Line:%u\n", node._filename.c_str(), node._function.c_str(), node._line);
LongType totalCostTime = 0;
LongType totalCallCount = 0;
int id = 0;
LongType costTime = 0;
LongType callCount = 0;
StatisticsMap::iterator timeIt = section->_costTimeMap.begin();
while(timeIt!=section->_costTimeMap.end())
{
id = timeIt->first;
costTime = timeIt->second;
callCount = section->_callCountMap[id];
totalCostTime += costTime;
totalCallCount += callCount;
sa.Save("ThreadId:%d,CostTime:%.2f,callCount:%lld\n", id, (double)costTime, totalCallCount);
++it;
}
}
}
test.cpp
#include "PerformanceProfiler.h"
//测试用例
//普通情况
///////////////////////////////////////////////////////////////////////////////////
//void Test1()
//{
// PPSection* section = PerformanceProfiler::GetInstance() \
// ->CreateSection(__FILE__, __FUNCTION__, __LINE__, "第一段代码");
//
// section->Begin();
// Sleep(5000);
// section->End();
//}
void Test2()
{
PERFORMANCE_PROFILER_EE_BEGIN(sql, "数据库");
Sleep(1000);
PERFORMANCE_PROFILER_EE_END(sql);
PERFORMANCE_PROFILER_EE_BEGIN(network, "网络");
Sleep(2000);
PERFORMANCE_PROFILER_EE_END(network);
}
//Test2调用3次
void TestN2()
{
for (int i = 3; i > 0; i--)
{
Test2();
}
}
///////////////////////////////////////////////////////////////////////////////////
//测试递归
LongType Fib(size_t n)
{
PERFORMANCE_PROFILER_EE_BEGIN(fib, "递归");
LongType ret = 0;
if (n < 2)
{
ret = n;
}
else
{
ret = Fib(n - 1) + Fib(n - 2);
}
PERFORMANCE_PROFILER_EE_END(fib);
return ret;
}
void TestN3()
{
PERFORMANCE_PROFILER_EE_BEGIN(fib, "FIB");
Fib(20);
PERFORMANCE_PROFILER_EE_END(fib);
}
//测试多线程
void ThreadRun(int count)
{
cout << this_thread::get_id() << endl;
while (count--)
{
PERFORMANCE_PROFILER_EE_BEGIN(ThreadRun, "ThreadRun");
this_thread::sleep_for(std::chrono::milliseconds(100));
PERFORMANCE_PROFILER_EE_END(ThreadRun);
}
}
void TestMhread()
{
cout << this_thread::get_id() << endl;
thread t1(ThreadRun, 15);
thread t2(ThreadRun, 10);
thread t3(ThreadRun, 5);
t1.join();
t2.join();
t3.join();
}
int main()
{
SET_CONFIG_OPTION(PERFORMANCE_PROFILER_EE | SAVE_TO_CONSOLE);
//Test2();
//TestN3();
TestMhread();
system("pause");
return 0;
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。