C++ Programmer's Cookbook

{C++ 基础} {C++ 高级} {C#界面,C++核心算法} {设计模式} {C#基础}

使用API实现1/1000秒的性能测试类

 

//  MbUnit Test Framework
//  
//  Copyright (c) 2004 Jonathan de Halleux
//
//  This software is provided 'as-is', without any express or implied warranty. 
//  
//  In no event will the authors be held liable for any damages arising from 
//  the use of this software.
//  Permission is granted to anyone to use this software for any purpose, 
//  including commercial applications, and to alter it and redistribute it 
//  freely, subject to the following restrictions:
//
//         1. The origin of this software must not be misrepresented; 
//         you must not claim that you wrote the original software. 
//         If you use this software in a product, an acknowledgment in the product 
//         documentation would be appreciated but is not required.
//
//         2. Altered source versions must be plainly marked as such, and must 
//         not be misrepresented as being the original software.
//
//         3. This notice may not be removed or altered from any source 
//         distribution.
//         
//         MbUnit HomePage:  http://mbunit.tigris.org
//         Author: Jonathan de Halleux

using  System;
using  System.Runtime.InteropServices;
using  System.ComponentModel;
using  System.Threading;

namespace  MbUnit.Core.Monitoring
{
    
///   <summary>
    
///  A high performance timer
    
///   </summary>
    
///   <remarks>
    
///  High Precision Timer based on Win32 methods.
    
///   </remarks>
    
///   <example>
    
///  This example times the execution of a method:
    
///   <code>
    
///  TimeMonitor timer = new TimeMonitor();
    
///  timer.Start();
    
///      // execute code
    
///  timer.Stop();
    
///  
    
///  Console.WriteLine("Duration: {0}",timer.Duration);
    
///   </example>

     public   class  TimeMonitor
    
{
        [DllImport(
" Kernel32.dll " )]
        
private   static   extern   bool  QueryPerformanceCounter( out   long  lpPerformanceCount);  

        [DllImport(
" Kernel32.dll " )]
        
private   static   extern   bool  QueryPerformanceFrequency( out   long  lpFrequency);
        
        
private   long  startTime, stopTime;
        
private   long  now;
        
private   long  freq;
        
        
///   <summary> Default constructor </summary>
        
///   <remarks> Initializes the timer. </remarks>

         public  TimeMonitor()
        
{
            startTime 
=   0 ;
            stopTime  
=   0 ;

            
if  (QueryPerformanceFrequency( out  freq)  ==   false )
            
{
                
//  high-performance counter not supported 
                 throw   new  Win32Exception(); 
            }

        }

        
        
///   <summary> Gets the clock frequency </summary>
        
///   <value> Clock frequency </value>

         public   long  Frequency
        
{
            
get
            
{
                
return   this .freq;
            }

        }

        
        
///   <summary> Starts the timer </summary>
        
///   <remarks> Resets the duration and starts the timer </remarks>

         public   void  Start()
        
{
            
//  lets do the waiting threads there work
            Thread.Sleep( 0 );  

            QueryPerformanceCounter(
out  startTime);
        }

        
        
///   <summary> Stops the timer </summary>
        
///   <remarks> Stops the timer </remarks>

         public   void  Stop()
        
{
            QueryPerformanceCounter(
out  stopTime);
        }

        
        
///   <summary> Gets the current duration value without stopping the timer </summary>
        
///   <value> Current duration value </value>

         public   double  Now
        
{
            
get
            
{
                QueryPerformanceCounter(
out  now);
                
return  ( double )(now  -  startTime)  /  ( double ) freq;
            }
        
        }


        
///   <summary> Gets the timed duration value in seconds </summary>
        
///   <value> Timer duration </value>

         public   double  Duration
        
{
            
get
            
{
                
return  ( double )(stopTime  -  startTime)  /  ( double ) freq;
            }

        }

    }

}




c++版的:
High-resolution timer for timing code fragments 


Timing of code fragments 
is simple: 

record the start time 
execute the code 
record the end time 
calucate the difference between end and start 
For timing exuction time of pieces of code you need a high
-resolution timer. On Windows, Windows CE and Pocket PC/Smartphone (which are Windows CE variations) you can use QueryPerformanceCounter and QueryPerformanceFrequence API calls. 

Here
's a simple implementation in C: 

typedef 
struct prof_timer_t {
    LARGE_INTEGER time_start;
    LARGE_INTEGER time_stop;
}
 prof_timer_t;

void prof_timer_start(prof_timer_t *timer) {
    QueryPerformanceCounter(
&timer->time_start);
}


void prof_timer_stop(prof_timer_t *timer) {
    QueryPerformanceCounter(
&timer->time_stop);
}


double prof_timer_get_duration_in_secs(prof_timer_t *timer) {
    LARGE_INTEGER freq;
    
double duration;
    QueryPerformanceFrequency(
&freq);
    duration 
= (double)(timer->time_stop.QuadPart-timer->time_start.QuadPart)/(double)freq.QuadPart;
    
return duration;
}


And 
in C++

// very simple, high-precision (at least in theory) timer for timing API calls
struct ProfTimer {
    
void Start(void{
        QueryPerformanceCounter(
&mTimeStart);
    }
;
    
void Stop(void{
        QueryPerformanceCounter(
&mTimeStop);
    }
;
    
double GetDurationInSecs(void)
    
{
        LARGE_INTEGER freq;
        QueryPerformanceFrequency(
&freq);
        
double duration = (double)(mTimeStop.QuadPart-mTimeStart.QuadPart)/(double)freq.QuadPart;
        
return duration;
    }


    LARGE_INTEGER mTimeStart;
    LARGE_INTEGER mTimeStop;
}
;

And here
's an example of using the C++ version: 

    ProfTimer t;
    t.Start();
    foo();
    t.Stop();
    
double dur = t.GetDurationInSecs();
    printf(
"executing foo() took %f seconds\n" , dur);

posted on 2006-06-16 14:07 梦在天涯 阅读(1572) 评论(1)  编辑 收藏 引用 所属分类: CPlusPlusC#/.NETVS2005/2008

评论

# re: 性能测试类 2006-06-16 14:26 梦在天涯

GetTickCount()和GetCurrentTime()都只精确到55ms(1个tick就是55ms)。如果要精确到毫秒,应该使用timeGetTime函数或QueryPerformanceCounter函数。
虽然timeGetTime返回值的单位是1ms,但实际上它的精度只有10ms左右。
如果想提高精度,可以使用QueryPerformanceCounter和QueryPerformanceFrequency。这两个函数不是在每个系统中都支持。对于支持它们的系统中,可以获得低于1ms的精度。Windows 内部有一个精度非常高的定时器, 精度在微秒级, 但不同的系统这个定时器的频率不同, 这个频率与硬件和操作系统都可能有关。利用 API 函数 QueryPerformanceFrequency 可以得到这个定时器的频率。利用 API 函数 QueryPerformanceCounter 可以得到定时器的当前值。根据要延时的时间和定时器的频率, 可以算出要延时的时间定时器经过的周期数。在循环里用 QueryPerformanceCounter 不停的读出定时器值, 一直到经过了指定周期数再结束循环, 就达到了高精度延时的目的。  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

EMail:itech001#126.com

导航

统计

  • 随笔 - 461
  • 文章 - 4
  • 评论 - 746
  • 引用 - 0

常用链接

随笔分类

随笔档案

收藏夹

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

积分与排名

  • 积分 - 1665744
  • 排名 - 5

最新评论

阅读排行榜