“样本”在性能输出中意味着什么?

时间:2012-10-19 06:19:22

标签: profile sample perf

我使用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'使用其他信息?

1 个答案:

答案 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; 
}