这几天,一直忙于测试程序性能,基于rational 的quantify 工具进行性能测试,能够对exe,dll文件测试,还是很不错的,可以在ibm官方网站下载,不算太大。因为trial版,没有把数据保存起来。
- <1>支持EXE,DLL分析
- <2>支持Line,function,time分析
- <3>支持多线程分析,可以独立分析线程
- <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 Software Corporation开发的专业软件测试工具,属于Rational Purify Plus系列的一部分。该工具主要用于检测C/C++及Java应用中的内存管理错误,帮助开发者提高软件...
Rational Purify Crack Keygen 6.0 Rational Purify Crack Keygen 6.0
Rational公司提供了一系列强大的测试工具,如Rational Purecoverage、Rational Purify、Rational Quantify和Rational Robot,这些工具可以帮助开发者和测试人员有效地进行代码覆盖率分析、内存泄漏检测、性能优化...
如何使用测试工具Rational Purify.swf
详细介绍了Rational Purify的知识和使用方法
《使用Rational Purify与GDB进行Power C/C++调试》一文,深入探讨了在UNIX平台上开发的C/C++应用程序中的调试技巧,特别聚焦于动态内存管理问题及其解决方案。文章由Rational Software B.V.的技术营销工程师Goran ...
Rational Purify Plus是一款强大的软件质量保证工具,主要用于C/C++程序的动态分析,它集成了Rational Purify、Rational Visual Quantify和Rational Visual PureCoverage三个子工具,分别针对可靠性测试、性能评估和...
### 如何使用Rational进行性能测试 #### 一、性能测试的主要步骤 1. **明确测试目的**:性能测试可以分为几种类型,包括基准测试、配置测试、负载测试、压力测试和争用测试等。每种类型的测试都有其特定的目标。...
rational purify plus v2003 crack
IBM Rational PurifyPlus 安装文件包
IBM Purify/PureCoverage Test Factory是保证软件的可靠性和可测试性的一种实时自动化测试工具。其隶属于IBM公司的自动化测试工具包Rational Software,是一种嵌入式的测试软件,可以嵌入多种开发环境中,如Visual ...
### Purify - Rational的测试工具知识点详述 #### 一、Purify工具概述与功能特点 Purify是Rational公司(后被IBM收购)推出的一款强大的内存调试工具,主要用于帮助开发者检测C/C++代码中的内存泄漏和性能瓶颈问题...
### Rational测试工具—性能测试考试模拟题解析 #### 1. 性能测试定义与目的 - **知识点**: 性能测试是一种系统测试方法,旨在评估软件应用在各种负载条件下的表现,包括响应时间、吞吐量、资源利用率等方面。 - **...
8. **与其他工具的配合**:Purify可以与其他IBM的Rational工具(如Rational Rose、Rational ClearCase等)结合使用,实现从需求管理、设计、编码到测试的完整软件开发生命周期管理。 总结,"Rational_Purify_Key"是...
### Rational 测试工具-性能测试 课程大纲知识点详解 #### 第一章:IBMRationalPerformanceTester简介 **知识点概述:** - **性能测试基础:** 阐明性能测试的基本概念,包括它的重要性和应用场景。 - **Rational ...
RPT则是性能测试工具,用于模拟大量并发用户,以测试应用程序在高负载下的性能和稳定性,帮助找出系统瓶颈。 配置管理与测试自动化相辅相成,前者保证了代码的有序和一致性,后者提升了测试的效率和准确性。在实际...
1. **性能测试需求**:首先,明确性能测试的目标和度量指标。这通常包括响应时间、并发用户数、交易吞吐量、交易成功率以及资源使用情况等。性能需求应该具体、可衡量,并且与业务目标紧密相关。 2. **录制和修改...
Rational Administrator 中创建测试项目、Rational Robot 的功能测试和性能测试、使用 Project 2003 进行项目计划编写等多方面的内容。 知识点: 1. Rational Suite Enterprise 的安装:包括安装环境的配置、安装...
这个名为“ibm rational 助您轻松完成自动化的性能测试和性能优化v20.rar”的压缩包文件包含了关于如何利用IBM Rational工具进行自动化性能测试和优化的详细资料,特别是文档“IBM Rational助您轻松完成自动化的性能...