Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hist.c
Go to the documentation of this file.
1 #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 */
9 static int hpp__header_overhead(struct perf_hpp *hpp)
10 {
11  return scnprintf(hpp->buf, hpp->size, "Overhead");
12 }
13 
14 static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
15 {
16  return 8;
17 }
18 
19 static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
20 {
21  struct hists *hists = he->hists;
22  double percent = 100.0 * he->stat.period / hists->stats.total_period;
23 
24  return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
25 }
26 
27 static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
28 {
29  struct hists *hists = he->hists;
30  double percent = 100.0 * he->stat.period / hists->stats.total_period;
31  const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
32 
33  return scnprintf(hpp->buf, hpp->size, fmt, percent);
34 }
35 
36 static int hpp__header_overhead_sys(struct perf_hpp *hpp)
37 {
38  const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
39 
40  return scnprintf(hpp->buf, hpp->size, fmt, "sys");
41 }
42 
43 static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
44 {
45  return 7;
46 }
47 
48 static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
49 {
50  struct hists *hists = he->hists;
51  double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
52 
53  return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
54 }
55 
56 static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
57 {
58  struct hists *hists = he->hists;
59  double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
60  const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
61 
62  return scnprintf(hpp->buf, hpp->size, fmt, percent);
63 }
64 
65 static int hpp__header_overhead_us(struct perf_hpp *hpp)
66 {
67  const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
68 
69  return scnprintf(hpp->buf, hpp->size, fmt, "user");
70 }
71 
72 static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
73 {
74  return 7;
75 }
76 
77 static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
78 {
79  struct hists *hists = he->hists;
80  double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
81 
82  return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
83 }
84 
85 static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
86 {
87  struct hists *hists = he->hists;
88  double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
89  const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
90 
91  return scnprintf(hpp->buf, hpp->size, fmt, percent);
92 }
93 
94 static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
95 {
96  return scnprintf(hpp->buf, hpp->size, "guest sys");
97 }
98 
99 static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
100 {
101  return 9;
102 }
103 
104 static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
105  struct hist_entry *he)
106 {
107  struct hists *hists = he->hists;
108  double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
109 
110  return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
111 }
112 
113 static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
114  struct hist_entry *he)
115 {
116  struct hists *hists = he->hists;
117  double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
118  const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
119 
120  return scnprintf(hpp->buf, hpp->size, fmt, percent);
121 }
122 
123 static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
124 {
125  return scnprintf(hpp->buf, hpp->size, "guest usr");
126 }
127 
128 static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
129 {
130  return 9;
131 }
132 
133 static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
134  struct hist_entry *he)
135 {
136  struct hists *hists = he->hists;
137  double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
138 
139  return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
140 }
141 
142 static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
143  struct hist_entry *he)
144 {
145  struct hists *hists = he->hists;
146  double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
147  const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
148 
149  return scnprintf(hpp->buf, hpp->size, fmt, percent);
150 }
151 
152 static int hpp__header_baseline(struct perf_hpp *hpp)
153 {
154  return scnprintf(hpp->buf, hpp->size, "Baseline");
155 }
156 
157 static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
158 {
159  return 8;
160 }
161 
162 static double baseline_percent(struct hist_entry *he)
163 {
164  struct hist_entry *pair = he->pair;
165  struct hists *pair_hists = pair ? pair->hists : NULL;
166  double percent = 0.0;
167 
168  if (pair) {
169  u64 total_period = pair_hists->stats.total_period;
170  u64 base_period = pair->stat.period;
171 
172  percent = 100.0 * base_period / total_period;
173  }
174 
175  return percent;
176 }
177 
178 static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
179 {
180  double percent = baseline_percent(he);
181 
182  return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
183 }
184 
185 static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
186 {
187  double percent = baseline_percent(he);
188  const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
189 
190  return scnprintf(hpp->buf, hpp->size, fmt, percent);
191 }
192 
193 static int hpp__header_samples(struct perf_hpp *hpp)
194 {
195  const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
196 
197  return scnprintf(hpp->buf, hpp->size, fmt, "Samples");
198 }
199 
200 static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused)
201 {
202  return 11;
203 }
204 
205 static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
206 {
207  const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
208 
209  return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
210 }
211 
212 static int hpp__header_period(struct perf_hpp *hpp)
213 {
214  const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
215 
216  return scnprintf(hpp->buf, hpp->size, fmt, "Period");
217 }
218 
219 static int hpp__width_period(struct perf_hpp *hpp __maybe_unused)
220 {
221  return 12;
222 }
223 
224 static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
225 {
226  const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
227 
228  return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
229 }
230 
231 static int hpp__header_delta(struct perf_hpp *hpp)
232 {
233  const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
234 
235  return scnprintf(hpp->buf, hpp->size, fmt, "Delta");
236 }
237 
238 static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
239 {
240  return 7;
241 }
242 
243 static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
244 {
245  struct hist_entry *pair = he->pair;
246  struct hists *pair_hists = pair ? pair->hists : NULL;
247  struct hists *hists = he->hists;
248  u64 old_total, new_total;
249  double old_percent = 0, new_percent = 0;
250  double diff;
251  const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
252  char buf[32] = " ";
253 
254  old_total = pair_hists ? pair_hists->stats.total_period : 0;
255  if (old_total > 0 && pair)
256  old_percent = 100.0 * pair->stat.period / old_total;
257 
258  new_total = hists->stats.total_period;
259  if (new_total > 0)
260  new_percent = 100.0 * he->stat.period / new_total;
261 
262  diff = new_percent - old_percent;
263  if (fabs(diff) >= 0.01)
264  scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
265 
266  return scnprintf(hpp->buf, hpp->size, fmt, buf);
267 }
268 
269 static int hpp__header_displ(struct perf_hpp *hpp)
270 {
271  return scnprintf(hpp->buf, hpp->size, "Displ.");
272 }
273 
274 static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
275 {
276  return 6;
277 }
278 
279 static int hpp__entry_displ(struct perf_hpp *hpp,
280  struct hist_entry *he)
281 {
282  struct hist_entry *pair = he->pair;
283  long displacement = pair ? pair->position - he->position : 0;
284  const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
285  char buf[32] = " ";
286 
287  if (displacement)
288  scnprintf(buf, sizeof(buf), "%+4ld", displacement);
289 
290  return scnprintf(hpp->buf, hpp->size, fmt, buf);
291 }
292 
293 #define HPP__COLOR_PRINT_FNS(_name) \
294  .header = hpp__header_ ## _name, \
295  .width = hpp__width_ ## _name, \
296  .color = hpp__color_ ## _name, \
297  .entry = hpp__entry_ ## _name
298 
299 #define HPP__PRINT_FNS(_name) \
300  .header = hpp__header_ ## _name, \
301  .width = hpp__width_ ## _name, \
302  .entry = hpp__entry_ ## _name
303 
305  { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
306  { .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
307  { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
308  { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
309  { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) },
310  { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
311  { .cond = false, HPP__PRINT_FNS(samples) },
312  { .cond = false, HPP__PRINT_FNS(period) },
313  { .cond = false, HPP__PRINT_FNS(delta) },
314  { .cond = false, HPP__PRINT_FNS(displ) }
315 };
316 
317 #undef HPP__COLOR_PRINT_FNS
318 #undef HPP__PRINT_FNS
319 
320 void perf_hpp__init(void)
321 {
323  perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
324  perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true;
325 
326  if (perf_guest) {
327  perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true;
328  perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true;
329  }
330  }
331 
333  perf_hpp__format[PERF_HPP__SAMPLES].cond = true;
334 
336  perf_hpp__format[PERF_HPP__PERIOD].cond = true;
337 }
338 
339 void perf_hpp__column_enable(unsigned col, bool enable)
340 {
341  BUG_ON(col >= PERF_HPP__MAX_INDEX);
342  perf_hpp__format[col].cond = enable;
343 }
344 
345 static inline void advance_hpp(struct perf_hpp *hpp, int inc)
346 {
347  hpp->buf += inc;
348  hpp->size -= inc;
349 }
350 
351 int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
352  bool color)
353 {
354  const char *sep = symbol_conf.field_sep;
355  char *start = hpp->buf;
356  int i, ret;
357  bool first = true;
358 
359  if (symbol_conf.exclude_other && !he->parent)
360  return 0;
361 
362  for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
363  if (!perf_hpp__format[i].cond)
364  continue;
365 
366  if (!sep || !first) {
367  ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
368  advance_hpp(hpp, ret);
369  first = false;
370  }
371 
372  if (color && perf_hpp__format[i].color)
373  ret = perf_hpp__format[i].color(hpp, he);
374  else
375  ret = perf_hpp__format[i].entry(hpp, he);
376 
377  advance_hpp(hpp, ret);
378  }
379 
380  return hpp->buf - start;
381 }
382 
383 int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
384  struct hists *hists)
385 {
386  const char *sep = symbol_conf.field_sep;
387  struct sort_entry *se;
388  int ret = 0;
389 
391  if (se->elide)
392  continue;
393 
394  ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
395  ret += se->se_snprintf(he, s + ret, size - ret,
396  hists__col_len(hists, se->se_width_idx));
397  }
398 
399  return ret;
400 }
401 
402 /*
403  * See hists__fprintf to match the column widths
404  */
405 unsigned int hists__sort_list_width(struct hists *hists)
406 {
407  struct sort_entry *se;
408  int i, ret = 0;
409 
410  for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
411  if (!perf_hpp__format[i].cond)
412  continue;
413  if (i)
414  ret += 2;
415 
416  ret += perf_hpp__format[i].width(NULL);
417  }
418 
420  if (!se->elide)
421  ret += 2 + hists__col_len(hists, se->se_width_idx);
422 
423  if (verbose) /* Addr + origin */
424  ret += 3 + BITS_PER_LONG / 4;
425 
426  return ret;
427 }