zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    云架构系统如何做性能分析?| 实战干货
    1024 程序员日,聊聊升职加薪与职业发展!
    测试面试题集锦(三)| 计算机网络和数据库篇(附答案)
    在线沙龙 | 前端测试技术创新与实践
    测试开发系列课程学员打卡听课细则
    这 5 款实用性能测试工具,你会如何选择?
    618 年中大促!Python 自动化测试训练营立减 1000 元!送接口测试实战课!
    美人
    栀子花开
    朋友别哭
  • 原文地址:https://www.cnblogs.com/hbccdf/p/microsecond_performance_statistics.html
Copyright © 2011-2022 走看看