2012-10-19 27 views
4

我用linux perf來分析我的程序,我無法理解結果。「採樣」在perf輸出中意味着什麼?

 
10.5% 2  fun  .......... 
     | 
     |- 80% - ABC 
     |  call_ABC 
     -- 20% - DEF 
       call_DEF 

上面的例子是指 '樂' 具有兩個樣品,並有助於10.5%的開銷,

和其中的80%是從ABC稱爲,20%從DEF。我對嗎?

現在我們只有兩個樣本,那麼'perf'如何計算ABC和DEF的分數?

他們爲什麼不是50%?劑量'perf'使用額外信息?

+1

你能否提供你用來執行perf的語法/選項? – csj

回答

0

上面的例子是指 '樂' 具有兩個樣品,並有助於10.5%的開銷,

是的,perf report -g -n這部分顯示,2 19的樣本(2 19 10.5%)爲在foo函數本身。其他17個樣本採樣。

我剛剛使用最近的gcc(-static -O3 -fno-inline -fno-omit-frame-pointer -g)和perf(對於低分辨率採樣爲perf record -e cycles:u -c 500000 -g ./test12968422或對於高分辨率爲-c 5000)複製了您的代碼。現在perf有點不同的重量規則,但想法應該是一樣的。如果程序只有兩個樣本,並且兩個都在foo中,call_DEF/_ABC(沒有附加信息)的調用圖(perf report -n -g callee)爲50。這個方案實際上有foo中運行時的86%,其中61%來自ABC調用時,86 25%,從DEF調用時:

100% 2 fun 
- fun 
    + 50% call_DEF 
    + 50% call_ABC 

什麼樣的附加信息PERF可以用來重建的更多信息?我認爲它可以是call_DEF和call_ABC的自重;或者它可以是所有樣本調用堆棧中callchain部分的「call_ABC-> foo」和「call_DEF-> foo」部分的頻率。

從linux內核版本4.4/4.10開始,我無法重現您的情況。我在call_ABC和call_DEF中添加了不同數量的自我工作。他們兩個都只是打電話給foo進行固定的工作量。現在我有19個樣品的-e cycles:u -c 54000 -g,13 call_ABC,2 call_DEF,2爲了好玩(和2在一些隨機函數):

Children Self Samples Symbol 
     74% 68%  13 [.] call_ABC 
     16% 10.5%  2 [.] call_DEF 
    10.5% 10.5%  2 [.] fun 
    - fun 
     + 5.26% call_ABC 
     + 5.26% call_DEF 

所以,儘量PERF的新版本,而不是3.2版本的Linux內核時代。

首先fun唯一的工作來源,從ABC和DEF調用時不相等的股份:在有趣的ABC和DEF不相等的工作,等於小的工作

#define g 100000 
int a[2+g]; 

void fill_a(){ 
    a[0]=0; 
    for(int f=0;f<g;f++) 
     a[f+1]=f; 
} 

int fun(int b) 
{ 
    while(a[b]) 
     b=a[b]; 
    return b; 
} 

int call_ABC(int b) 
{ 
    int d = b; 
    b = fun(d); 
    return d-b; 
} 

int call_DEF(int b) 
{ 
    int e = b; 
    b = fun(e); 
    return e+b; 
} 

int main() 
{ 
    int c,d; 
    fill_a(); 
    c=call_ABC(100000); 
    c=call_DEF(45000); 
    return c+d; 
} 

第二個來源:

#define g 100000 
int a[2+g]; 

void fill_a(){ 
    a[0]=0; 
    for(int f=0;f<g;f++) 
     a[f+1]=f; 
} 

int fun(int b) 
{ 
    while(a[b]) 
     b=a[b]; 
    return b; 
} 

int call_ABC(int b) 
{ 
    int d = b; 
    while(a[d]) 
     d=a[d]; 
    b = fun(5000); 
    return d-b; 
} 

int call_DEF(int b) 
{ 
    int e = b; 
    while(a[e]) 
     e=a[e]; 
    b = fun(5000); 
    return e+b; 
} 

int main() 
{ 
    int c,d; 
    fill_a(); 
    c=call_ABC(100000); 
    c=call_DEF(20000); 
    return c+d; 
}