#include <time.h>
int clock_gettime (clockid_t clock_id, struct timespec *tp)
获取当前 clock_id 的时钟值并存储在 tp 中。
其中 tp 是一个 timespec 结构体,在 time.h 头文件中定义:
#include <time.h>:
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
clock_id 是识别系统时钟的 ID,常用的定义有以下几种:
- CLOCK_REALTIME:这是实际的时间,即从 1970 年 1 月 1 日(UTC)至今的秒数。这种计时方式会受到 NTP(网络时间协议)的影响,系统时间可能会被自动调整。用户可以修改系统时间,但修改后会影响到 CLOCK_REALTIME 的计数。
- CLOCK_MONOTONIC:这是单调时间,即从系统启动到现在的时间。CLOCK_MONOTONIC 时钟不受系统时间不连续跳跃的影响(例如,如果系统管理员手动更改时钟),但是受到由
adjtime()
和 NTP 执行的增量调整的影响。在系统休眠(suspend)时,CLOCK_MONOTONIC 会停止增加。 - CLOCK_MONOTONIC_RAW:与 CLOCK_MONOTONIC 类似,但不同之处在于它不会受到 NTP 的影响。即使 NTP 服务器和本地的时钟硬件之间存在问题,NTP 也不会影响到 CLOCK_MONOTONIC_RAW 的频率。该时钟 ID 从 Linux 2.6.28 内核开始引入,Linux 特有。
- CLOCK_BOOTTIME:与 CLOCK_MONOTONIC 类似,当系统进入休眠(suspend)时,它会继续增加。
可以通过「
man 3 clock_gettime
」命令查阅 Linux 手册获取 clock_id 更详细信息。
我们通过以下示例来展示程序运行耗时的计算方法:
#include <time.h>
int main(int argc, char const *argv[])
{
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
func_or_code_here(); // your code ...
clock_gettime(CLOCK_MONOTONIC_RAW, &end);
long elapsed_ms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1e6;
return 0;
}
在上面的示例中,通过 clock_gettime()
函数获取运行时刻的实际时间并存储在 start
与 end
两个变量中,然后计算经过的时间(毫秒),最后得出函数运行耗时。
以下是一种 C++ 的封装方式,文件名为 timer.h,仅供参考:
#include <time.h>
class Timer {
public:
Timer() {
reset();
}
~Timer() = default;
long elapsed_sec() {
clock_gettime(CLOCK_MONOTONIC_RAW, &_end);
return (_end.tv_sec - _start.tv_sec) + (_end.tv_nsec - _start.tv_nsec) / 1e9;
}
long elapsed_ms() {
clock_gettime(CLOCK_MONOTONIC_RAW, &_end);
return (_end.tv_sec - _start.tv_sec) * 1000 + (_end.tv_nsec - _start.tv_nsec) / 1e6;
}
long elapsed_us() {
clock_gettime(CLOCK_MONOTONIC_RAW, &_end);
return (_end.tv_sec - _start.tv_sec) * 1e6 + (_end.tv_nsec - _start.tv_nsec) / 1000;
}
long elapsed_ns() {
clock_gettime(CLOCK_MONOTONIC_RAW, &_end);
return (_end.tv_sec - _start.tv_sec) * 1e9 + (_end.tv_nsec - _start.tv_nsec);
}
void reset() {
clock_gettime(CLOCK_MONOTONIC_RAW, &_start);
}
private:
struct timespec _start;
struct timespec _end;
};
在以上的封装过程中,在 Timer
类中定义了 _start
与 _end
成员变量,用于存储开始时间与结束时间,Timer
类提供了计算耗时的秒(elapsed_sec
),毫秒(elapsed_ms
),微秒(elapsed_us
),纳秒(elapsed_ns
)的成员函数。同时提供了 reset
函数用于重新计时。在这里我们可以通过以下示例来更好地理解 Timer
的用法:
#include <iostream>
#include "timer.h"
int main(int argc, char const *argv[])
{
Timer t;
func_or_code_here(); // your code ...
long elapsed_ms = t.elapsed_ms();
return 0;
}