Rational purify trial性能テスト——(1)
9166 ワード
以前parasoftのテストツールを使ったことがありますが、覚えていません.そのツールはいいと思いました.
quantifyはライン、function、codeを選択できますが、一般的にラインを選択すればいいです.
このようなテストツールは、細粒度のテスト状況に基づいて、より直観的または有効な分析論理処理部分ができず、ミクロ分析と考えられる.マクロ解析プログラムのコードブロックも必要です.そのコードブロックの実行回数、時間などがかかります.
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
");
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(「ファイルパス」);1回実行
終了時:
STAT_GLOBAL_FINISH()
この2つのマクロ、特に最後のマクロは、最適化された後、この呼び出しを省略し、INITと維持するために加算されます.
再最適化する場合、INITとFINISHはデフォルトで省略できるので、より簡潔明瞭になります.
次のように呼び出されます.
STAT_TEST_BEGIN(「テスト名」);
XXXXXX;テストコード
STAT_TEST_END(「テスト名」);
(1)std:string構造と破棄、時間がかかりすぎる
(2)mallocとdeleteの呼び出し回数が多すぎて時間がかかる
そのため、初歩的にミクロから見ると、主に頻繁な文字列操作であり、小さなオブジェクトの分配回収もある.
基本的にシナリオを決定できます.処理文字列を最適化する必要があり、メモリプールを使用して小さなオブジェクトを管理する必要があります.
プログラム論理テストの結果に基づいて:
関数名
呼び出し回数
呼び出し時間Performance Counter
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の時間がかかりすぎて、この論理は追加の配慮が必要です.へへへ!
(2)バグを修正し、時間が長すぎると負数が出る