简单的程序效率分析工具

QcFunctionProfiler.h:

#ifndef QC_FUNCTION_PROFILER_H
#define QC_FUNCTION_PROFILER_H

/*
** 这工具用于分析多程序片段运行的时间.
** 
** 用法:
** 1) 用宏PROFILER_FUNCTION_ON() 打开分析开关
** 2) 在需要分析片段的前后分别加上 PROFILER_FUNCTION_BEGIN(标示符): PROFILER_FUNCTION_END()
**    若是C++文件,可以用{}给要分析的程序片段添加作用域,在作用域前加上 PROFILER_FUNCTION(标示符)。
** 3) 用宏PROFILER_FUNCTION_OFF() 关闭分析开关,并且输出分析结果。
** 
** 限制:此工具限于Windows下的单线程程序。
*/

#ifdef _cplusplus
extern "C" {
#endif
	extern void QcFunctionBegin(int*, const char*);
	extern void QcFunctionEnd();
	extern void QcProfilerOn();
	extern void QcProfilerOff();
#ifdef _cplusplus
};
namespace Qc
{
	class FunctionProfiler
	{
		FunctionProfiler(const FunctionProfiler&);
		void operator=(const FunctionProfiler&);
	public:
		explicit FunctionProfiler(int* pId, const char* psName)
		{
			QcFunctionBegin(pId, psName);
		}
		~FunctionProfiler()
		{
			QcFunctionEnd();
		}
	};
}
#define PROFILER_FUNCTION(name)\
static int name##Id = 0;\
Qc::FunctionProfiler name##Profiler(&name##Id, #name);
#endif

#ifdef _DEBUG
#define PROFILER_FUNCTION_ON() QcProfilerOn()
#define PROFILER_FUNCTION_OFF() QcProfilerOff()
#define PROFILER_FUNCTION_BEGIN(name)\
	static int name##Id = 0;\
	QcFunctionBegin(&name##Id, #name)
#define PROFILER_FUNCTION_END() QcFunctionEnd()
#else
#define PROFILER_FUNCTION_ON()
#define PROFILER_FUNCTION_OFF()
#define PROFILER_FUNCTION_BEGIN(name)
#define PROFILER_FUNCTION_END()
#endif

#endif


QcFunctionProfiler.cpp

#include "QcFunctionProfiler.h"
#include <Windows.h>
#include <strstream>
#include <vector>
#include <string>
using namespace std;

#define PROFILER_HELPER Qc::ProfilerHelper::GetHelper()
static bool _gbProfilerOn = false;

inline static __int64 GetTicks()
{
	__int64 iRet = 0;
	return QueryPerformanceCounter((LARGE_INTEGER*)&iRet) ? iRet : 0;
}
inline static __int64 GetFrequency()
{
	__int64 iRet = 0;
	return QueryPerformanceFrequency((LARGE_INTEGER*)&iRet) ? iRet : 1000;
}

namespace Qc
{
	class ProfilerHelper
	{
	private:
		ProfilerHelper(){}
		~ProfilerHelper(){}
		struct ProfilerData
		{
			ProfilerData(int* pId, const char* psName)
				: _pId(pId)
				, _iCount(0)
				, _iTotalTime(0)
				, _iMaxTime(1)
				, _iMinTime(0x7fffffffffffffff)
				, _psName(psName)
			{}
			void Print(string& str)
			{
				static double fre = GetFrequency()/1000.0;
				ostrstream stream;
				stream << "\nThe profiler result of " << _psName << ":\n";
				stream << "Call Time: " << _iCount << "\n";
				stream << "The total time:" << _iTotalTime/fre << "(ms)\n";
				stream << "The average time:" << _iTotalTime/fre/_iCount << "(ms)\n";
				stream << "The max time:" << _iMaxTime/fre << "(ms)\n";
				stream << "The min time:" << _iMinTime/fre << "(ms)\n"<< '\0';
				str = stream.str();
				stream.freeze(false);
			} 
			int* _pId;
			int _iCount;
			__int64 _iTotalTime;
			__int64 _iMaxTime;
			__int64 _iMinTime;
			const char* _psName;
		};
		struct FrameData
		{
			__int64 _iBeginTime;
			int _iId;
		};
		typedef vector<ProfilerData> ProfilerDataList;
		typedef vector<FrameData> CallStack;

		inline ProfilerData* GetProfiler(int id)
		{
			ProfilerData* pRet = NULL;
			if (id > 0 && id <= (int)_profilerDataList.size())
				pRet = &_profilerDataList[id - 1];
			return pRet;
		}
	public:
		inline static ProfilerHelper& GetHelper()
		{
			return _gsProfilerHelper;
		}
		inline void AllocProfiler(int* pId, const char* psName)
		{
			_profilerDataList.push_back(ProfilerData(pId, psName));
			*pId = _profilerDataList.size();
		}
		inline void FramePush(int id)
		{
			FrameData data;
			data._iId = id;
			_callStack.push_back(data);
			_callStack.back()._iBeginTime = GetTicks();
		}
		inline void FramePop()
		{
			if (_callStack.size())
			{
				FrameData& frame = _callStack.back();
				__int64 callTime = GetTicks() - frame._iBeginTime;
				ProfilerData* pProfiler = GetProfiler(frame._iId);
				pProfiler->_iCount++;
				pProfiler->_iTotalTime += callTime;
				pProfiler->_iMaxTime = max(pProfiler->_iMaxTime, callTime);
				pProfiler->_iMinTime = min(pProfiler->_iMinTime, callTime);
				_callStack.pop_back();
			}
		}
		inline void Print()
		{
			string str;
			ProfilerDataList::iterator iter = _profilerDataList.begin();
			for (; iter != _profilerDataList.end(); iter++)
			{
				iter->Print(str);
				OutputDebugStringA(str.c_str());
			}
		}
		inline void Clear()
		{	
			string str;
			ProfilerDataList::iterator iter = _profilerDataList.begin();
			for (; iter != _profilerDataList.end(); iter++)
			{
				iter->_pId = 0;
			}
			_profilerDataList.clear();
			_callStack.clear();
		}
	private:
		ProfilerDataList _profilerDataList;
		CallStack _callStack;
		static ProfilerHelper _gsProfilerHelper;
	};
	ProfilerHelper ProfilerHelper::_gsProfilerHelper;
}


void QcFunctionBegin(int* pId, const char* psName)
{
	if (_gbProfilerOn)
	{
		if (*pId == 0)
		{
			PROFILER_HELPER.AllocProfiler(pId, psName);
		}
		PROFILER_HELPER.FramePush(*pId);
	}
}
void QcFunctionEnd()
{
	if (_gbProfilerOn)
	{
		PROFILER_HELPER.FramePop();
	}
}
void QcProfilerOn()
{
	if (!_gbProfilerOn)
	{
		_gbProfilerOn = true;
		PROFILER_HELPER.Clear();
	}
}
void QcProfilerOff()
{
	if (_gbProfilerOn)
	{
		_gbProfilerOn = false;
		PROFILER_HELPER.Print();
	}
}


Test.cpp

#include "QcFunctionProfiler.h"
#include <stdlib.h>
#include <stdio.h>

int main()
{
	PROFILER_FUNCTION_ON();

	int iCount = 1000 * 100;


	for (int i=0; i<iCount; i++)
	{
		PROFILER_FUNCTION_BEGIN(New);
		int* pRet = new int;
		*pRet = i;
		PROFILER_FUNCTION_END();

		PROFILER_FUNCTION_BEGIN(Malloc);
		pRet = (int*)malloc(sizeof(int));
		*pRet = i;
		PROFILER_FUNCTION_END();

	}

	PROFILER_FUNCTION_OFF();
	getchar();
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值