2011-01-11 265 views
21

我正在使用Linux安全模塊鉤子爲recv()系統調用添加一些自定義功能。與原始recv()相比,我想測量此功能的開銷。我寫了一個簡單的tcp服務器,我運行並沒有我的模塊。這個tcp服務器調用一個recv()函數'N'次。它測量與像對各時間的recv:測量Linux內核中函數的執行時間

clock_gettime(before); 
recv() 
clock_gettime(after); 
global_time += after - before. 

最後,我打印的平均時間爲單個的recv()中包含「global_time/N」。這段時間稱爲「user_space_avg_recv」時間。

在我的模塊內部,我想要放置時間測量函數來計算我的鉤子的準確執行時間。我嘗試了3種方法。

  1. 我用的jiffies如下:

    sj = jiffies; 
    my_hook(); 
    ej = jiffies; 
    current->total_oh = ej - sj; 
    

    但我看到有SJ和EJ值之間沒有差別。因此total_oh不變。

  2. 我用current_kernel_time(),因爲我認爲它返回的時間以納秒爲單位。但是,再一次,前後沒有差別。

  3. 我用過get_cycles。當進程退出時,我會打印整個週期。不過,當我將總週期值轉換爲毫秒時,它會比「user_space_avg_recv」值大得多。這是沒有意義的,因爲內核中的測量值總是小於從用戶空間測量的時間值。這可能意味着我要麼不使用正確的API進行測量,要麼在將數值從週期轉換爲毫秒時出錯。

我基本上是用下面的公式週期轉換成毫秒:

avg overhead of my hook in milliseconds = 
      (((cycles/2.99)/10^6)/N) 

2.99,因爲我的時鐘頻率爲2.99Ghz

幾點:

  • 我的用戶空間程序使用集合關係綁定到單個核心。

  • 我使用的內核2.6.22.14

  • 要切換上下文,而我的鉤內停止的內核,我用preempt_disable()和preempt_enable()。因此它不會計算其他內核線程的執行時間。即使這樣,因爲我的鉤子使用了一些I/O,我的線程可能會自動釋放控制器,或者可能會發生一些可能會增加總週期數的中斷。

問題: 如何在內核中精確測量函數執行時間?

+0

嘗試禁用BIOS中的頻率更改並重新測量週期 – osgx 2011-01-11 08:47:35

回答

19

您可以使用function tracer API來獲取所有函數調用和返回的跟蹤,並使用高精度時間戳。這包括中斷事件和上下文切換。然後,您可以分析用戶空間中的結果軌跡,以準確瞭解您的函數運行多長時間。

如果您不能使用函數跟蹤器API,則可以調用do_gettimeofday()調用以獲得微秒級分辨率時間戳,或者在納秒級分辨率下獲得getnstimeofday()。這些是用戶空間gettimeofday()調用在內部使用的相同功能。當然,對於非常快速的功能,這可能不夠準確;任何更快的準確性,你可能需要深入計時器代碼,看看它如何實現週期轉換。還要注意,僅僅因爲它們具有高分辨率並不意味着它們具有那麼高的精度 - 但它們應該用於基準測試。

注意,任何形式的跟蹤將導致額外的延遲 - do_gettimeofday()需要大量的原子比較並交換操作,並且ftrace把日誌代碼上每一個功能前和終曲。解釋結果時應考慮到這一點。

+0

是不是寫爲2.6.28以上?我正在使用2.6.22.14。 – Methos 2011-01-11 09:00:01

+0

@Methos:用另一種方法更新。 – bdonlan 2011-01-11 09:30:37

+1

@bdonlan,感謝您的更新。但是,do_gettimeofday()從內部讀取「xtime」中的值。在number-2中提到的current_kernel_time()函數也是相同的(它在同一個文件kernel/time.c中)。正如我在第二點中所說的,我沒有看到我的鉤子之前和之後返回的值之間有任何時間差。 – Methos 2011-01-11 09:46:24

3

我不確定你會得到你想要的結果,但我們使用follwing代碼有微秒。

double Microsecs() 
{ 
    static struct timeval _t; 
    static struct timezone tz; 
    gettimeofday(&_t, &tz); 
    return (double)_t.tv_sec + (double)_t.tv_usec/(1000*1000); 
} 

比你打電話之前和之後你想要的電話,看看它有多少時間。
我們一直使用這種方法來評估IO時間監控讀/寫/查找操作,以優化性能,並且我們獲得了很好的結果。

HTH。

-1

您是否嘗試過使用OProfile?