5

我使用 linux perf 来分析我的程序,但我无法理解结果。

10.5% 2 乐趣.......
      |
      |- 80% - ABC
      | call_ABC
      -- 20% - 防御
               call_DEF

上面的例子意味着 'fun' 有两个样本并贡献了 10.5% 的开销,

其中 80% 来自 ABC,20% 来自 DEF。我对吗?

现在我们只有两个样本,那么 'perf' 是如何计算 ABC 和 DEF 的分数的呢?

为什么他们不是 50%?剂量“性能”使用附加信息?

4

1 回答 1

0

上面的例子意味着 '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; 
}
于 2017-05-11T04:02:04.257 回答