-
Notifications
You must be signed in to change notification settings - Fork 2
Example: Argument Passing
This is simple introductory tutorial using Callgrind and CGV to profile a c++ binary.
It assumes you have built CGV, and have installed valgrind, and a modern C++ compiler. If you haven't done this yet checkout the getting started page.
Navigate to the example directory, and run make. It's a two-liner so feel free to change out g++ for your compiler of choice...
# Build the example
>>> make
g++-4.8.2 -g -O3 -march=native -o sums -std=c++11 main.cpp sums.cpp
# Collect the callgrind data
>>> ../../gather.sh ./sums
==10214== Callgrind, a call-graph generating cache profiler
==10214== Copyright (C) 2002-2012, and GNU GPL'd, by Josef Weidendorfer et al.
==10214== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==10214== Command: ./sums
==10214==
==10214== For interactive control, run 'callgrind_control -h'.
==10214==
==10214== Events : Ir
==10214== Collected : 1327625
==10214==
==10214== I refs: 1,327,625
# Start CGV
>>> ../../profile gather.out
Building call graph...done
Process started up in 5 mili-seconds
|ROOT>
By default we're placed into the ROOT (just above main) node. If you run the 'tree' command from here you can see you entire program branch out.
|ROOT> tree 2
ROOT
Calls: 0, Time: 0, Av. Time: 0
main
Calls: 1, Time: 62951, Av. Time: 62951
vector(int const&, int const&, int const&, int const&, int const&)
Calls: 1, Time: 62743, Av. Time: 62743
c_style(int const&, int const&, int const&, int const&, int const&)
Calls: 1, Time: 85, Av. Time: 85
initializer(int const&, int const&, int const&, int const&, int const&)
Calls: 1, Time: 39, Av. Time: 39
array(int const&, int const&, int const&, int const&, int const&)
Calls: 1, Time: 11, Av. Time: 11
templ(int const&, int const&, int const&, int const&, int const&)
Calls: 1, Time: 6, Av. Time: 6
basic(int const&, int const&, int const&, int const&, int const&)
Calls: 1, Time: 6, Av. Time: 6
|ROOT>
In the interests of space, I've limited the maximum depth of the graph in the above example to 2.
We want a function which takes a variable number of arguments (let's say ints) and returns their sum. We will use this hard-coded function has a benchmark.
|ROOT> searchchildren basic
--> main/basic(int const&, int const&, int const&, int const&, int const&) : 6.000000e+00 / 1 (6)
There are 0 more results
|basic> annotate
10: ( 0%): int sum(const int& i1,
11: ( 0%): const int& i2,
12: ( 0%): const int& i3,
13: ( 0%): const int& i4,
14: ( 0%): const int& i5)
15: ( 0%): {
16: 5 !83%!: return i1 + i2 + i3 + i4 + i5;
17: ( 0%): }
18: ( 0%):
19: ( 0%): int basic(const int& i1,
20: ( 0%): const int& i2,
21: ( 0%): const int& i3,
22: ( 0%): const int& i4,
23: ( 0%): const int& i5)
24: ( 0%): {
25: ( 0%): return sum(i1,i2,i3,i4,i5);
26: 1 (16%): }
I'm using a release binary ( g++ -g -O3 -march=native main.cpp sums.cpp). In the interest of fairness, each function is called from an outer function with identical signatures.
The example code is provided in the CGV source.
While c didn't support it function overloading, it did bequeath C++ the var_arg method variable argument functions:
/**************************************
* c-style var args: 85 Reads (x14.1)
*************************************/
int varsum(const int& n, ...)
{
va_list vl;
va_start(vl,n);
int s = 0;
for ( int i = 0; i< n; ++i) {
s += va_arg(vl,int);
}
va_end(vl);
return s;
}
The va_* functions are actually just clever macros which allow the function to pull as many arguments as it likes off the stack.