PROFILE技术总结(一): 应用微秒级精度定时器的方法
2008-02-20 09:53
411 查看
作者: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,
对以上数据解释如下:
● 第一列代表:本身函数和自己的子函数所用时间
● 第二列代表:本身函数的运行时间
● 第三列代表:第一列所代表的时间总用总时间的比例
● 第四列代表:第二列所表示的时间总用总时间的比例
● 第五列代表:函数被调用的次数
● 第六列代表:本测试函数运行一次的平均时间
● 第七列代表:被测试函数的函数名称
至此,利用微秒级精度定时器测试时间的程序就介绍到这,希望对大家有帮助。
摘要: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,
对以上数据解释如下:
● 第一列代表:本身函数和自己的子函数所用时间
● 第二列代表:本身函数的运行时间
● 第三列代表:第一列所代表的时间总用总时间的比例
● 第四列代表:第二列所表示的时间总用总时间的比例
● 第五列代表:函数被调用的次数
● 第六列代表:本测试函数运行一次的平均时间
● 第七列代表:被测试函数的函数名称
至此,利用微秒级精度定时器测试时间的程序就介绍到这,希望对大家有帮助。
相关文章推荐
- 二级缓存EhCache在几种应用技术的配置方法和步骤总结
- 一起谈.NET技术,【经验总结】C#常用线程同步方法应用场景和实现原理
- 一种制作微秒级精度定时器的方法(转贴)
- 一种制作微秒级精度定时器的方法(转贴)
- Tomcat部署Web应用方法总结
- .Net GridView应用:GridView 使用方法总结
- Tomcat 部署web应用方法总结
- SCORM技术总结及题库应用
- 好的技术博客、应用总结
- 关于ASP.NET页面打印技术的常用方法总结
- EJB核心技术应用总结
- paip.android APK安装方法大总结系统应用的安装
- iOS7以下的应用实现启动画面的方法总结
- java基础技术知识点总结——存储、数组、字段和方法
- 黑马程序员——String类方法应用的总结
- Tomcat 部署web应用方法总结
- 多层数据库应用基于Delphi DataSnap方法调用的实现-----------------对象池技术
- C51单片机 AT89S52 定时器使用方法及总结
- 全面总结NAT技术原理与应用
- 编写高质量OC代码52建议总结:13.用“方法调配技术”调试“黑盒方法”