Q:

perf top result about nested functions

We are using perf top to show the CPU usage. The result shows two functions 
samples    pcnt    function
------     ----    ---------
...        ...     ....
12617.00   6.8%    func_outside
 8691.00   4.7%    func_inside
.....

In fact, these two functions are nested like this, and always 1 to 1 nested.
func_outside() {
  ....
  func_inside() 
  ... 
}

Should I conclude that in the perf top result, the 4.7% is actually already included in the 6.8%. And if excluding the cost of func_inside, the func_outside cost 2.1% (6.8-4.7)? 

A:

Short Answer
No each percentage that is reported is for that specific function only.  So the func_inside samples are not counted in func_outside
Details
The way perf works is that it periodically collects performance samples.  By default perf top simply checks which function is currently running and then adds that to the sample count for this function.
I was pretty sure this is the case, but wanted to verify that this is how perf top displays the results so I wrote a quick test program to test its behavior.  This program has two functions of interest outer and inner.  The outer function calls inner in a loop, and the amount of work that inner does is controlled by an argument. When compiling be sure to use O0 to avoid inlining.  The command line arguments control the ratio of work between the two functions.
Running with parameters ./a.out 1 1 1000000000 gives results:
49.20%  a.out             [.] outer    
23.69%  a.out             [.] main    
21.32%  a.out             [.] inner    

Running with parameters ./a.out 1 10 1000000000 gives results:
66.06%  a.out             [.] inner    
17.77%  a.out             [.] outer    
 9.50%  a.out             [.] main    

Running with parameters ./a.out 1 100 1000000000 gives results:
88.53%  a.out             [.] inner    
 2.85%  a.out             [.] outer    
 1.09%  a.out             [.] main    

If the count for inner was included in outer then the runtime percentage for outer would always be higher than inner.  But as these results show that is not the case.  
The test program I used is below and was compiled with gcc -O0 -g --std=c11 test.c.
#include <stdlib.h>
#include <stdio.h>

long inner(int count) {
  long sum = 0;
  for(int i = 0; i < count; i++) {
    sum += i;
  }
  return sum;

}

long outer(int count_out, int count_in) {
  long sum = 0;
  for(int i = 0; i < count_out; i++) {
    sum += inner(count_in);
  }
  return sum;
}

int main(int argc, char **argv)  {
  if(argc < 4) {
    printf("Usage: %s <outer_cnt> <inner_cnt> <loop>\n",argv[0]);
    exit(-1);
  }

  int outer_cnt = atoi(argv[1]);
  int inner_cnt = atoi(argv[2]);
  int loops     = atoi(argv[3]);

  long res = 0;
  for(int i = 0; i < loops; i++) {
    res += outer(outer_cnt, inner_cnt);
  }

  printf("res is %ld\n", res);
  return 0;
}

