日期:2014-05-17  浏览次数:20955 次

性能测试——(2)基于windows下的测试宏
#ifndef STAT_H
#define STAT_H
#include<map>
#include<string>
using namespace std;

/***
wx,取消原有用宏方式,但测试函数的开销可能会增加测试的精度
**/
struct st_stat{
public:
	st_stat():call_count(0),time(0){}
	LARGE_INTEGER start;
	LARGE_INTEGER end;
	int call_count;
	__int64 time;
};
/**测试函数性能或者代码块的
*/
class Runnable
{
public:
	explicit Runnable(const std::string& name): _name(name) {}  
	~Runnable() {}

	const std::string& name() const { return _name; }    

	inline void begin() ;
	inline void end() ;
	void diff_time(LONGLONG diff)
	{
		stat.time -=  (stat.end.QuadPart-diff);
	}
	int getCallCount(){return stat.call_count;}
	__int64 getCallTime(){return stat.time;}
	st_stat stat;
private:
	std::string _name;

};


class test_suite
{
public:
	static test_suite& get_instance()
	{
		static test_suite me;
		return me;
	}
~test_suite(){if(fp) fclose(fp);fp=NULL;
}

	void setWorkingDir(const std::string& val) { _working_dir = val; }
	const std::string& getWorkingDir() const { return _working_dir; }

	void setTestFilter(const std::string& val) { _test_filter = val; }
	const std::string& getTestFilter() const { return _test_filter; }
	void addTest(Runnable* test) { test_vec.insert(pair<string,Runnable*>(test->name(),test)); }
	void func_begin(const std::string &name);
	void func_end(const std::string &name);

	void init(const std::string &dir);
	void finish();
private:
	test_suite():fp(NULL),_working_dir(),_test_filter(){}

	void printHeading();
	void printFooter();
	void printError(const std::string&msg);

	std::string _working_dir;
	std::string _test_filter;
	typedef std::map<std::string,Runnable*> MAP;
	typedef MAP::iterator IT;
	typedef MAP::const_iterator const_it;
	 MAP test_vec;//所有需要测试的函数列表
	 
	std::vector<Runnable*> none_init_vec;//没有初始化的,需要new对象,因此最后需要释放
	FILE *fp;
};

void call_stat_begin(st_stat*pstat);
void call_stat_end(st_stat*pstat);

#if defined ST_TEST_PERFORMANCE
#define STAT_TEST_INIT(name) \
struct st_##name##_test: Runnable { \
	st_##name##_test(): Runnable(#name) { \
	test_suite::get_instance().addTest(this); \
	} \
} name##_test_instance

#define STAT_TEST_BEGIN(name) \
	test_suite::get_instance().func_begin(#name)

#define STAT_TEST_END(name) \
	test_suite::get_instance().func_end(#name)


#define STAT_GLOBAL_INIT(fileDir) test_suite::get_instance().init(fileDir);
#define STAT_GLOBAL_FINISH() test_suite::get_instance().finish();
#else
	#define STAT_TEST_INIT(name) 

#define STAT_TEST_BEGIN(name) (void*)(0)

#define STAT_TEST_END(name) (void*)(0)

#define STAT_GLOBAL_INIT(fileDir) 
#define STAT_GLOBAL_FINISH() (void*)(0)
#endif
#endif

st_stat.cpp?文件

?

#include"stdafx.h"
#include"st_stat.h"

#ifdef _WIN32
#include<windows.h>
void call_stat_begin(st_stat*pstat)
{
	pstat->call_count++;
	LARGE_INTEGER large_integer;
	DWORD mask = 1;
	//DWORD_PTR oldmask = ::SetThreadAffinityMask(::GetCurrentThread(),mask);//特别注意,在准确测试时候是需要设置cpu亲和性,否则多核情况下不准确,这里都注释掉
	BOOL bRet = ::QueryPerformanceCounter(&large_integer);

	//::SetThreadAffinityMask(::GetCurrentThread(),oldmask);
	_ASSERT(bRet);

	pstat->start = large_integer;
}
void call_stat_end(st_stat*pstat)
{
	DWORD mask = 1;
	//DWORD_PTR oldmask = ::SetThreadAffinityMask(::GetCurrentThread(),mask);
	LARGE_INTEGER large_integer;
	BOOL bRet = ::QueryPerformanceCounter(&large_integer);
	_ASSERT(bRet);
	//::SetThreadAffinityMask(::GetCurrentThread(),oldmask);
	pstat->end = large_integer;
	pstat->time += pstat->end.QuadPart-pstat->start.QuadPart;
}

void Runnable::begin()
{
	::call_stat_begin(&stat);

}
void  Runnable::end()
{
	call_stat_end(&stat);
}

void test_suite::func_begin(const std::string & name)
{
	// Run test initializers
	const_it it = test_vec.find(name);
	if(it!=test_vec.end())
	{
		LARGE_INTEGER large_integer;
		BOOL bRet = ::QueryPerformanceCounter(&large_inte