zoukankan      html  css  js  c++  java
  • C++简单的函数计时方法

       这里提供一个简单的函数计时方法,利用QueryPerformanceFrequency和QueryPerformanceCount函数进行精确计时,这是最精确的计时方法。
       原理是在函数被调用时记录时间,结束时利用局部对象的析构函数再记录一次时间,将这个时间差累积到对应的函数的统计数据中。当程序退出时,全局对象释放,将所有函数的数据输出到调试窗口。使用时,需要再函数开头位置插入一条宏:_PF。需要计时的函数内都插入一条这样的宏。为了方便,宏被定义的比较短。


      FunctionName   ActiveTime    Average  Clled
             WinMain     
    5.480105    5.480105     1
        
             MsgProc     
    0.975687    0.015245    64
        
             InitD3D     
    0.222094    0.222094     1
        
        InitGeometry     
    0.004631    0.004631     1
        
              Render     
    4.876714    0.021771   224
        
       SetupMatrices     
    0.001405    0.000006   224
        
             Cleanup     
    0.209167    0.209167     1 



    #define PERFDATA_INIT_SIZE 32
    #define PERFDATA_INC_SIZE  32
    class PerformanceDaemon 
    {
    private
    :
        typedef 
    struct
     _PERF_DATA
        
    {
            DWORD  nID;
            LPSTR pstrName;
            DWORD TotolCalled;
            LONGLONG TotolTime;
            
    //LARGE_INTEGER FuncBeginTime;


        }
    PERF_DATA,*LPPERF_DATA;


        LPPERF_DATA m_pDatas;
        DWORD m_dwUsed;
        DWORD m_dwSize;

        LARGE_INTEGER m_TickNow;
        LARGE_INTEGER m_Freq;
        
    void
     SetSize(DWORD dwSize)
        
    {
            assert(dwSize
    >
    m_dwUsed);
            LPPERF_DATA pData
    =new
     PERF_DATA[dwSize];
            memcpy(pData,m_pDatas,m_dwUsed
    *sizeof
    (PERF_DATA));
            memset(pData
    +m_dwUsed,0,(dwSize-m_dwUsed)*sizeof
    (PERF_DATA));
            delete []m_pDatas;
            m_pDatas
    =
    pData;
            m_dwSize
    =
    dwSize;
        }

    public:

        PerformanceDaemon ()
        
    {
            m_pDatas
    =0
    ;
            m_dwUsed
    =0
    ;
            m_dwSize
    =0
    ;
            
            SetSize(PERFDATA_INIT_SIZE);

            QueryPerformanceFrequency(
    &
    m_Freq); 
            QueryPerformanceCounter(
    &
    m_TickNow);

        }




        
    void FuncStart(LPSTR pstrName,DWORD &nID)
        
    {
            
    if(nID>=m_dwUsed && nID!=0xFFFFreturn
    ;
            
    if(nID==0xFFFF)    //add new function record;

            {
            

                PERF_DATA data;
                SIZE_T nLenght;
                nLenght
    =
    strlen(pstrName);
                memset(
    &data,0,sizeof
    (data));
                data.pstrName
    =new CHAR[nLenght+1
    ];
                strcpy(data.pstrName,pstrName);

                
    if(m_dwUsed >=
     m_dwSize) 
                    SetSize(m_dwSize
    +
    PERFDATA_INC_SIZE);
                
                nID
    =m_dwUsed++
    ;
                
                

                m_pDatas[nID]
    =
    data;

            }

            QueryPerformanceCounter(
    &m_TickNow);
        }

        
    void GetTime(LONGLONG *pTime)
        
    {
            
    *pTime=
    m_TickNow.QuadPart;
        }


        
    void FuncEnd(DWORD nID,LONGLONG *pTime)
        
    {
            LARGE_INTEGER TickNow;
            QueryPerformanceCounter(
    &
    TickNow);
        
            
    if(nID>=m_dwUsed && nID!=0xFFFFreturn
    ;
            m_pDatas[nID].TotolTime
    += TickNow.QuadPart-*
    pTime;
            m_pDatas[nID].TotolCalled
    ++
    ;
            m_TickNow
    =
    TickNow;    
        
        }


        
    void DumpFunctionPerfmance()
        
    {
            CHAR strBuffer[
    256
    ];

            OutputDebugString(
    "FunctionName\t\tActiveTime\tAverage\t  Clled\n"
    ); 
            
    for(DWORD i=0;i<m_dwUsed;i++
    )
            
    {
                
    double
     t;
                DWORD n
    =
    m_pDatas[i].TotolCalled;

                t
    =m_pDatas[i].TotolTime/double
    (m_Freq.QuadPart); 
                sprintf(strBuffer,
    "%16s %12f\t%8f%6u\t\n",m_pDatas[i].pstrName,t,t/
    n,n);
                OutputDebugString(strBuffer);
            }

        
        }



        
    ~PerformanceDaemon ()
        
    {
            DumpFunctionPerfmance();
            
    for(DWORD i=0;i<m_dwUsed;i++
    )
            
    {
                delete []m_pDatas[i].pstrName;
            
            }

            

            delete []m_pDatas;
        
        
        }


    }
    ;
    PerformanceDaemon  Perf;
    class
     PerformanceWatcher
    {
        DWORD dwID;    
        LONGLONG StartTime;        
    //为了解决嵌套调用问题


    public:
        
    //just for convinience 

        PerformanceWatcher(LPSTR pstrFunName,DWORD &nID)
        
    {
            Perf.FuncStart(pstrFunName,nID);
            dwID
    =
    nID;
            Perf.GetTime(
    &
    StartTime);
            
        }

        
    ~PerformanceWatcher()
        
    {
            Perf.FuncEnd(dwID,
    &
    StartTime);
        }


    }
    ;

    #ifdef _DEBUG
    #define _PF  \

        
    static DWORD __PerfCounter=0xFFFF;\
        PerformanceWatcher __PerfWatcher(__FUNCTION__,__PerfCounter);
    #else

    #define _PF
    #endif 



    VOID Cleanup()
    {
        _PF
        
    if( g_pTexture !=
     NULL )
            g_pTexture
    ->
    Release();

        
    if( g_pVB !=
     NULL )
            g_pVB
    ->
    Release();

        
    if( g_pd3dDevice !=
     NULL )
            g_pd3dDevice
    ->
    Release();

        
    if( g_pD3D !=
     NULL )
            g_pD3D
    ->
    Release();
    }


    据MSDN上的资料,VC6以后的版本上的确支持Profile,但个人感觉没有VC6那么方便了。
    VC6 Function Profiling 参考:
    http://msdn.microsoft.com/en-us/library/aa269759(VS.60).aspx

    另外有一个/callcap的编译宏,这个宏允许函数开始执行和结束时调用两个自定义的函数,参考:
    http://msdn.microsoft.com/en-us/library/ms404386.aspx

    // File: callcaphooks.c

    #include 
    <stdio.h>
    int main();

    void _CAP_Enter_Function(void *p) 
    {
        
    if (p != main) 
            printf(
    "Enter function   (at address %p) at %d\n"
                p, GetTickCount());
            
    return;
    }

    void _CAP_Exit_Function(void *p) 
    {
        
    if (p != main) 
            printf(
    "Leaving function (at address %p) at %d\n"
                p, GetTickCount());
        
    return;
    }




  • 相关阅读:
    Educational Codeforces Round 10 C. Foe Pairs 水题
    Educational Codeforces Round 10 B. z-sort 构造
    CDOJ 1048 Bob's vector 三分
    Educational Codeforces Round 10 A. Gabriel and Caterpillar 模拟
    第14届电子科大初赛民间盗版部分题目题解
    HDU 5654 xiaoxin and his watermelon candy 离线树状数组 区间不同数的个数
    HDU 5653 Bomber Man wants to bomb an Array. dp
    HDU 5652 India and China Origins 二分+并查集
    HDU 5651 xiaoxin juju needs help 数学
    HDU 5650 so easy 数学
  • 原文地址:https://www.cnblogs.com/Tue/p/1244757.html
Copyright © 2011-2022 走看看