]>
Commit | Line | Data |
---|---|---|
2adccceb MK |
1 | .\" Copyright (C) 2014 Michael Kerrisk <mtk.manpages@gmail.com> |
2 | .\" | |
5fbde956 | 3 | .\" SPDX-License-Identifier: Linux-man-pages-copyleft |
2adccceb | 4 | .\" |
45186a5d | 5 | .TH SPROF 1 2020-11-01 "Linux man-pages (unreleased)" |
2adccceb MK |
6 | .SH NAME |
7 | sprof \- read and display shared object profiling data | |
8 | .SH SYNOPSIS | |
9 | .nf | |
4c9b3247 MK |
10 | .BR sprof " [\fIoption\fP]... \fIshared-object-path\fP \ |
11 | [\fIprofile-data-path\fP]" | |
2adccceb MK |
12 | .fi |
13 | .SH DESCRIPTION | |
14 | The | |
15 | .B sprof | |
16 | command displays a profiling summary for the | |
43151de3 | 17 | shared object (shared library) specified as its first command-line argument. |
2adccceb MK |
18 | The profiling summary is created using previously generated |
19 | profiling data in the (optional) second command-line argument. | |
20 | If the profiling data pathname is omitted, then | |
21 | .B sprof | |
22 | will attempt to deduce it using the soname of the shared object, | |
23 | looking for a file with the name | |
a28b73cd | 24 | .I <soname>.profile |
2adccceb MK |
25 | in the current directory. |
26 | .SH OPTIONS | |
27 | The following command-line options specify the profile output | |
28 | to be produced: | |
29 | .TP | |
30 | .BR \-c ", " \-\-call\-pairs | |
31 | Print a list of pairs of call paths for the interfaces exported | |
32 | by the shared object, | |
33 | along with the number of times each path is used. | |
34 | .TP | |
35 | .BR \-p ", " \-\-flat\-profile | |
36 | Generate a flat profile of all of the functions in the monitored object, | |
37 | with counts and ticks. | |
38 | .TP | |
39 | .BR \-q ", " \-\-graph | |
40 | Generate a call graph. | |
41 | .PP | |
42 | If none of the above options is specified, | |
43 | then the default behavior is to display a flat profile and a call graph. | |
44 | .PP | |
45 | The following additional command-line options are available: | |
46 | .TP | |
47 | .BR \-? ", " \-\-help | |
48 | Display a summary of command-line options and arguments and exit. | |
49 | .TP | |
a28b73cd | 50 | .B \-\-usage |
2adccceb MK |
51 | Display a short usage message and exit. |
52 | .TP | |
53 | .BR \-V ", " \-\-version | |
54 | Display the program version and exit. | |
3113c7f3 | 55 | .SH STANDARDS |
2adccceb MK |
56 | The |
57 | .B sprof | |
58 | command is a GNU extension, not present in POSIX.1. | |
a14af333 | 59 | .SH EXAMPLES |
2adccceb MK |
60 | The following example demonstrates the use of |
61 | .BR sprof . | |
62 | The example consists of a main program that calls two functions | |
43151de3 | 63 | in a shared object. |
2adccceb | 64 | First, the code of the main program: |
2a86152e | 65 | .PP |
2adccceb | 66 | .in +4n |
60d3774e | 67 | .EX |
2adccceb MK |
68 | $ \fBcat prog.c\fP |
69 | #include <stdlib.h> | |
70 | ||
71 | void x1(void); | |
72 | void x2(void); | |
73 | ||
74 | int | |
75 | main(int argc, char *argv[]) | |
76 | { | |
77 | x1(); | |
78 | x2(); | |
79 | exit(EXIT_SUCCESS); | |
80 | } | |
60d3774e | 81 | .EE |
2adccceb MK |
82 | .in |
83 | .PP | |
84 | The functions | |
a28b73cd | 85 | .IR x1 () |
2adccceb | 86 | and |
a28b73cd | 87 | .IR x2 () |
2adccceb | 88 | are defined in the following source file that is used to |
43151de3 | 89 | construct the shared object: |
2a86152e | 90 | .PP |
2adccceb | 91 | .in +4n |
60d3774e | 92 | .EX |
2adccceb MK |
93 | $ \fBcat libdemo.c\fP |
94 | #include <unistd.h> | |
95 | ||
96 | void | |
97 | consumeCpu1(int lim) | |
98 | { | |
88893a77 | 99 | for (int j = 0; j < lim; j++) |
2adccceb MK |
100 | getppid(); |
101 | } | |
102 | ||
103 | void | |
104 | x1(void) { | |
88893a77 | 105 | for (int j = 0; j < 100; j++) |
2adccceb MK |
106 | consumeCpu1(200000); |
107 | } | |
108 | ||
109 | void | |
110 | consumeCpu2(int lim) | |
111 | { | |
88893a77 | 112 | for (int j = 0; j < lim; j++) |
2adccceb MK |
113 | getppid(); |
114 | } | |
115 | ||
116 | void | |
117 | x2(void) | |
118 | { | |
88893a77 | 119 | for (int j = 0; j < 1000; j++) |
2adccceb MK |
120 | consumeCpu2(10000); |
121 | } | |
60d3774e | 122 | .EE |
2adccceb MK |
123 | .in |
124 | .PP | |
43151de3 | 125 | Now we construct the shared object with the real name |
2adccceb MK |
126 | .IR libdemo.so.1.0.1 , |
127 | and the soname | |
128 | .IR libdemo.so.1 : | |
2a86152e | 129 | .PP |
2adccceb | 130 | .in +4n |
60d3774e | 131 | .EX |
2adccceb MK |
132 | $ \fBcc \-g \-fPIC \-shared \-Wl,\-soname,libdemo.so.1 \e\fP |
133 | \fB\-o libdemo.so.1.0.1 libdemo.c\fP | |
60d3774e | 134 | .EE |
2adccceb MK |
135 | .in |
136 | .PP | |
137 | Then we construct symbolic links for the library soname and | |
138 | the library linker name: | |
2a86152e | 139 | .PP |
2adccceb | 140 | .in +4n |
60d3774e | 141 | .EX |
2adccceb MK |
142 | $ \fBln \-sf libdemo.so.1.0.1 libdemo.so.1\fP |
143 | $ \fBln \-sf libdemo.so.1 libdemo.so\fP | |
60d3774e | 144 | .EE |
2adccceb MK |
145 | .in |
146 | .PP | |
43151de3 | 147 | Next, we compile the main program, linking it against the shared object, |
2adccceb | 148 | and then list the dynamic dependencies of the program: |
2a86152e | 149 | .PP |
2adccceb | 150 | .in +4n |
60d3774e | 151 | .EX |
2adccceb MK |
152 | $ \fBcc \-g \-o prog prog.c \-L. \-ldemo\fP |
153 | $ \fBldd prog\fP | |
154 | linux\-vdso.so.1 => (0x00007fff86d66000) | |
155 | libdemo.so.1 => not found | |
156 | libc.so.6 => /lib64/libc.so.6 (0x00007fd4dc138000) | |
157 | /lib64/ld\-linux\-x86\-64.so.2 (0x00007fd4dc51f000) | |
60d3774e | 158 | .EE |
2adccceb MK |
159 | .in |
160 | .PP | |
43151de3 | 161 | In order to get profiling information for the shared object, |
2adccceb | 162 | we define the environment variable |
a28b73cd | 163 | .B LD_PROFILE |
2adccceb | 164 | with the soname of the library: |
2a86152e | 165 | .PP |
2adccceb | 166 | .in +4n |
60d3774e | 167 | .EX |
2adccceb | 168 | $ \fBexport LD_PROFILE=libdemo.so.1\fP |
60d3774e | 169 | .EE |
2adccceb MK |
170 | .in |
171 | .PP | |
172 | We then define the environment variable | |
a28b73cd | 173 | .B LD_PROFILE_OUTPUT |
2adccceb MK |
174 | with the pathname of the directory where profile output should be written, |
175 | and create that directory if it does not exist already: | |
2a86152e | 176 | .PP |
2adccceb | 177 | .in +4n |
60d3774e | 178 | .EX |
2adccceb MK |
179 | $ \fBexport LD_PROFILE_OUTPUT=$(pwd)/prof_data\fP |
180 | $ \fBmkdir \-p $LD_PROFILE_OUTPUT\fP | |
60d3774e | 181 | .EE |
2adccceb MK |
182 | .in |
183 | .PP | |
184 | .B LD_PROFILE | |
185 | causes profiling output to be | |
186 | .I appended | |
187 | to the output file if it already exists, | |
188 | so we ensure that there is no preexisting profiling data: | |
2a86152e | 189 | .PP |
2adccceb | 190 | .in +4n |
60d3774e | 191 | .EX |
2adccceb | 192 | $ \fBrm \-f $LD_PROFILE_OUTPUT/$LD_PROFILE.profile\fP |
60d3774e | 193 | .EE |
2adccceb MK |
194 | .in |
195 | .PP | |
196 | We then run the program to produce the profiling output, | |
197 | which is written to a file in the directory specified in | |
198 | .BR LD_PROFILE_OUTPUT : | |
2a86152e | 199 | .PP |
2adccceb | 200 | .in +4n |
60d3774e | 201 | .EX |
2adccceb MK |
202 | $ \fBLD_LIBRARY_PATH=. ./prog\fP |
203 | $ \fBls prof_data\fP | |
204 | libdemo.so.1.profile | |
60d3774e | 205 | .EE |
2adccceb MK |
206 | .in |
207 | .PP | |
208 | We then use the | |
a28b73cd | 209 | .B sprof \-p |
2adccceb | 210 | option to generate a flat profile with counts and ticks: |
2a86152e | 211 | .PP |
2adccceb | 212 | .in +4n |
60d3774e | 213 | .EX |
2adccceb MK |
214 | $ \fBsprof \-p libdemo.so.1 $LD_PROFILE_OUTPUT/libdemo.so.1.profile\fP |
215 | Flat profile: | |
216 | ||
217 | Each sample counts as 0.01 seconds. | |
218 | % cumulative self self total | |
219 | time seconds seconds calls us/call us/call name | |
220 | 60.00 0.06 0.06 100 600.00 consumeCpu1 | |
221 | 40.00 0.10 0.04 1000 40.00 consumeCpu2 | |
222 | 0.00 0.10 0.00 1 0.00 x1 | |
223 | 0.00 0.10 0.00 1 0.00 x2 | |
60d3774e | 224 | .EE |
2adccceb MK |
225 | .in |
226 | .PP | |
227 | The | |
a28b73cd | 228 | .B sprof \-q |
2adccceb | 229 | option generates a call graph: |
2a86152e | 230 | .PP |
2adccceb | 231 | .in +4n |
60d3774e | 232 | .EX |
2adccceb MK |
233 | $ \fBsprof \-q libdemo.so.1 $LD_PROFILE_OUTPUT/libdemo.so.1.profile\fP |
234 | ||
235 | index % time self children called name | |
236 | ||
237 | 0.00 0.00 100/100 x1 [1] | |
238 | [0] 100.0 0.00 0.00 100 consumeCpu1 [0] | |
239 | \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- | |
240 | 0.00 0.00 1/1 <UNKNOWN> | |
241 | [1] 0.0 0.00 0.00 1 x1 [1] | |
242 | 0.00 0.00 100/100 consumeCpu1 [0] | |
243 | \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- | |
244 | 0.00 0.00 1000/1000 x2 [3] | |
245 | [2] 0.0 0.00 0.00 1000 consumeCpu2 [2] | |
246 | \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- | |
247 | 0.00 0.00 1/1 <UNKNOWN> | |
248 | [3] 0.0 0.00 0.00 1 x2 [3] | |
249 | 0.00 0.00 1000/1000 consumeCpu2 [2] | |
250 | \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\- | |
60d3774e | 251 | .EE |
2adccceb MK |
252 | .in |
253 | .PP | |
254 | Above and below, the "<UNKNOWN>" strings represent identifiers that | |
255 | are outside of the profiled object (in this example, these are instances of | |
256 | .IR main() ). | |
257 | .PP | |
258 | The | |
a28b73cd | 259 | .B sprof \-c |
2adccceb | 260 | option generates a list of call pairs and the number of their occurrences: |
2a86152e | 261 | .PP |
2adccceb | 262 | .in +4n |
60d3774e | 263 | .EX |
2adccceb MK |
264 | $ \fBsprof \-c libdemo.so.1 $LD_PROFILE_OUTPUT/libdemo.so.1.profile\fP |
265 | <UNKNOWN> x1 1 | |
266 | x1 consumeCpu1 100 | |
267 | <UNKNOWN> x2 1 | |
268 | x2 consumeCpu2 1000 | |
60d3774e | 269 | .EE |
2adccceb MK |
270 | .in |
271 | .SH SEE ALSO | |
272 | .BR gprof (1), | |
273 | .BR ldd (1), | |
274 | .BR ld.so (8) |