The cost of Callgrind main () includes much less than 100%

I have profiled several very simple C ++ programs running on Linux. The inclusive cost of main () for all of them is far from 100%, something like 3.83%. Am I using callgrind correctly? I have the output of callgrind_annotate with --inclusive=yes inserted below.

A program is called a heap that sorts a simple heap. The team I use

 valgrind --tool=callgrind ./heap 

Then i type

 callgrind_annotate --inclusive=yes callgrind.out.25434 

Output:

 `-------------------------------------------------------------------------------- Profile data file 'callgrind.out.25434' (creator: callgrind-3.6.0) `-------------------------------------------------------------------------------- I1 cache: D1 cache: LL cache: Timerange: Basic block 0 - 361578 Trigger: Program termination Profiled target: ./heap (PID 25434, part 1) Events recorded: Ir Events shown: Ir Event sort order: Ir Thresholds: 99 Include dirs: User annotated: Auto-annotation: off `-------------------------------------------------------------------------------- Ir `-------------------------------------------------------------------------------- 2,552,558 PROGRAM TOTALS `-------------------------------------------------------------------------------- Ir file:function `-------------------------------------------------------------------------------- 2,552,558 ???:0x00000810 [/lib/ld-2.7.so] 2,515,793 ???:0x00000a60 [/lib/ld-2.7.so] 2,515,219 ???:0x00015270 [/lib/ld-2.7.so] 2,514,780 ???:0x000021e0 [/lib/ld-2.7.so] 2,456,164 ???:0x0000b2f0 [/lib/ld-2.7.so] 2,256,719 ???:0x00009e40 [/lib/ld-2.7.so] 1,702,371 ???:0x00009ac0 [/lib/ld-2.7.so] 657,883 ???:0x000098e0 [/lib/ld-2.7.so] 367,045 ???:0x00017040 [/lib/ld-2.7.so] 33,170 ???:0x080483e0 [/home/test/heap] 33,036 ???:0x0000ce60 [/lib/ld-2.7.so] 31,347 ???:0x0000e850 [/lib/ld-2.7.so] 30,706 ???:(below main) [/lib/libc-2.7.so] 30,071 ???:0x00008570 [/lib/ld-2.7.so] 27,954 ???:0x0000f500 [/lib/ld-2.7.so] 27,758 ???:0x0000ca30 [/lib/ld-2.7.so] 21,366 ???:0x0001767b [/lib/ld-2.7.so] 
+4
source share
1 answer

main() not the top function in the call graph. Glibc has a _start function that will call main() and also accept the return value from main . There is also (for dynamically linked programs = almost everything) an ELF interpreter, also known as a dynamic run-time linker: / lib / ld-linux.so (this name is used in linux, in other Unixes something like / lib /ld.so). Linker downloads and initializes all the dynamic libraries needed by the application; and it is called by the OS before _start .

What is done before main ? Downloading libraries (open library file, analyzing its header, mmap it, accepting code for a new location in memory = handling movements) and initializing them (both in a dynamic and statistically linked library, this is necessary, note that glibc = libc also a library), Each library can have code that will be launched immediately after loading the library ( __attribute__((constructor)) or non-trivial global object constructors). In addition, glibc can register some functions that will be launched after main (for example, via atexit() ; if main returns normally, they will be called by _start), and libraries can have destructor functions for global objects.

If your program uses threads, the top thread function 1 .. n will not be the main one (each thread can share the stack, and the chain of function calls from main is stored in thread stack 0).

In your example, we see / lib / ld - *. So, and this is a dynamic linker. Your application seems to be too short to be properly profiled, and it uses a large number of dynamic libraries.

+4
source

Source: https://habr.com/ru/post/1340028/


All Articles