aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/ui/hist.c
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung.kim@lge.com>2012-09-02 22:53:06 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-09-08 12:19:44 -0400
commitea251d51d2c7d7233790123227f787c477f567f5 (patch)
treeedc255462a434ecd3bbb1fac16daf1198a050e2e /tools/perf/ui/hist.c
parent8bf98b89688c3d7ec071bf26d49761e38d846b47 (diff)
perf hists: Introduce perf_hpp for hist period printing
Current hist print functions are messy because it has to consider many of command line options and the code doing that is scattered around to places. So when someone wants to add an option to manipulate the hist output it'd very easy to miss to update all of them in sync. And things getting worse as more options/features are added continuously. So I'd like to refactor them using hpp formats and move common code to ui/hist.c in order to make it easy to maintain and to add new features. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1346640790-17197-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/ui/hist.c')
-rw-r--r--tools/perf/ui/hist.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
new file mode 100644
index 000000000000..8ccd1f2330d1
--- /dev/null
+++ b/tools/perf/ui/hist.c
@@ -0,0 +1,340 @@
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 */
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}