2017-09-15 55 views
1

我試圖用gperftools分析多線程工作負載,但是難以解釋產生的輸出。我寫了一個簡單的程序,啓動兩個工作負載相同的線程,並使用gperftools cpu profiler進行配置。在輸出中,我可以看到每個線程的兩個函數,但是每個線程的開銷在一次運行和下一次運行之間會有很大的不同。我希望這兩個函數都顯示相同的結果,因爲它們是相同的工作負載,但實際上,其中一個可能是90%,另一個是10%,有時是80%/ 20%,95%/ 5%等等。理解爲什麼這些函數顯示不同的開銷,或者爲什麼結果從一次運行到另一次運行會發生很大變化。該基準運行約5秒鐘,並有1600個樣本,因此應該穩定。在多線程工作負載上解釋gperftools的結果

是否有任何文檔解釋了多線程工作負載分析的工作原理以及如何解釋輸出?例如,剖析器是否對每個樣本的每個線程進行回溯,如果不是,那麼它在做什麼?

#include <vector> 
#include <cstdlib> 
#include <thread> 
using namespace std; 

void thread_func() { 
    int size = 500000; 
    vector<int> V(size); 
    for(int i = 0; i < 100000; i++) { 
     V.erase(V.begin() + (rand() % size)); 
     V.insert(V.begin() + (rand() % size), rand() % 10); 
    } 
} 

void thread_func2() { 
    int size = 500000; 
    vector<int> V(size); 
    for(int i = 0; i < 100000; i++) { 
     V.erase(V.begin() + (rand() % size)); 
     V.insert(V.begin() + (rand() % size), rand() % 10); 
    } 
} 

int main() { 
    srand(1234); 
    thread t1(thread_func); 
    thread t2(thread_func2); 
    t1.join(); 
    t2.join(); 
    return 0; 
} 

輸出示例:

0 0.0% 100.0%  1429 89.3% thread_func 
0 0.0% 100.0%  172 10.7% thread_func2 

凡和10.7%來自的89.3%? (這些是總樣本的在功能和它的被調用者的百分比)

Image contains a portion of the graph, numbers are slightly different from above because it's a different run

+0

這些列在你的輸出中意味着什麼?我認爲這是特別有用的知道列不同。另外,如果您想更多地看到結果,它可能已經有所瞭解。 – hakre

+0

有趣的列是第4和第5:此函數及其被調用者中的樣本數,此函數及其被調用者中總樣本的百分比。前兩列與列出的函數中的樣本相關,第三列是迄今爲止在輸出中輸出的所有函數的累計百分比。 –

+0

我想我想知道的是,對於每個樣本,是分析器對每個樣本進行回溯運行線程?如果不是,它在做什麼? –

回答

1

這被稱爲與SIGPROF信號遞送問題。有關詳細信息,請參閱https://github.com/golang/go/issues/14434

Gperftools實際上已經「修復」了歪斜(就像在這個問題上提到的那樣)。您只需設置CPUPROFILE_PER_THREAD_TIMERS = t並確保librt和libpthread已鏈接。你還需要「註冊」你的線程或LD_PRELOAD https://github.com/alk/gperf-all-threads

+0

這是一個很好的答案,謝謝你的幫助。 –

+0

@Aliaksei Kandratsenka,謝謝你的回答。我有一個後續問題,我不確定它是否值得單獨發佈:在打開gperftools的多線程支持的情況下,如何分別輸出每個線程的性能分析結果?通過您的設置,我認爲所有結果都收集在CPUPROFILE指定的單個輸出文件中。 –

+0

無法跟蹤線程特定的配置文件。只有特定的線程子集才能提供簡單的支持。請參閱ProfileOptions結構。分析特定線程偶爾會非常有用。 –