CS140 Lab 11 - Profiling

Objective

  • Learn about profiling tools.
  • Use gprof to profile a sample program.
  • Optimize a program after profiling.

Background

Optimization material is from Chapter 5 and 12 in CS:APP textbook.
See also: Optimization slides, Cache Optimization.

gprof - the GNU Profiler.

Required Tasks

  1. Log into your Linux account on one of the CS machines.
  2. Create a directory for your lab11 experiments.

How to use gprof

Using the gprof tool is not at all complex. You just need to do the following on a high-level:

  • Have profiling enabled while compiling the code
  • Execute the program code to produce the profiling data
  • Run the gprof tool on the profiling data file (generated in the step above).

The last step above produces an analysis file which is in human readable form. This file contains a couple of tables (flat profile and call graph) in addition to some other information. While flat profile gives an overview of the timing information of the functions like time consumption for the execution of a particular function, how many times it was called etc. On the other hand, call graph focuses on each function like the functions through which a particular function was called, what all functions were called from within this particular function etc So this way one can get idea of the execution time spent in the sub-routines too.

Lets try and understand the three steps listed above through a practical example. Following test code will be used throughout the article :

//test_gprof.c
#include<stdio.h>

void new_func1(void);

void func1(void)
{
    printf("\n Inside func1 \n");
    int i = 0;

    for(;i<0xffffffff;i++);
    new_func1();

    return;
}

static void func2(void)
{
    printf("\n Inside func2 \n");
    int i = 0;

    for(;i<0xffffffaa;i++);
    return;
}

int main(void)
{
    printf("\n Inside main()\n");
    int i = 0;

    for(;i<0xffffff;i++);
    func1();
    func2();

    return 0;
}

Second file:

//test_gprof_new.c
#include<stdio.h>

void new_func1(void)
{
    printf("\n Inside new_func1()\n");
    int i = 0;

    for(;i<0xffffffee;i++);

    return;
}

Note that the ‘for’ loops inside the functions are there to consume some execution time.

Step-1 : Profiling enabled while compilation

In this first step, we need to make sure that the profiling is enabled when the compilation of the code is done. This is made possible by adding the ‘-pg’ option in the compilation step.

From the man page of gcc :

-pg : Generate extra code to write profile information suitable for the analysis program gprof. You must use this option when compiling the source files you want data about, and you must also use it when linking.

So, lets compile our code with ‘-pg’ option :

$ gcc -Wall -pg test_gprof.c test_gprof_new.c -o test_gprof
$

Please note : The option ‘-pg’ can be used with the gcc command that compiles (-c option), gcc command that links(-o option on object files) and with gcc command that does the both(as in example above).

Step-2 : Execute the code

In the second step, the binary file produced as a result of step-1 (above) is executed so that profiling information can be generated.

$ ls
test_gprof  test_gprof.c  test_gprof_new.c

$ ./test_gprof 

 Inside main()

 Inside func1 

 Inside new_func1()

 Inside func2 

$ ls
gmon.out  test_gprof  test_gprof.c  test_gprof_new.c

$

So we see that when the binary was executed, a new file ‘gmon.out’ is generated in the current working directory.

Note that while execution if the program changes the current working directory (using chdir) then gmon.out will be produced in the new current working directory. Also, your program needs to have sufficient permissions for gmon.out to be created in current working directory.

Step-3 : Run the gprof tool

In this step, the gprof tool is run with the executable name and the above generated ‘gmon.out’ as argument. This produces an analysis file which contains all the desired profiling information.

$  gprof test_gprof gmon.out > analysis.txt

Note that one can explicitly specify the output file (like in example above) or the information is produced on stdout.

$ ls
analysis.txt  gmon.out  test_gprof  test_gprof.c  test_gprof_new.c

So we see that a file named ‘analysis.txt’ was generated.

Comprehending the profiling information

As produced above, all the profiling information is now present in ‘analysis.txt’.

Lets have a look at this text file.

So (as already discussed) we see that this file is broadly divided into two parts :

1. Flat profile
2. Call graph

The individual columns for the (flat profile as well as call graph) are very well explained in the output itself.

Customize gprof output using flags

There are various flags available to customize the output of the gprof tool. Some of them are discussed below:

1. Suppress the printing of statically(private) declared functions using -a

If there are some static functions whose profiling information you do not require then this can be achieved using -a option :

$ gprof -a test_gprof gmon.out > analysis.txt

Now examine that analysis file

So we see that there is no information related to func2 (which is defined static)

2. Suppress verbose blurbs using -b

As you would have already seen that gprof produces output with lot of verbose information so in case this information is not required then this can be achieved using the -b flag.

$ gprof -b test_gprof gmon.out > analysis.txt

Now examine the analysis file.

So we see that all the verbose information is not present in the analysis file.

3. Print only flat profile using -p

In case only flat profile is required then :

$ gprof -p -b test_gprof gmon.out > analysis.txt

Note that I have used(and will be using) -b option so as to avoid extra information in analysis output.

Now see that analysis output.

So we see that only flat profile was there in the output.

4. Print information related to specific function in flat profile

This can be achieved by providing the function name along with the -p option:

$ gprof -pfunc1 -b test_gprof gmon.out > analysis.txt

Now if we see that analysis output.

So we see that a flat profile containing information related to only function func1 is displayed.

5. Suppress flat profile in output using -P

If flat profile is not required then it can be suppressed using the -P option :

$ gprof -P -b test_gprof gmon.out > analysis.txt

Now see the analysis output

So we see that flat profile was suppressed and only call graph was displayed in output.

Also, if there is a requirement to print flat profile but excluding a particular function then this is also possible using -P flag by passing the function name (to exclude) along with it.

$ gprof -Pfunc1 -b test_gprof gmon.out > analysis.txt

In the above example, we tried to exclude ‘func1′ by passing it along with the -P option to gprof.

Now lets see the analysis output.

So we see that flat profile was displayed but information on func1 was suppressed.

6. Print only call graph information using -q

gprof -q -b test_gprof gmon.out > analysis.txt

In the example above, the option -q was used. Lets see what effect it casts on analysis output.

So we see that only call graph was printed in the output.

7. Print only specific function information in call graph.

This is possible by passing the function name along with the -q option.

$ gprof -qfunc1 -b test_gprof gmon.out > analysis.txt

Now check the analysis output.

So we see that information related to only func1 was displayed in call graph.

8. Suppress call graph using -Q

If the call graph information is not required in the analysis output then -Q option can be used.

$ gprof -Q -b test_gprof gmon.out > analysis.txt

Now see the analysis output.

So we see that only flat profile is there in the output. The whole call graph got suppressed.

Also, if it is desired to suppress a specific function from call graph then this can be achieved by passing the desired function name along with the -Q option to the gprof tool.

$ gprof -Qfunc1 -b test_gprof gmon.out > analysis.txt

In the above example, the function name func1 is passed to the -Q option.

Now check the analysis output.

So we see that call graph information related to func1 was suppressed.

Line-by-line profiling

Use this page to figure out line-by-line profiling: gprof line-by-line profiling

Profile this code and a modified version of swapping the order of the lines:




#define N 200
char stuff[N][N];


int main(int argc, char **argv) {


    int i,j;
    int sum = 0.0;
    for(i=0; i<N; i++) {
        for(j=0; j<N; j++) {
            sum+= stuff[i][j];
        }
    }


    printf("The sum is %d", sum);

}

Lab Submission



Submit your analysis output as a text file or pdf on gradescope containing: This submission is due by the end of the lab session.