[C++] 程序耗时统计函数的使用指南


在代码调试过程中,经常使用耗时函数统计程序代码段的时间。

精度方面

  • clock_gettime: ns (推荐)
  • gettimeofday: us
  • times: 10ms
  • clock: 10ms

1. clock_gettime

  • 首先clock_gettime 是一个系统调用,用于获取系统时间。
  • 注意在多线程或者多进程使用时的竞争问题
  • 如果系统时钟源不稳定,会导致这个数据的准确性;但是一般是稳定的,除非外部授时源因为同步而修改系统时间,就会导致不稳定。
  • 避免使用这个函数过于频繁,否则导致严重性能下降。

1.1 基本使用

#include <time.h>
// clockid_t 主要有4个值
// CLOCK_REALTIME: 这个是系统的实时时间,会根据用户改变系统时间而改变。是从UTC1970-1-1 0:0:0 开始计时。(绝对时间)
// CLOCK_MONOTONIC: 从系统启动开始计时,不受系统时间被用户改变而改变。(相对时间)
// CLOCK_PROCESS_CPUTIME_ID: 当前进程进入到cpu所花费的时间,测量进程占用 CPU 的时间; 它是POSIX.1-2008标准下的系统定时器,这个定时器提供了一种方式来获取一个进程自从启动以来所消耗的 CPU 时间,包括用户模式和内核模式下的时间; 
// CLOCK_THREAD_CPUTIME_ID: 当前线程到代码系统CPU花费的时间; 同理CLOCK_PROCESS_CPUTIME_ID
/*
struct timespec {
  time_t rv_sec;  // 秒 
  long tv_nsec;  // 纳秒 
};
*/
int clock_gettime(clockid_t clk_id, struct timespec* tp);

2. clock

  • 这个函数是ANSI C标准库的函数, 在time.h中
  • clock() 返回的是执行程序使用的处理器的时间, 在多任务系统下, 有可能和真实的时间相差很多。
  • clock()函数返回的是CPU时间,而不是实际的时间。这意味着,如果程序在等待I/O操作或其他系统调用时被阻塞,clock()函数不会计算这些时间。
  • 这个函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数。
  • 如果超过一个小时,将要导致溢出.
  • 函数clock没有考虑CPU被子进程使用的情况.
  • 和clock_gettime一样,也不能区分用户空间和内核空间。

2.1 基本使用

#include <time.h>
clock_t start, end;
start = clock();

// do something

end = clock();

// 计算时间以毫秒为单位;
// 也就是(end - start) / CLOCKS_PER_SEC 得到的时间单位是s
// CLOCKS_PER_SEC: 每秒的时钟单位数, 也就是函数返回的是时钟数,
double time_diff = (end - start) / CLOCKS_PER_SEC * 1000;

3. getimeofday

  • 如果您需要测量实际的运行时间(而不是仅CPU时间),您可以使用<sys/time.h>库中的gettimeofday()函数。
  • 精度达不到ns

3.1 基本使用

#include <sys/time.h>
// timezone 参数若不使用则传入NULL即可。
// 它获得的时间精确到微秒(1e-6 s)量级
// 函数执行成功后返回0,失败后返回-1
int gettimeofday(struct timeval*tv, struct timezone *tz);

struct timeval tv_begin, tv_end;
gettimeofday(&tv_begin, NULL);
dosomething();
gettimeofday(&tv_end, NULL);

4. times

  • 可以获取进程或者子进程的用户代码时间和内核代码时间
  • 这个函数的值 和 linux 中的time 工具基本一致; 如 time ./app时打印的时间。
  • 是个相对时间,所以可能也和系统时间改变无关。

4.1 基本使用

#include<sys/times.h>
#include <sys/types.h>
#include <time.h>
/*
strace tms{
 clock_t tms_utime; // 记录的是进程执行用户代码的时间.
 clock_t tms_stime; // 记录的是进程执行内核代码的时间.
 clock_t tms_cutime; // 记录的是子进程执行用户代码的时间.
 clock_t tms_cstime; // 记录的是子进程执行内核代码的时间.
}
*/
clock_t times(struct tms *buf); // 返回值是过去一段时间内时钟嘀嗒的次数

struct tms tmsstart, tmsend;
clock_t start, end;

// sysconf(_SC_CLK_TCK) 是一个在 Unix 和类 Unix 系统中用来获取系统时钟滴答(tick)频率的函数调用。这个值表示每秒中的时钟滴答次数,通常用于衡量系统时间函数(如 times 函数)的分辨率
start = times(&tmsstart); // 如果为-1, 则获取时间失败
end = times(&tmsend);
clktck=sysconf(_SC_CLK_TCK) // 如果小于0, 则失败

// 注意都需要除以 时钟滴答频率。
printf("real:%7.2f\n", (end-start)/(double)clktck);
printf("user-cpu:%7.2f\n", (tmsend->tms_utime - tmsstart->tms_utime)/(double)clktck);

其他能获取 用户和内核时间的方法: getrusage in <sys/resource.h>

5. chrono库的使用

Reference

  • https://blog.csdn.net/tjcwt2011/article/details/137235482
  • https://blog.csdn.net/tianya_lu/article/details/134068972
  • https://baike.baidu.com/item/gettimeofday/3369586?fr=ge_ala
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值