by Falcon of tinylab.org
2015/04/15
Reason
Source code analysis is a topic that programmers can not leave. Whether it is research open source projects, or usually do all kinds of transplant, development, can not avoid the deep interpretation of the source code.
工欲善其事, its prerequisite.
Previously described how to analyze the source code statically through CallGraph, here is how to analyze the actual function execution of the program runtime, taking into account that the application part and the kernel part of the relatively large differences, the first introduction to the application of the section.
The main introduction of three tools, one is gprof
, another is, another is valgrind
to be able to export the results of the first two as DOT graphics tool, called gprof2dot
, its function is somewhat similar to the last we introduced tree2dotx
.
Get ready
Several related tools need to be prepared beforehand.
Gprof2dot:converts the output from many profilers to a dot graph
$ sudo apt-get install python python-pip$ sudo pip install gprof2dot
Graphviz:dot format Processing
$ sudo apt-get install graphviz
Gprof:display Call Graph profile Data
$ sudo apt-get install gprof
VALGRIND:A suite of tools for debugging and profiling programs
$ sudo apt-get install valgrind
Tool OK, then a typical C program, save as: FIB.C
#include <stdio.h>int fibonacci(int n);int main(int argc, char **argv){ int fib; int n; for (n = 0; n <= 42; n++) { fib = fibonacci(n); printf("fibonnaci(%d) = %dn", n, fib); } return 0;}int fibonacci(int n){ int fib; if (n <= 0) { fib = 0; } else if (n == 1) { fib = 1; } else { fib = fibonacci(n -1) + fibonacci(n - 2); } return fib;}
Gprof
Gprof is used to analyze run-time code execution for an application.
It needs to compile the source code and -pg
then run:
$ gcc -pg -o fib fib.c$ ./fib
After running, a log file is generated:
$ ls gmon.outgmon.out
Can analyze it:
$ gprof -b ./fib | gprof2dot | dot -Tsvg -o fib-gprof.svg
See fib-gprof.svg
below:
It can be observed that this chart, in addition to calling relationships, has the number of executions and percentages of each function.
Valgrind s Callgrind
Valgrind is an open source performance analysis tool. It can be used not only to check for problems such as memory leaks, but also to generate call graphs for functions.
Valgrind does not depend on -pg
The compile option, it can be compiled and run directly:
$ gcc -o fib fib.c$ valgrind --tool=callgrind ./fib
You will then see a log file:
$ ls callgrind*callgrind.out.22737
Then use the gprof2dot
analysis:
$ gprof2dot -f callgrind ./callgrind.out.22737 | dot -Tsvg -o fib-callgrind.svg
See fib-callgrind.svg
below:
What needs to be mentioned is that Valgrind extracts more information than gprof, including the parent function of the main function.
However, Valgrind actually provides more information, with the -n0 -e0
implementation percent limit removed, all performed by the show:
$ gprof2dot -f callgrind -n0 -e0 ./callgrind.out.22737 | dot -Tsvg -o fib-callgrind-all.svg
The results are as follows:
All the invocation cases are shown. The hotspot call branch is marked out in red. Because there are actually a lot of other things behind the running of a program, such as dynamic symbolic links, as well as the main
actual code is called printf
, although the proportion is very low.
Considering the above results are too many, not easy to analyze, if you only want to care about the invocation of a function, main
as an example, you can:
$ gprof2dot -f callgrind -n0 -e0 ./callgrind.out.22737 --root=main | dot -Tsvg -o fib-callgrind-main.svg
What needs to be mentioned is that, in addition gprof2dot
, kcachegrind
it can be used to show Valgrind‘s callgrind
the data:
$ sudo apt-get install kcachegrind$ kcachegrind ./callgrind.out.22737
The File --> Export Graph
call graph can be exported by. Just one is a graphical tool, one is a command line, and kcachegrind
you can't show all the branches at once, but it's flexible to view nodes by node.
Summary
We show the actual execution path of the source code from the run-time perspective, and we are only going into the function hierarchy at this point.
The results are slightly different from the previous static analysis.
- When actually running, the number of calls to different branches varies, and even some branches may not execute at all. This data provides a hot spot for us to optimize performance.
- When actually running, we observe that in addition to the functions in the code, there are also
main
the parent functions, and even the internal invocation details of the library functions, printf
giving us a way to understand the details of the running behind the program.
This article simply introduces the application section (which is actually the user space at the time the program runs), and next time we will analyze what kernel interfaces (system calls) are invoked when an application executes, the execution of those interfaces, and the function calls that go deep into kernel space.
"Source Analysis" Dynamic analysis of C program function call relationship