C++高精度计时器——微秒级时间统计

作者: admin 分类: C++ 发布时间: 2021-10-06 21:42

转载:https://www.cnblogs.com/hbccdf/p/microsecond_performance_statistics.html


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

 

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

标签云