程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++高性能計數器——微秒級時間統計,計數器微秒

C++高性能計數器——微秒級時間統計,計數器微秒

編輯:C++入門知識

C++高性能計數器——微秒級時間統計,計數器微秒


在C++中,經常需要通過計時來統計性能信息,通過統計的耗時信息,來分析性能瓶頸,通常情況下,可能毫秒級別的時間統計就足夠用了,但是在毫厘必爭的性能熱點的地方,毫秒級別的統計還是不夠的,這種情況下,就需要至少微秒級別的統計信息,甚至要精確到CPU的指令周期級別。下面來重點說一下毫秒級的計時統計信息。

毫厘必爭--微秒計時思路

在Windows平台上,用來統計微秒級別耗時信息,需要用到兩個Windows API:

BOOL WINAPI QueryPerformanceFrequency(
  _Out_  LARGE_INTEGER *lpFrequency
);

BOOL WINAPI QueryPerformanceCounter(
  _Out_  LARGE_INTEGER *lpPerformanceCount
);

QueryPerformanceFrequency用於獲取性能計數的頻率,每秒多少次,

QueryPerformanceCounter用於獲取當前性能計數的值,

有了這兩個API,我們就可以用來統計耗時了,思路如下:

秒級耗時 = (結束性能計數值 - 開始性能計數值) / 性能計數頻率 微秒耗時 = (結束性能計數值 - 開始性能計數值)* 1000000 / 性能計數頻率

微秒計時實現

LARGE_INTEGER freq_;
QueryPerformanceFrequency(&freq_);

LARGE_INTEGER begin_time;
LARGE_INTEGER end_time;
QueryPerformanceCounter(&begin_time);
Sleep(100);
QueryPerformanceCounter(&end_time);

double ns_time = (end_time.QuadPart - begin_time.QuadPart) * 1000000.0 / freq_.QuadPart;

封裝微秒計時的實現

雖然上面已經實現了微秒精度計時,但是由於每次調用API時,都要定義變量等,使用起來肯定會有很多重復或者類似的代碼,那麼為了避免這種情況,對此實現進行了封裝,如下:

class stop_watch
{
public:
    stop_watch()
        : elapsed_(0)
    {
        QueryPerformanceFrequency(&freq_);
    }
    ~stop_watch(){}
public:
    void start()
    {
        QueryPerformanceCounter(&begin_time_);
    }
    void stop()
    {
        LARGE_INTEGER end_time;
        QueryPerformanceCounter(&end_time);
        elapsed_ += (end_time.QuadPart - begin_time_.QuadPart) * 1000000 / freq_.QuadPart;
    }
    void restart()
    {
        elapsed_ = 0;
        start();
    }
    //微秒
    double elapsed()
    {
        return static_cast<double>(elapsed_);
    }
    //毫秒
    double elapsed_ms()
    {
        return elapsed_ / 1000.0;
    }
    //秒
    double elapsed_second()
    {
        return elapsed_ / 1000000.0;
    }

private:
    LARGE_INTEGER freq_;
    LARGE_INTEGER begin_time_;
    long long elapsed_;
};

那麼,如何使用此封裝的類呢,來看一下調用的例子:

stop_watch watch;
watch.start();
Sleep(100);
watch.stop();
cout << watch.elapsed() << " ns" << endl;

看看調用是不是更方便了呢,是不是有點似曾相識的感覺,對,沒錯,你猜對了。。。

參考資料

QueryPerformanceFrequency

QueryPerformanceCounter

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved