`

Rational purify trial性能测试——(1)

阅读更多
  • quantify和简单代码块测试    

       这几天,一直忙于测试程序性能,基于rational 的quantify 工具进行性能测试,能够对exe,dll文件测试,还是很不错的,可以在ibm官方网站下载,不算太大。因为trial版,没有把数据保存起来。

 

  1. <1>支持EXE,DLL分析
  2. <2>支持Line,function,time分析
  3. <3>支持多线程分析,可以独立分析线程
  4. <4>结果图形化,支持树状调用结果;支持属性列表方式

 

以前用过parasoft的测试工具,不记得了,当时觉得那个工具挺好的。

 

quantify可以选择line,function,code,一般选择line就好了。

 

 

这类测试工具,是基于细粒度的测试情况,不能较直观或者有效的分析逻辑处理部分,可以认为是微观分析;我们也需要宏观分析程序代码块,那部分代码块执行次数,耗时等等。

 

写了一个windows 下的简单的测试程序代码块,用于从逻辑换上来分析程序性能的源码;如果需要支持Linux,修改计时函数就行了。

 

st_stat.h

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

	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) \
struct st_##name##_test: Runnable { \
	st_##name##_test(): Runnable(#name) { \
	test_suite::get_instance().addTest(this); \
	} \
} name##_test_instance

#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"st_stat.h"

#ifdef _WIN32
#include<windows.h>
void call_stat_begin(st_stat*pstat)
{
	pstat->call_count++;
	LARGE_INTEGER large_integer;
	BOOL bRet = ::QueryPerformanceCounter(&large_integer);
	_ASSERT(bRet);
	pstat->start = large_integer;
}
void call_stat_end(st_stat*pstat)
{
	LARGE_INTEGER large_integer;
	BOOL bRet = ::QueryPerformanceCounter(&large_integer);
	_ASSERT(bRet);
	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_integer);
		_ASSERT(bRet);
		(*it).second->begin();
		return;
	}
	Runnable *pTest = new Runnable(name);
	test_vec.insert(pair<string,Runnable*>(name,pTest));
	none_init_vec.push_back(pTest);
	pTest->begin();
}

void test_suite::func_end(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_integer);
		_ASSERT(bRet);
		(*it).second->end();
		(*it).second->diff_time(large_integer.QuadPart);

	}
	//printError(name);
	/*vector<Runnable*>::iterator it = test_vec.begin();
	for (; it != test_vec.end(); ++it)
	{
	if ((*it)->name()==name)
	{
	LARGE_INTEGER large_integer;
	BOOL bRet = ::QueryPerformanceCounter(&large_integer);
	_ASSERT(bRet);
	(*it)->end();
	(*it)->diff_time(large_integer.QuadPart);
	}
	}*/

}
void test_suite::printHeading()
{
	if(fp)
	{

		fprintf(fp,"函数名,调用次数,调用时间PerformanceCounter\n");
		fprintf(fp,"start Tick Count=%d ms\r ",::GetTickCount());
	}
}
void test_suite::printFooter()
{
	if(fp)
	{
		fprintf(fp,"end Tick Count=%d ms\r",::GetTickCount());
	}
}
void test_suite:: init(const std::string &dir){
	setWorkingDir(dir);
	if(fp)
	{
		fclose(fp);
		fp = NULL;
	}
	if(getWorkingDir().size()>0)
	{	
		std::string filePath(dir);
		filePath.append("test_performance.csv");

		fp=fopen(filePath.c_str(),"w+");
	}
	else
	{
		fp=fopen("test_performance.csv","w+");
	}

	printHeading();
}
void test_suite::finish()
{

	if(fp)
	{
		for(IT it = test_vec.begin();it!=test_vec.end();it++)
		{
			fprintf(fp,"%s,%d,%I64d\r",it->second->name().c_str(),it->second->getCallCount(),it->second->getCallTime());
		}
	}
	if(fp) 
	{
		fclose(fp);
		fp =NULL;
	}
	std::vector<Runnable*>::iterator it = none_init_vec.begin();
	for(;it !=none_init_vec.end();it++)
	{
		if(*it!=NULL)
		{
			delete *it;
			*it=NULL;
		}
	}
}
void test_suite::printError(const std::string&msg)
{
	if(fp)
	{
		fprintf(fp,"%s",msg.c_str());
	}
}
#endif

 

使用方式,也很简单

开始时:

STAT_GLOBAL_INIT("文件路径");执行一次

 

结束时:

STAT_GLOBAL_FINISH()

这两个宏,特别是最后一个宏,可以优化后,省略这个调用,为了保持与INIT,所以加上了。

打算再优化下,INIT和FINISH默认都可以省略,这样就更简洁明了

 

然后就是如下调用了;

STAT_TEST_BEGIN("测试名字");

XXXXXX;测试代码

STAT_TEST_END("测试名字");

 

  • 结果分析

经过初步Quantify测试结果,得到我现有的程序如下问题:

(1)std:string构造和销毁,耗时太多

(2)malloc和delete调用次数太多,耗时很大

因此,初步从微观可以看出,主要是频繁字符串操作,还有小对象的分配回收;

基本上可以确定方案:需要优化处理字符串,需要使用内存池管理小对象。

 

而基于程序逻辑测试结果:

 

 

函数名 调用次数 调用时间PerformanceCounter
start Tick Count=16480171 ms  
 AddLineGraphToMemory 2043768 842106440
AddRegionGraphToMemory 317901 1462981839
GetShapeFeatureValue 8739066 0
     
LINE_裁剪 2043768 359172490
OutPutReulstFile 70 347857107
REGION_裁剪 274746 -985524651
ReadEveryShapeFile 3702 1332493360
ReadEveryTabFile 249 1898886781

 

上面逻辑宏观测试结果,REGION_裁剪和AddRegionGraphToMemory的耗时太多,这部分逻辑需要额外关照,嘿嘿!

 

  • 下一步:

(1)丰富下这个测试代码,让他支持单元测试,即可测试某一个函数

(2)修改bug,当时间太长,出现负数了

 

  • 大小: 19.4 KB
分享到:
评论

相关推荐

    Rational Purify中文教程

    - **工具介绍**:Rational Purify是一款由Rational Software Corporation开发的专业软件测试工具,属于Rational Purify Plus系列的一部分。该工具主要用于检测C/C++及Java应用中的内存管理错误,帮助开发者提高软件...

    Rational Purify Crack Keygen 6.0

    Rational Purify Crack Keygen 6.0 Rational Purify Crack Keygen 6.0

    如何使用测试工具Rational Purecoverage、Rational Purify、Rational Quantify、Rational Robot

    Rational公司提供了一系列强大的测试工具,如Rational Purecoverage、Rational Purify、Rational Quantify和Rational Robot,这些工具可以帮助开发者和测试人员有效地进行代码覆盖率分析、内存泄漏检测、性能优化...

    如何使用测试工具Rational Purify.swf

    如何使用测试工具Rational Purify.swf

    Rational Purify使用教程

    详细介绍了Rational Purify的知识和使用方法

    Power C-C++ Debugging-Using Rational Purify with GDB.pdf

    《使用Rational Purify与GDB进行Power C/C++调试》一文,深入探讨了在UNIX平台上开发的C/C++应用程序中的调试技巧,特别聚焦于动态内存管理问题及其解决方案。文章由Rational Software B.V.的技术营销工程师Goran ...

    rational_purify培训资料.ppt

    Rational Purify Plus是一款强大的软件质量保证工具,主要用于C/C++程序的动态分析,它集成了Rational Purify、Rational Visual Quantify和Rational Visual PureCoverage三个子工具,分别针对可靠性测试、性能评估和...

    如何使用Rational进行性能测试

    ### 如何使用Rational进行性能测试 #### 一、性能测试的主要步骤 1. **明确测试目的**:性能测试可以分为几种类型,包括基准测试、配置测试、负载测试、压力测试和争用测试等。每种类型的测试都有其特定的目标。...

    rational purify plus v2003 crack

    rational purify plus v2003 crack

    IBM Rational PurifyPlus 安装压缩包3

    IBM Rational PurifyPlus 安装文件包

    Rational_Software_Purify_6.0_(Build_1528).rar

    IBM Purify/PureCoverage Test Factory是保证软件的可靠性和可测试性的一种实时自动化测试工具。其隶属于IBM公司的自动化测试工具包Rational Software,是一种嵌入式的测试软件,可以嵌入多种开发环境中,如Visual ...

    Purify - Rational的测试工具.txt 使用说明

    ### Purify - Rational的测试工具知识点详述 #### 一、Purify工具概述与功能特点 Purify是Rational公司(后被IBM收购)推出的一款强大的内存调试工具,主要用于帮助开发者检测C/C++代码中的内存泄漏和性能瓶颈问题...

    Rational测试工具-性能测试考试模拟题

    ### Rational测试工具—性能测试考试模拟题解析 #### 1. 性能测试定义与目的 - **知识点**: 性能测试是一种系统测试方法,旨在评估软件应用在各种负载条件下的表现,包括响应时间、吞吐量、资源利用率等方面。 - **...

    Rational_Purify_Key

    8. **与其他工具的配合**:Purify可以与其他IBM的Rational工具(如Rational Rose、Rational ClearCase等)结合使用,实现从需求管理、设计、编码到测试的完整软件开发生命周期管理。 总结,"Rational_Purify_Key"是...

    Rational 测试工具-性能测试 课程大纲

    ### Rational 测试工具-性能测试 课程大纲知识点详解 #### 第一章:IBMRationalPerformanceTester简介 **知识点概述:** - **性能测试基础:** 阐明性能测试的基本概念,包括它的重要性和应用场景。 - **Rational ...

    Rational 软件配置管理技术白皮书+Rational 软件测试自动化技术白皮书

    RPT则是性能测试工具,用于模拟大量并发用户,以测试应用程序在高负载下的性能和稳定性,帮助找出系统瓶颈。 配置管理与测试自动化相辅相成,前者保证了代码的有序和一致性,后者提升了测试的效率和准确性。在实际...

    如何利用Rational Performance Tester进行性能测试

    1. **性能测试需求**:首先,明确性能测试的目标和度量指标。这通常包括响应时间、并发用户数、交易吞吐量、交易成功率以及资源使用情况等。性能需求应该具体、可衡量,并且与业务目标紧密相关。 2. **录制和修改...

    《项目管理及软件测试》实验指导书.docx

    Rational Administrator 中创建测试项目、Rational Robot 的功能测试和性能测试、使用 Project 2003 进行项目计划编写等多方面的内容。 知识点: 1. Rational Suite Enterprise 的安装:包括安装环境的配置、安装...

    08 Rational测试工具 - 性能测试

    1. **性能测试**:性能测试是为了评估软件系统在特定工作负载下的响应时间、吞吐量、资源利用率等关键性能指标。它不仅关注功能的正确性,更关注系统在压力下的表现。 2. **Rational Performance Tester**:是IBM ...

    ibm rational 助您轻松完成自动化的性能测试和性能优化v20.rar

    这个名为“ibm rational 助您轻松完成自动化的性能测试和性能优化v20.rar”的压缩包文件包含了关于如何利用IBM Rational工具进行自动化性能测试和优化的详细资料,特别是文档“IBM Rational助您轻松完成自动化的性能...

Global site tag (gtag.js) - Google Analytics