PerformanceProfiler.h

為穆棱等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及穆棱網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都做網(wǎng)站、網(wǎng)站設(shè)計、穆棱網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
#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, // 結(jié)果按調(diào)用次數(shù)排序
SORT_BY_COST_TIME = 32, // 結(jié)果按花費時間排序
};
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)
{
// 讀取配置文件,設(shè)置選選項
}
protected:
int _flag;
};
//////////////////////////////////////////////////////////////////////////
//保存適配器
class SaveAdapter
{
public:
//基類為純虛函數(shù),子類重寫
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;
};
//////////////////////////////////////////////////////////////////////////
//性能剖析器->節(jié)點信息
static int GetThreadId()
{
#ifdef _WIN32
return GetCurrentThreadId();
#else
return thread_self();
#endif
}
struct PPNode
{
string _filename; //文件名
string _function; //函數(shù)名
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; //遞歸引用計數(shù)
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);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//剖析節(jié)點
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, "數(shù)據(jù)庫");
Sleep(1000);
PERFORMANCE_PROFILER_EE_END(sql);
PERFORMANCE_PROFILER_EE_BEGIN(network, "網(wǎng)絡(luò)");
Sleep(2000);
PERFORMANCE_PROFILER_EE_END(network);
}
//Test2調(diào)用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;
}
網(wǎng)站題目:PerformanceProfiler
轉(zhuǎn)載來于:http://chinadenli.net/article14/ghodge.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、微信公眾號、虛擬主機、網(wǎng)站收錄、靜態(tài)網(wǎng)站、微信小程序
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)