Benchmarking Nanosekunden-Zeitstempel: std::chrono vs clock_gettime(CLOCK_REALTIME)

In C/C++ gibt es zwei wesentliche Methoden der Zeitstempelung mit Nanosekunden-Auflösung:

Methode A: std::chrono::high_resolution_clock

benchmark_nanosecond_timestamping.cpp
uint64_t getCurrentNanoTimestampCpp() {
    return std::chrono::duration_cast<std::chrono::nanoseconds>(
        std::chrono::high_resolution_clock::now().time_since_epoch()
    ).count();
}

Diese Methode erfordert nur C++11 und die C++-Standardbibliothek. Sie ist portabel und funktioniert auf allen Plattformen, die C++11 unterstützen.

Methode B: clock_gettime(CLOCK_REALTIME)

get_current_nanotime_c.cpp
#include <ctime>

uint64_t getCurrentNanoTimestampC() {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return (uint64_t)ts.tv_sec * 1000000000LL + ts.tv_nsec;
}

Diese Methode ist auf POSIX-kompatiblen Systemen verfügbar und nicht auf Windows portierbar.

Benchmarking

Siehe unten für den vollständigen Code, um die beiden Methoden zu benchmarken.

Ergebnisse

Ergebnisse auf Intel(R) Core(TM) i7-14700, Ubuntu mit Kernel 6.8.1-1018-realtime und g++ -fexpensive-optimizations -O3 -march=native -o benchmark_nanosecond_timestamping benchmark_nanosecond_timestamping.cpp

benchmark_results.txt
C clock_gettime average time per call: 13.603 ns
C++ chrono average time per call: 14.1544 ns

Mit anderen Worten:

Vollständiger Benchmark-Code

benchmark_nanosecond_timestamping_full.cpp
#include <iostream>
#include <chrono>
#include <ctime>

uint64_t getCurrentNanoTimestampC() {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return (uint64_t)ts.tv_sec * 1000000000LL + ts.tv_nsec;
}

uint64_t getCurrentNanoTimestampCpp() {
    return std::chrono::duration_cast<std::chrono::nanoseconds>(
        std::chrono::system_clock::now().time_since_epoch()
    ).count();
}

void benchmarkFunction(uint64_t (*func)(), const std::string& name, int iterations) {
    auto start = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < iterations; ++i) {
        func();
    }
    auto end = std::chrono::high_resolution_clock::now();

    std::chrono::duration<double, std::nano> duration = end - start;
    std::cout << name << " average time per call: "
              << (duration.count() / iterations) << " ns" << std::endl;
}

int main() {
    constexpr int iterations = 10000000;

    benchmarkFunction(getCurrentNanoTimestampC, "C clock_gettime", iterations);
    benchmarkFunction(getCurrentNanoTimestampCpp, "C++ chrono", iterations);

    return 0;
}

Check out similar posts by category: C/C++, Performance, Benchmarks