time.h 中的 time() 是单调的吗?

Cap*_*man 3 c++ performance time

我说的是老式的 time() 函数,它返回自纪元以来的秒数(UTC)。这应该是单调的,对吧?

在我的测试中(见下文),它的运行速度比使用 CLOCK_MONOTONIC 的 Clock_gettime 快大约 10 倍,所以我想知道它是否可以用作单调计时器,用于我需要低延迟低分辨率单调计时器的情况。(例如,删除服务器上存在时间超过 15 秒的连接)

如果您好奇的话,这是代码:

#include <cstdio>
#include <chrono>
#include <time.h>
#include <sys/time.h>
#include <x86intrin.h>

using namespace std;

class Timer {
    std::chrono::time_point<std::chrono::steady_clock> start;
public:
    inline double t() {
        auto end = std::chrono::steady_clock::now();
        std::chrono::duration<double> diff = end - start;
        return diff.count();
    }
    inline double milli() { return t() * 1000.0;}
    Timer() :start(std::chrono::steady_clock::now()) {}
};

const int nloop = 10000000;

void cpp_steady() {
    for (int i=0;i<nloop;i++) {
        chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
    }
}

void get_tod() {
    timeval tv;
    for (int i=0;i<nloop;i++) {
        gettimeofday(&tv, 0);
    }
}

void get_clock() {
    for (int i=0;i<nloop;i++) {
        clock_t t = clock();
    }
}

void get_time() {
    int x =0;
    for (int i=0;i<nloop;i++) {
        time_t t = time(0);
        x+=t*3;
    }
    fprintf(stderr,"%d\n",x);    
}

void get_clock_gettime() {
    timespec ts;
    for (int i=0;i<nloop;i++) {
        clock_gettime(CLOCK_MONOTONIC, &ts);
    }
}

void get_rdtsc() {
    for (int i=0;i<nloop;i++) {
        __rdtsc();
    }
}

void emptyloop() {
    int x=0;
    for (int i=0;i<nloop;i++) {
        x+=3*i;
    }
    fprintf(stderr,"%d\n",x);
}

void measure(const char *name, void (*f)()) {
    Timer t;
    f();
    double dur = t.milli();
    printf(" %-15s : %.3f ms\n", name, dur);
}

int main () {

    measure("cpp_steady", cpp_steady);
    measure("gettimeofday", get_tod);
    //measure("clock", get_clock);  //too fking slow
    measure("time", get_time);
    measure("clock_gettime", get_clock_gettime);
    measure("rdtsc", get_rdtsc);
    measure("empty", emptyloop);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

./clk_bench 2>/dev/null
 cpp_steady      : 212.415 ms
 gettimeofday    : 200.733 ms
 time            : 19.526 ms
 clock_gettime   : 197.791 ms
 rdtsc           : 75.169 ms
 empty           : 2.821 ms

Run Code Online (Sandbox Code Playgroud)

(顺便说一句,我知道这只是几纳秒的问题,并不重要,但实际上 time_t 也消耗更少的内存,并且比其他替代方案更便携......)

Ser*_*sta 7

time除了不保证单调之外,没有明确的答案。

它只是返回内核认为的当前时间。如果存在保证时钟永远不会倒退的操作程序,并且遵守这些程序,那么它应该是单调的。例如,在用于ntpd时间同步的 Unix 机器上,时钟永远不应该向后运行。但是,如果管理员(在机器上具有管理员权限的人)发现机器时间不准确并将其向后修正,那么任何单调假设都将是错误的。