2017-08-24 301 views
2

我使用的CentOS Linux的發佈英特爾1611年3月7日(R)至強(R)CPU E5-2667 V4 @ 3.20GHzclock_gettime可能會很慢,甚至使用VDSO

在我的用戶空間應用程序的測試,我已經注意到clock_gettime(CLOCK_MONOTONIC,&ts)可能需要5-6微秒而不是〜23納秒的平均值。每10000次隨後的呼叫可能只發生一次,但可能會發生。

如果沒有VDSO庫,可以解釋。但是,VDSO用於每個clock_gettime(我通過strace檢查)。

不管相應的線程是否貼在某個CPU核心上,或者沒有。無論如何,如果這個CPU內核與操作系統隔離,或者不是。這意味着測試應用程序可能運行在獨佔的CPU核心上,而滯後可能會出現!

我通過比較兩個相繼clock_gettime調用的結果測量延遲,如:

unsigned long long __gettimeLatencyNs() { 
    struct timespec t1_ts; 
    struct timespec t2_ts; 
    clock_gettime(CLOCK_MONOTONIC, &t1_ts); 
    clock_gettime(CLOCK_MONOTONIC, &t2_ts); 
    return ((t2_ts.tv_sec - t1_ts.tv_sec)*NANO_SECONDS_IN_SEC + t2_ts.tv_nsec - t1_ts.tv_nsec); 
} 

任何人都可以分享一些想法,這可能是錯在那裏?

回答

3

讓我們看看源代碼clock_gettime

/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */ 
notrace static int __always_inline do_realtime(struct timespec *ts) 
{ 
    unsigned long seq; 
    u64 ns; 
    int mode; 

    do { 
     seq = gtod_read_begin(gtod); 
     mode = gtod->vclock_mode; 
     ts->tv_sec = gtod->wall_time_sec; 
     ns = gtod->wall_time_snsec; 
     ns += vgetsns(&mode); 
     ns >>= gtod->shift; 
    } while (unlikely(gtod_read_retry(gtod, seq))); 

    ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns); 
    ts->tv_nsec = ns; 

    return mode; 
} 

我們在這裏看到的是,代碼的循環中運行。該循環用unlikely條件進行註釋。條件與這樣的事實有關,即代碼讀取有時更新的共享內存,並且在更新時,代碼需要等待更新完成。

然後,最有可能的答案是,你經常抓住clock_gettime,而相應的內核代碼正在更新其結構。發生這種情況時,代碼運行速度會明顯變慢。

+1

看起來,我們可能會遇到等待「內核正在更新內容」的情況,不僅在這樣的綜合測試中。如果內核僅僅需要幾微秒來更新內存,那就相當奇怪了...... –

相關問題