blob: 8ccd1f2330d10cb56045db1d671422c77defbe59 [file] [log] [blame]
Namhyung Kimea251d52012-09-03 11:53:06 +09001#include <math.h>
2
3#include "../util/hist.h"
4#include "../util/util.h"
5#include "../util/sort.h"
6
7
8/* hist period print (hpp) functions */
9static int hpp__header_overhead(struct perf_hpp *hpp)
10{
11 if (hpp->ptr)
12 return scnprintf(hpp->buf, hpp->size, "Baseline");
13 else
14 return scnprintf(hpp->buf, hpp->size, "Overhead");
15}
16
17static int hpp__width_overhead(struct perf_hpp *hpp __used)
18{
19 return 8;
20}
21
22static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
23{
24 double percent = 100.0 * he->period / hpp->total_period;
25
26 if (hpp->ptr) {
27 struct hists *old_hists = hpp->ptr;
28 u64 total_period = old_hists->stats.total_period;
29 u64 base_period = he->pair ? he->pair->period : 0;
30
31 if (total_period)
32 percent = 100.0 * base_period / total_period;
33 else
34 percent = 0.0;
35 }
36
37 return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%%", percent);
38}
39
40static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
41{
42 double percent = 100.0 * he->period / hpp->total_period;
43
44 if (hpp->ptr) {
45 struct hists *old_hists = hpp->ptr;
46 u64 total_period = old_hists->stats.total_period;
47 u64 base_period = he->pair ? he->pair->period : 0;
48
49 if (total_period)
50 percent = 100.0 * base_period / total_period;
51 else
52 percent = 0.0;
53 }
54
55 return scnprintf(hpp->buf, hpp->size, " %5.2f%%", percent);
56}
57
58static int hpp__header_overhead_sys(struct perf_hpp *hpp)
59{
60 return scnprintf(hpp->buf, hpp->size, " sys ");
61}
62
63static int hpp__width_overhead_sys(struct perf_hpp *hpp __used)
64{
65 return 6;
66}
67
68static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
69{
70 double percent = 100.0 * he->period_sys / hpp->total_period;
71 return percent_color_snprintf(hpp->buf, hpp->size, "%5.2f%%", percent);
72}
73
74static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
75{
76 double percent = 100.0 * he->period_sys / hpp->total_period;
77 return scnprintf(hpp->buf, hpp->size, "%5.2f%%", percent);
78}
79
80static int hpp__header_overhead_us(struct perf_hpp *hpp)
81{
82 return scnprintf(hpp->buf, hpp->size, " user ");
83}
84
85static int hpp__width_overhead_us(struct perf_hpp *hpp __used)
86{
87 return 6;
88}
89
90static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
91{
92 double percent = 100.0 * he->period_us / hpp->total_period;
93 return percent_color_snprintf(hpp->buf, hpp->size, "%5.2f%%", percent);
94}
95
96static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
97{
98 double percent = 100.0 * he->period_us / hpp->total_period;
99 return scnprintf(hpp->buf, hpp->size, "%5.2f%%", percent);
100}
101
102static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
103{
104 return scnprintf(hpp->buf, hpp->size, "guest sys");
105}
106
107static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __used)
108{
109 return 9;
110}
111
112static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
113 struct hist_entry *he)
114{
115 double percent = 100.0 * he->period_guest_sys / hpp->total_period;
116 return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%% ", percent);
117}
118
119static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
120 struct hist_entry *he)
121{
122 double percent = 100.0 * he->period_guest_sys / hpp->total_period;
123 return scnprintf(hpp->buf, hpp->size, " %5.2f%% ", percent);
124}
125
126static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
127{
128 return scnprintf(hpp->buf, hpp->size, "guest usr");
129}
130
131static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __used)
132{
133 return 9;
134}
135
136static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
137 struct hist_entry *he)
138{
139 double percent = 100.0 * he->period_guest_us / hpp->total_period;
140 return percent_color_snprintf(hpp->buf, hpp->size, " %5.2f%% ", percent);
141}
142
143static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
144 struct hist_entry *he)
145{
146 double percent = 100.0 * he->period_guest_us / hpp->total_period;
147 return scnprintf(hpp->buf, hpp->size, " %5.2f%% ", percent);
148}
149
150static int hpp__header_samples(struct perf_hpp *hpp)
151{
152 return scnprintf(hpp->buf, hpp->size, " Samples ");
153}
154
155static int hpp__width_samples(struct perf_hpp *hpp __used)
156{
157 return 11;
158}
159
160static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
161{
162 return scnprintf(hpp->buf, hpp->size, "%11" PRIu64, he->nr_events);
163}
164
165static int hpp__header_period(struct perf_hpp *hpp)
166{
167 return scnprintf(hpp->buf, hpp->size, " Period ");
168}
169
170static int hpp__width_period(struct perf_hpp *hpp __used)
171{
172 return 12;
173}
174
175static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
176{
177 return scnprintf(hpp->buf, hpp->size, "%12" PRIu64, he->period);
178}
179
180static int hpp__header_delta(struct perf_hpp *hpp)
181{
182 return scnprintf(hpp->buf, hpp->size, " Delta ");
183}
184
185static int hpp__width_delta(struct perf_hpp *hpp __used)
186{
187 return 7;
188}
189
190static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
191{
192 struct hists *pair_hists = hpp->ptr;
193 u64 old_total, new_total;
194 double old_percent = 0, new_percent = 0;
195 double diff;
196 char buf[32];
197
198 old_total = pair_hists->stats.total_period;
199 if (old_total > 0 && he->pair)
200 old_percent = 100.0 * he->pair->period / old_total;
201
202 new_total = hpp->total_period;
203 if (new_total > 0)
204 new_percent = 100.0 * he->period / new_total;
205
206 diff = new_percent - old_percent;
207 if (fabs(diff) < 0.01)
208 return scnprintf(hpp->buf, hpp->size, " ");
209
210 scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
211 return scnprintf(hpp->buf, hpp->size, "%7.7s", buf);
212}
213
214static int hpp__header_displ(struct perf_hpp *hpp)
215{
216 return scnprintf(hpp->buf, hpp->size, "Displ.");
217}
218
219static int hpp__width_displ(struct perf_hpp *hpp __used)
220{
221 return 6;
222}
223
224static int hpp__entry_displ(struct perf_hpp *hpp, struct hist_entry *he __used)
225{
226 char buf[32];
227
228 if (!hpp->displacement)
229 return scnprintf(hpp->buf, hpp->size, " ");
230
231 scnprintf(buf, sizeof(buf), "%+4ld", hpp->displacement);
232 return scnprintf(hpp->buf, hpp->size, "%6.6s", buf);
233}
234
235#define HPP__COLOR_PRINT_FNS(_name) \
236 .header = hpp__header_ ## _name, \
237 .width = hpp__width_ ## _name, \
238 .color = hpp__color_ ## _name, \
239 .entry = hpp__entry_ ## _name
240
241#define HPP__PRINT_FNS(_name) \
242 .header = hpp__header_ ## _name, \
243 .width = hpp__width_ ## _name, \
244 .entry = hpp__entry_ ## _name
245
246struct perf_hpp_fmt perf_hpp__format[] = {
247 { .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
248 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
249 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
250 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) },
251 { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
252 { .cond = false, HPP__PRINT_FNS(samples) },
253 { .cond = false, HPP__PRINT_FNS(period) },
254 { .cond = false, HPP__PRINT_FNS(delta) },
255 { .cond = false, HPP__PRINT_FNS(displ) }
256};
257
258#undef HPP__COLOR_PRINT_FNS
259#undef HPP__PRINT_FNS
260
261void perf_hpp__init(bool need_pair, bool show_displacement)
262{
263 if (symbol_conf.show_cpu_utilization) {
264 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
265 perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true;
266
267 if (perf_guest) {
268 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true;
269 perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true;
270 }
271 }
272
273 if (symbol_conf.show_nr_samples)
274 perf_hpp__format[PERF_HPP__SAMPLES].cond = true;
275
276 if (symbol_conf.show_total_period)
277 perf_hpp__format[PERF_HPP__PERIOD].cond = true;
278
279 if (need_pair) {
280 perf_hpp__format[PERF_HPP__DELTA].cond = true;
281
282 if (show_displacement)
283 perf_hpp__format[PERF_HPP__DISPL].cond = true;
284 }
285}
286
287static inline void advance_hpp(struct perf_hpp *hpp, int inc)
288{
289 hpp->buf += inc;
290 hpp->size -= inc;
291}
292
293int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
294 bool color)
295{
296 const char *sep = symbol_conf.field_sep;
297 char *start = hpp->buf;
298 int i, ret;
299
300 if (symbol_conf.exclude_other && !he->parent)
301 return 0;
302
303 for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
304 if (!perf_hpp__format[i].cond)
305 continue;
306
307 if (!sep || i > 0) {
308 ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
309 advance_hpp(hpp, ret);
310 }
311
312 if (color && perf_hpp__format[i].color)
313 ret = perf_hpp__format[i].color(hpp, he);
314 else
315 ret = perf_hpp__format[i].entry(hpp, he);
316
317 advance_hpp(hpp, ret);
318 }
319
320 return hpp->buf - start;
321}
322
323int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
324 struct hists *hists)
325{
326 const char *sep = symbol_conf.field_sep;
327 struct sort_entry *se;
328 int ret = 0;
329
330 list_for_each_entry(se, &hist_entry__sort_list, list) {
331 if (se->elide)
332 continue;
333
334 ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
335 ret += se->se_snprintf(he, s + ret, size - ret,
336 hists__col_len(hists, se->se_width_idx));
337 }
338
339 return ret;
340}