簡體   English   中英

獲得時間戳的最快方法

[英]Fastest way to get a timestamp

我正在實現一些數據結構,在此結構中,我需要在一段時間后使某些條目無效,因此對於每個條目,我需要保持其插入時間戳。 當我得到一個條目時,我需要再次獲得一個時間戳,並從插入中計算經過的時間(如果它太舊了,我將無法使用它)。

許多線程對這個數據結構高度滿意,因此我必須以最有效的方式獲得此時間戳(在insertfind )。 效率在這里非常重要。

如果有關系,我正在使用C ++開發的Linux機器上工作。 檢索時間戳的最有效方法是什么?

順便說一句,在我正在處理的某個舊項目中,我記得我看到一些匯編命令直接從CPU獲取時間戳(不記得該命令)。

我創建了以下基准,以測試幾種檢索時間戳的方法。 基准測試是使用帶有-O2的GCC編譯的,並在我的Mac上進行了測試。 我已經測量了每種方法獲取1M時間戳所花費的時間,從結果看來rdtsc比其他方法快。

編輯:基准進行了修改,以支持多個線程。

基准代碼:

#include <iostream>
#include <chrono>
#include <sys/time.h>
#include <unistd.h>
#include <vector>
#include <thread>
#include <atomic>

#define NUM_SAMPLES 1000000
#define NUM_THREADS 4

static inline unsigned long long getticks(void)
{
    unsigned int lo, hi;

    // RDTSC copies contents of 64-bit TSC into EDX:EAX
    asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
    return (unsigned long long)hi << 32 | lo;
}

std::atomic<bool> g_start(false);
std::atomic<unsigned int> totalTime(0);

template<typename Method>
void measureFunc(Method method)
{
    // warmup
    for (unsigned int i = 0; i < NUM_SAMPLES; i++)
    {   
        method();
    }

    auto start = std::chrono::system_clock::now();

    for (unsigned int i = 0; i < NUM_SAMPLES; i++)
    {   
        method();
    }

    auto end = std::chrono::system_clock::now();
    totalTime += std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
}

template<typename Method>
void measureThread(Method method)
{
    while(!g_start.load());

    measureFunc(method);
}

template<typename Method>
void measure(const std::string& methodName, Method method)
{
    std::vector<std::thread> threads;

    totalTime.store(0);
    g_start.store(false);

    for (unsigned int i = 0; i < NUM_THREADS; i++)
    {
        threads.push_back(std::thread(measureThread<Method>, method));
    }

    g_start.store(true);

    for (std::thread& th : threads)
    {
        th.join();
    }

    double timePerThread = (double)totalTime / (double)NUM_THREADS;

    std::cout << methodName << ": " << timePerThread << "ms per thread" << std::endl;
}

int main(int argc, char** argv)
{
    measure("gettimeofday", [](){ timeval tv; return gettimeofday(&tv, 0); });
    measure("time", [](){ return time(NULL); });
    measure("std chrono system_clock", [](){ return std::chrono::system_clock::now(); });
    measure("std chrono steady_clock", [](){ return std::chrono::steady_clock::now(); });
    measure("clock_gettime monotonic", [](){ timespec tp; return clock_gettime(CLOCK_MONOTONIC, &tp); });
    measure("clock_gettime cpu time", [](){ timespec tp; return clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp); });
    measure("rdtsc", [](){ return getticks(); });

    return 0;
}

單線程的結果(以毫秒為單位):

gettimeofday: 54ms per thread
time: 260ms per thread
std chrono system_clock: 62ms per thread
std chrono steady_clock: 60ms per thread
clock_gettime monotonic: 102ms per thread
clock_gettime cpu time: 493ms per thread
rdtsc: 8ms per thread

有4個線程:

gettimeofday: 55.25ms per thread
time: 292.5ms per thread
std chrono system_clock: 69.25ms per thread
std chrono steady_clock: 68.5ms per thread
clock_gettime monotonic: 118.25ms per thread
clock_gettime cpu time: 2975.75ms per thread
rdtsc: 10.25ms per thread

從結果來看,當從多個線程中調用std::chrono時,其開銷很小,隨着線程數的增加, gettimeofday方法保持穩定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM