C++ 中的耗时计算函数

2024-01-08 16:52:18
#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,常用的定义有以下几种:

  1. CLOCK_REALTIME:这是实际的时间,即从 1970 年 1 月 1 日(UTC)至今的秒数。这种计时方式会受到 NTP(网络时间协议)的影响,系统时间可能会被自动调整。用户可以修改系统时间,但修改后会影响到 CLOCK_REALTIME 的计数。
  2. CLOCK_MONOTONIC:这是单调时间,即从系统启动到现在的时间。CLOCK_MONOTONIC 时钟不受系统时间不连续跳跃的影响(例如,如果系统管理员手动更改时钟),但是受到由 adjtime() 和 NTP 执行的增量调整的影响。在系统休眠(suspend)时,CLOCK_MONOTONIC 会停止增加。
  3. CLOCK_MONOTONIC_RAW:与 CLOCK_MONOTONIC 类似,但不同之处在于它不会受到 NTP 的影响。即使 NTP 服务器和本地的时钟硬件之间存在问题,NTP 也不会影响到 CLOCK_MONOTONIC_RAW 的频率。该时钟 ID 从 Linux 2.6.28 内核开始引入,Linux 特有。
  4. 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() 函数获取运行时刻的实际时间并存储在 startend 两个变量中,然后计算经过的时间(毫秒),最后得出函数运行耗时。

以下是一种 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;
}

文章来源:https://blog.csdn.net/bluebird_shao/article/details/135388127
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。