我使用 linux perf 来分析我的程序,但我无法理解结果。
10.5% 2 乐趣....... | |- 80% - ABC | call_ABC -- 20% - 防御 call_DEF
上面的例子意味着 'fun' 有两个样本并贡献了 10.5% 的开销,
其中 80% 来自 ABC,20% 来自 DEF。我对吗?
现在我们只有两个样本,那么 'perf' 是如何计算 ABC 和 DEF 的分数的呢?
为什么他们不是 50%?剂量“性能”使用附加信息?
上面的例子意味着 '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;
}