2015-03-18 52 views
2

我有一個應用程序被編寫,測試和調試了一個版本爲2.6.x的小型Linux內核。我最近試圖將該項目遷移到基於Debian 3.2.x內核的發行版,並注意到性能下降。我做了一些原始基準測試,發現usleep()的時序差異,函數調用的差異&循環時序等。針對基於Linux 3.2.x和基於2.6.x的系統編譯的代碼之間的戲劇性時序差異

我不確定精確的2.6.x內核配置是什麼(例如,搶佔模型等),我還沒有能夠提取內核構建配置信息 - 我們只是將這個系統作爲我們用於嵌入式應用程序的圖像。對於3.2.x內核,我使用「搶先式內核」配置爲我們的處理器構建了一個優化配置,並刪除了大量完全不需要的可選模塊(像HAM無線設備驅動程序這樣的東西 - 這些東西完全合理地移除)。

我們的系統是一個接近實時的應用程序,它不具有硬實時的要求(我們只需要繼續填充計算數據一定緩衝它被消費之前,這是固定的速率完成,但是一個可控通過硬件,實際上我們的CPU負載在要求最苛刻的應用程序中保持在30%左右 - 我們有保持緩衝區填充的性能並儘可能地保留空間)。我們使用pthreads,pthread_cond_wait/broadcast等來緩衝狀態信號,控制線程同步等。

首先,介紹一下系統的一些前言。有與圖案許多輪詢線程:

while (threadRunning) 
{ 
    CheckSomeStuff(); 
    usleep(polling_interval); 
} 

而且與像圖案的其他線程:

while (threadRunning) 
{ 
    pthread_cond_wait(stuff_needed_condition, some_mutex); // wait on signal 
    doSomeStuffWhenNeeded(); 
} 

這就是說,我們都注意到在移植的應用程序微妙的時機相關的問題,和算法運行比基於2.6.x內核的系統「慢」很多。

這個簡單的指標是說明:

static volatile long g_foo; 

static void setfoo(long foo) 
{ 
    g_foo = foo; 
} 

static void printElapsed(struct timeval t1, struct timeval t2, const char* smsg) 
{ 
    double time_elapsed; 
    time_elapsed = (t2.tv_sec - t1.tv_sec)*1e6 + (t2.tv_usec-t1.tv_usec); 
    printf("%s elapsed: %.8f\n", smsg, time_elapsed); 
} 

static void benchmarks(long sleeptime) 
{ 
    long i; 

    double time_elapsed; 

    struct timeval t1, t2; 

    // test 1 
    gettimeofday(&t1, NULL); 
    for (i=0;i<sleeptime;i++) 
    { 
     usleep(1); 
    } 
    gettimeofday(&t2, NULL); 
    printElapsed(t1, t2, "Loop usleep(1)"); 

    // test 2 
    gettimeofday(&t1, NULL); 
    usleep(sleeptime); 
    gettimeofday(&t2, NULL); 
    printElapsed(t1, t2, "Single sleep"); 


    // test 3 
    gettimeofday(&t1, NULL); 
    usleep(1); 
    gettimeofday(&t2, NULL); 
    printElapsed(t1, t2, "Single 1us sleep"); 

    // test 4 
    gettimeofday(&t1, NULL); 
    gettimeofday(&t2, NULL); 
    printElapsed(t1, t2, "gettimeofday x 2"); 

    // test 5 
    gettimeofday(&t1, NULL); 
    for (i=0;i<n;i++) 
    { 
     setfoo(i); 
    } 
    gettimeofday(&t2, NULL); 
    printElapsed(t1, t2, "loop function call"); 
} 

以下是測試結果(是的,輸出小數位是愚蠢的,我知道):

Kernel 2.6.x trial 1: 
Loop usleep(1) elapsed: 6063979.00000000 
Single sleep elapsed: 100071.00000000 
Single 1us sleep elapsed: 63.00000000 
gettimeofday x 2 elapsed: 1.00000000 
loop function call elapsed: 267.00000000 

Kernel 2.6.x trial 2: 
Loop usleep(1) elapsed: 6059328.00000000 
Single sleep elapsed: 100070.00000000 
Single 1us sleep elapsed: 63.00000000 
gettimeofday x 2 elapsed: 0.00000000 
loop function call elapsed: 265.00000000 

Kernel 2.6.x trial 3: 
Loop usleep(1) elapsed: 6063762.00000000 
Single sleep elapsed: 100064.00000000 
Single 1us sleep elapsed: 63.00000000 
gettimeofday x 2 elapsed: 1.00000000 
loop function call elapsed: 266.00000000 


kernel 3.2.65 trial 1: 
Loop usleep(1) elapsed: 8944631.00000000 
Single sleep elapsed: 100106.00000000 
Single 1us sleep elapsed: 96.00000000 
gettimeofday x 2 elapsed: 2.00000000 
loop function call elapsed: 491.00000000 

kernel 3.2.65 trial 2: 
Loop usleep(1) elapsed: 8891191.00000000 
Single sleep elapsed: 100102.00000000 
Single 1us sleep elapsed: 94.00000000 
gettimeofday x 2 elapsed: 2.00000000 
loop function call elapsed: 396.00000000 

kernel 3.2.65 trial 3: 
Loop usleep(1) elapsed: 8962089.00000000 
Single sleep elapsed: 100171.00000000 
Single 1us sleep elapsed: 123.00000000 
gettimeofday x 2 elapsed: 2.00000000 
loop function call elapsed: 407.00000000 

有在walltime巨大的差異之間架起在使用內核2.6.x和內核3.2.x的Linux操作系統上,調用usleep(1)(對於3.2.x爲9秒,對於2.6.x爲6秒)的循環的100,000個循環。爲了記錄,我不認爲我們正在使用呼叫「usleep(1);」代碼庫中的任何地方(但是與任何巨大的應用程序相比,更糟糕的事情可能存在於這裏和那裏),但是這是行爲上的巨大差異。循環中也有很大的不同,它將靜態全局變量設置爲100,000次(3.2時爲400微秒,2.6時爲260微秒)。

我意識到從glibc到編譯器&設置到linux內核配置有多個混淆問題。 Stack Overflow希望得到一些關於從哪裏開始戳的指導。 如果你必須完成這個遷移,你會做什麼?你會考慮哪些因素來解決我們所看到的性能問題?

如需進一步信息,兩個分佈是:

的Puppy Linux - 2.6內核。35-7 SMP未知的內核配置(PREEMPT不過,我敢肯定) - 的glibc 2.6.1 - GCC 4.6.3

Debian的喘息7.7(精簡) - Linux的65年3月2日從定製的內核配置來源 - gcc 4.7.2 - glibc 2.13(Debian EGLIBC 2.13-38 + deb7u6)

+0

首先,您需要描述您是如何得出「算法運行速度慢很多」的結論。這對於某個人有任何決定接下來要看的地方的重要信息。其次,目前還不清楚你爲什麼要睡覺。這可能會或可能不會影響您的問題。這幾乎是一個微觀基準。你的問題聽起來更系統化,因此恕我直言,你應該從更廣泛的系統層面開始,而不是立即縮小到這樣的微觀層面。一旦你提供了更多關於你的「慢」意味着什麼的信息,也許有人可以給出更好的建議。 – kaylum 2015-03-18 22:08:32

+0

在「microbenchmarking」級別上,您將在2.6.x系統上看到100,000次迭代循環需要大約250毫秒,而在3.2.x系統上大約需要400毫秒(單線程進程,空閒系統,以最高優先級運行nicelevel)。 在宏觀層面上,我們看到涉及浮點運算的計算佔用了更多的walltime時間。線程調度在這裏是一個可能的罪魁禍首,但即使對於單線程測試過程,我們也看到相同的計算需要更多的掛鐘時間。 – Walter231 2015-03-19 22:32:10

回答

0

您已經更新了內核,編譯器和glibc版本。

不要做。一次更新一個東西,並測量效果。然後你會知道哪些更新實際上會導致你的問題(這可能不是內核)。

您應該只能更新內核,然後只更新舊系統上的glibc。

+0

這是一個合理的建議。我會以更具診斷性的方式來看待這個問題。 – Walter231 2015-03-23 23:28:04

相關問題