您的位置:首页 > 其它

PROFILE技术总结(一): 应用微秒级精度定时器的方法

2008-02-20 09:53 393 查看
作者:liswei 可惜此人没有开辟BLOG

摘要:Profile在英文中解释为分类,文档管理。在我们计算机世界中,我们可以通过各种方法来测试我们程序或整个系统的性能,这些方法包括通过测试运行时间、访问cpu的次数,占用多少资源等,我们把这类方法统称为Profile技术。以下我将从应用微秒级精度定时器测试、利用Monte Carlo Profiler 工具、Perfalyzer 方法测试这三方面来介绍Profile技术。本篇先介绍应用应用微秒级精度定时器测试程序的效率。

一、应用微秒级精度定时器测试原理

高精度运行计数器(high-resolution performance counter),利用它可以获得高精度定时间隔,其精度与CPU的时钟频率有关。采用这种方法的基本思想如下:

(1)、首先调用QueryPerformanceFrequency函数取得高精度运行计数器的频率f。单位是每秒多少次(n/s),此数一般很大

(2)、在需要定时的代码的两端分别调用QueryPerformanceCounter以取得高精度运行计数器的数值n1,n2。两次数值的差值通过f换算成时间间隔,t=(n2-n1)/f。

二、微秒级精度定时器测试具体实现

为了更好的提高该测试函数的可用性,我根据原理把实现函数封装成一个类,使其可以更好的被使用,并且我们这个类可以通过建立链表一次性可以测试很多个函数。本类包括两个文件FunctionProfile.h和FunctionProfile.cpp

1、“被测试函数”结点结构体的实现

我们为每个测试函数建立一个结点Node,这个Node用如下结构体来实现:

typedef struct

{

LONG64 StartTime; //记录函数开始运行的时间

int functionIndex; //函数的标识号

TCHAR name[80]; //函数名称

int nProfiler_functionCountCalls; //函数被调用次数

LONG64 Profiler_functionTimings; //函数本身的运行时间

LONG64 Profiler_functionPlusChildTimings;//函数和子函数的运行时间

LONG64 TestFunctionTime; //记录测试函数的时间

void *parent; //记录父结点

}FunctionNode;

2、CFunctionProfile类的定义

1class CFunctionProfile

2

3

73

3、现在对类中几个主要的函数介绍如下:

(1)、QueryTimer函数的实现

这个函数用来获得当前计数器的数值,我们先来介绍下LARGE_INTEGER这个数据结构,这个数据结构如下所示:

1typedef union _LARGE_INTEGER

2

3

如果系统支持64位可以直接使用QuadPart来读取该计数值,如果不支持使用 LowPart和HighPart来取得直。

1void CFunctionProfile::QueryTimer(LONG64* pi64Time)

2

3

(2)SetFunctionName函数的实现

正如函数名所示的意思,这个函数是用来个被测试函数命名添加标识

1void CFunctionProfile::SetFunctionName(int nFunctionId,TCHAR *tFunctionName)

2

3

31

这样不是被测试函数的时间也被记录下来,也就提高了准确性。

(3)、 FunctionProfileStart函数的实现

这个函数记录被测试函数的开始时间和处理测试函数的时间。

1void CFunctionProfile::FunctionProfileStart(int nFunctionID)

2

3

37

这样就完成了被测试函数结点的开始时间的记录。

(4)、 FunctionProfileStop函数的实现

这个函数记录被测试函数的运行时间并对父结点进行处理。

1void CFunctionProfile::FunctionProfileStop(int nFunctionID)

2

3

69

4、在这个类中定义一个开关:

在FunctionProfile.h文件中定义一个,形式如下:

//如果用户定义PROFILE,则我们开启测试功能,否则不做处理,具体定义 可以参看FunctionProfile.h文件

ifdef PROFILE

……………

else

. ……………

Endif

5、定义一些宏定义方便用户使用

(1)、定义被测试函数的个数和被测试函数的标识符号:

//被测试函数个数

#define MAX_FUNCTIONS_TO_PROFILE 20

//被测试函数标识号

#define PROFILE_1 0

#define PROFILE_2 1

#define PROFILE_3 2

…………..

(2)、具体操作宏定义(下面是在PROFILE编译开关中定义的)

//定义一个类指针

static CFunctionProfile * Cprofile =NULL;

//实例化该类指针,并对该类初始化

#define PROFILE_INIT(szFileName)( Cprofile = new CFunctionProfile(szFileName) )

//虚构该类指针

#define PROFILE_DEINIT() {delete Cprofile; Cprofile = NULL;}

//设置被测试函数的名称

#definePROFILE_NAME(nFunctionID,szFunctionName) Cprofile->SetFunctionName(nFunctionID,szFunctionName)

//开始测试被测试函数

#define PROFILE_START(nFunctionID) Cprofile->FunctionProfileStart(nFunctionID)

//结束测试

#define PROFILE_STOP(nFunctionID) Cprofile->FunctionProfileStop(nFunctionID)

//把数据输出到文件中去

#define PROFILE_DUMP() Cprofile->WriteProfilerDataToFile()

6、做一个测试的sample Code:

代码如下:

1int WINAPI WinMain( HINSTANCE hInstance,

2

3 HINSTANCE hPrevInstance,

4

5 LPTSTR lpCmdLine,

6

7 int nCmdShow)

8

9

37void testProfile1( )

38

39

53

54

55void testProfile2( )

56

57

71

运行程序后输出如下结果到ProfileTest926.txt,如下:

Total Time 1.352 ms

Function Function Function Function Function

+ child only + child only only

time time ratio ratio Count time/count Function Name

1.317 0.098 0.97359 0.07258 1 0.098 MAIN_FUNCTION PROFILE,

0.789 0.618 0.58326 0.45689 1 0.618 testProfile1 PROFILE,

0.171 0.171 0.12637 0.12637 8 0.021 testProfile2 PROFILE,

对以上数据解释如下:

● 第一列代表:本身函数和自己的子函数所用时间

● 第二列代表:本身函数的运行时间

● 第三列代表:第一列所代表的时间总用总时间的比例

● 第四列代表:第二列所表示的时间总用总时间的比例

● 第五列代表:函数被调用的次数

● 第六列代表:本测试函数运行一次的平均时间

● 第七列代表:被测试函数的函数名称

至此,利用微秒级精度定时器测试时间的程序就介绍到这,希望对大家有帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: