上面的例子意味着 'fun' 有两个样本并贡献了 10.5% 的开销,
是的,这部分perf report -g -n显示 19 个样本中有 2 个(2 个是 19 个样本的 10.5%)在 foo 函数本身中。在其他功能中采样了其他 17 个样本。
-static -O3 -fno-inline -fno-omit-frame-pointer -g我刚刚使用最近的 gcc ( ) 和 perf复制了您的代码(perf record -e cycles:u -c 500000 -g ./test12968422用于低分辨率样本或-c 5000高分辨率)。现在 perf 有一些不同的重量规则,但想法应该是一样的。当程序只有 2 个样本并且两个样本都在 中时foo,调用图 ( perf report -n -g callee) 对于 call_DEF/_ABC 中的每一个都是 50(没有附加信息)。这个程序实际上有 86% 的运行时在 foo 中,其中 61% 是从 ABC 调用时,25% 是从 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 的性能,我无法重现您的情况。我在 call_ABC 和 call_DEF 中添加了不同数量的自我工作。他们都只是调用 foo 来完成固定的工作量。现在我有 19 个样本-e cycles:u -c 54000 -g,call_ABC 有 13 个,call_DEF 有 2 个,乐趣有 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 调用时分配不均:
#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;
}