• 性能测试的时间间隔获取方法


    性能测试的时候,一个问题就是时间间隔,有很多时间函数能获取时间,从而求取时间间隔。关于这方面的文章很多,我就不重复了,这里只是提供一些基本的信息,从而方便我自己做性能测试使用:

    (1)C语言时间函数clock()和clock_t:

    time.h中的C语言时间函数clock()能获取当前时间。需要注意的是,这个函数在Windows和Linux下是通用的,但是其返回值的单位是不同的,一个是毫秒,一个是微秒。

    从单位也可以看出该方式获取时间的精度。总体来说,其精度在毫秒级,所以测试性能的时候,对于粗时间间隔的测试,用这个函数就足够了。

    需要注意的是:在Linux上,clock()获取的是CPU时间,不是wall-clock时间,所以如果使用了sleep()等函数,那么是不会计算在内的。但是在Windows平台上,clock()获取的时间包括Sleep()等函数的时间,所以使用clock()的时候要注意这一点,在Linux上得到的很可能不是一个正确的Elapsed time。

    (2)利用CPU获取高精度时间rdtsc寄存器

    rdtsc是一个64位的寄存器,新的CPU都具备这个寄存器,用于记录从计算机启动开始CPU经过的时钟周期,可见其精度之高是和CPU的频率级别的。

    可以参考http://blog.sina.com.cn/s/blog_5d9051c00100jcsn.html的文章。

    由于是寄存器,所以只要使用汇编读取寄存器的值就可以得到时间了,具体关于汇编的写法有一些不同的形式,具体可以参考网上的写法,而且windows和Linux下也可能是有一些区别。需要注意的是,即使都是在Linux下或都是Windows下,编译64位和32位的时候,其写法也会不一样,参考:http://www.phpzy.com/php/1068620.htmlhttp://www.uplook.cn/index-Index-show-view2681.html?treeid=624(如果错误使用,得到的时间间隔可能为负数)

    PS:在Linux上,-m32和-m64选项分别表示生成32位和64位程序,使用-m32会定义__i386__宏,使用-m64则使用__x86_64__宏。

    关于Windows上,也可以使用rdtsc寄存器,但是windows上生成64位程序的时候,不知道该如何获得正确值,参考http://sunxiunan.com/?p=983里面有64位的情况,但是只能用于Itanium CPU上。根据MSDN的说明(http://msdn.microsoft.com/en-us/library/ee417693.aspx),不建议使用rdtsc寄存器,建议使用更精确的windows API的QueryPerformanceCounter和QueryPerformanceFrequency。

    (3)Windows平台的QueryPerformanceCounter和QueryPerformanceFrequency的使用:

    参考:http://www.oschina.net/code/snippet_197161_6789

    (4)Timing.h和测试:

    下面是能运行于Linux和Windows的代码,可以用于计算程序运行时间,对于一样的性能测试,应该可以胜任。

    // Timing.h
    #ifndef TIMING_H
    #define TIMING_H
    
    #include 
    #include 
    
    #ifdef WIN
    #include 
    #define timing_t double
    static _LARGE_INTEGER time_start, time_over;
    static double dqFreq;
    
    static inline void startTiming()
    {
    _LARGE_INTEGER f;
    QueryPerformanceFrequency(&f);
    dqFreq=(double)f.QuadPart;
    
    QueryPerformanceCounter(&time_start);
    }
    
    // unit: ms
    static inline timing_t stopTiming()
    {
        QueryPerformanceCounter(&time_over);
        return ((double)(time_over.QuadPart-time_start.QuadPart)/dqFreq*1000);
    }
    
    static inline timing_t stopWithPrintTiming()
    {
        timing_t timing;
    QueryPerformanceCounter(&time_over);
        timing = ((double)(time_over.QuadPart-time_start.QuadPart)/dqFreq*1000);
        printf("----------Elapsed Timing(ms) : %.3lf\n", timing);
        printf("----------------------------------------\n");
    
        return timing;
    }
    
    #else
    #include 
    typedef unsigned long long int64;
    #define timing_t int64
    #if defined(__i386__)
    inline int64 GetCycleCount() {
        int64 result;
        __asm__ __volatile__ ("rdtsc" : "=A" (result));
        return result;
    }
    #elif defined(__x86_64__)
    inline int64 GetCycleCount() 
    {
        int64 hi, lo;
        __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
        return ( (int64)lo)|( ((int64)hi)<<32 );
    }
    #endif
    
    static int64 ticks_start, ticks_end;
    
    static inline void startTiming()
    {
    ticks_start = GetCycleCount();
    }
    
    // unit: cycles
    static inline int64 stopTiming()
    {
        ticks_end = GetCycleCount();
        return (ticks_end - ticks_start);
    }
    
    static inline int64 stopWithPrintTiming()
    {
        int64 timing;
        ticks_end = GetCycleCount();
        timing = (ticks_end - ticks_start);
        printf("----------Elapsed Timing(Cycles) : %llu\n", timing);
        printf("----------------------------------------\n");
    
        return timing;
    }
    #endif
    
    // unit: ms
    static inline void wait(int ms)
    {
    #ifdef WIN32
        Sleep(ms);
    #else
        usleep(ms*1000);
    #endif
    }
    
    #endif

    // foo.cpp
    #include "timing.h"
    
    int main()
    {
    timing_t ticks_start, ticks_end;
    startTiming();
    
        wait(3000);// 3 seconds
        timing_t timing = stopWithPrintTiming();
    
        return 1;
    }


    Windows上编译:cl foo.cpp /DWIN,分别启动64bit和32bit的VS控制台进行测试。

    Linux上编译:gcc foo.cpp -m32和gcc foo.cpp -m64进行测试。

  • 相关阅读:
    基于Dockerfile搭建LNMP环境
    最新版本 Stable Diffusion 开源AI绘画工具之部署篇
    嵌入式开发--赛普拉斯cypress的铁电存储器FM25CL64B
    自定义Python版本ESL库访问FreeSWITCH
    Android:ChildHelper的Bucket
    数据可视化:Metabase
    matlab中hamming窗的 c/c++ 版本的实现
    深度学习笔记(3)——pytorch+TextCNN实现情感分类(外卖数据集)
    2024清理mac苹果电脑内存免费工具CleanMyMac X4.15
    常用hivesql记录
  • 原文地址:https://blog.csdn.net/m0_72431373/article/details/127100026