我使用linux perf来分析我的程序,我无法理解结果。
10.5% 2 fun .......... | |- 80% - ABC | call_ABC -- 20% - DEF call_DEF
上面的例子意味着'fun'有两个样本并且贡献了10.5%的开销,
其中80%来自ABC,20%来自DEF。我是对的吗?
现在我们只有两个样本,那么'perf'如何计算ABC和DEF的分数?
他们为什么不是50%?剂量'perf'使用其他信息?
答案 0 :(得分:0)
上面的例子意味着'fun'有两个样本并且贡献了10.5%的开销,
是的,perf report -g -n
的这一部分显示19个样本中的2个(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有不同的权重规则,但想法应该是相同的。如果程序只有2个样本且两者都在foo
中,则call_DEF / _ABC(无附加信息)中的每一个的调用图(perf report -n -g callee
)都为50。这个程序在foo中实际上有86%的运行时间,从ABC调用时有61%,从DEF调用时有86%:
100% 2 fun
- fun
+ 50% call_DEF
+ 50% call_ABC
perf可用于重建更多信息的附加信息有哪些?我认为它可以是call_DEF和call_ABC的自重;或者它可以是所有样本调用堆栈中调用链的“call_ABC-> foo”和“call_DEF-> foo”部分的频率。
使用来自Linux内核版本4.4 / 4.10的perf我无法重现你的情况。我在call_ABC和call_DEF中添加了不同数量的自我工作。他们两个只是调用foo来完成固定的工作量。现在我有19个-e cycles:u -c 54000 -g
个样本,13个用于call_ABC,2个用于call_DEF,2个用于fun(以及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调用不等份:
#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;
}
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;
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;
}