Perf: fix build breakage
[pandora-kernel.git] / tools / perf / util / hist.c
1 #include "annotate.h"
2 #include "util.h"
3 #include "build-id.h"
4 #include "hist.h"
5 #include "session.h"
6 #include "sort.h"
7 #include <math.h>
8
9 static bool hists__filter_entry_by_dso(struct hists *hists,
10                                        struct hist_entry *he);
11 static bool hists__filter_entry_by_thread(struct hists *hists,
12                                           struct hist_entry *he);
13
14 enum hist_filter {
15         HIST_FILTER__DSO,
16         HIST_FILTER__THREAD,
17         HIST_FILTER__PARENT,
18 };
19
20 struct callchain_param  callchain_param = {
21         .mode   = CHAIN_GRAPH_REL,
22         .min_percent = 0.5,
23         .order  = ORDER_CALLEE
24 };
25
26 u16 hists__col_len(struct hists *hists, enum hist_column col)
27 {
28         return hists->col_len[col];
29 }
30
31 void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len)
32 {
33         hists->col_len[col] = len;
34 }
35
36 bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len)
37 {
38         if (len > hists__col_len(hists, col)) {
39                 hists__set_col_len(hists, col, len);
40                 return true;
41         }
42         return false;
43 }
44
45 static void hists__reset_col_len(struct hists *hists)
46 {
47         enum hist_column col;
48
49         for (col = 0; col < HISTC_NR_COLS; ++col)
50                 hists__set_col_len(hists, col, 0);
51 }
52
53 static void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
54 {
55         u16 len;
56
57         if (h->ms.sym)
58                 hists__new_col_len(hists, HISTC_SYMBOL, h->ms.sym->namelen);
59         else {
60                 const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
61
62                 if (hists__col_len(hists, HISTC_DSO) < unresolved_col_width &&
63                     !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
64                     !symbol_conf.dso_list)
65                         hists__set_col_len(hists, HISTC_DSO,
66                                            unresolved_col_width);
67         }
68
69         len = thread__comm_len(h->thread);
70         if (hists__new_col_len(hists, HISTC_COMM, len))
71                 hists__set_col_len(hists, HISTC_THREAD, len + 6);
72
73         if (h->ms.map) {
74                 len = dso__name_len(h->ms.map->dso);
75                 hists__new_col_len(hists, HISTC_DSO, len);
76         }
77 }
78
79 static void hist_entry__add_cpumode_period(struct hist_entry *self,
80                                            unsigned int cpumode, u64 period)
81 {
82         switch (cpumode) {
83         case PERF_RECORD_MISC_KERNEL:
84                 self->period_sys += period;
85                 break;
86         case PERF_RECORD_MISC_USER:
87                 self->period_us += period;
88                 break;
89         case PERF_RECORD_MISC_GUEST_KERNEL:
90                 self->period_guest_sys += period;
91                 break;
92         case PERF_RECORD_MISC_GUEST_USER:
93                 self->period_guest_us += period;
94                 break;
95         default:
96                 break;
97         }
98 }
99
100 static void hist_entry__decay(struct hist_entry *he)
101 {
102         he->period = (he->period * 7) / 8;
103         he->nr_events = (he->nr_events * 7) / 8;
104 }
105
106 static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
107 {
108         u64 prev_period = he->period;
109
110         if (prev_period == 0)
111                 return true;
112
113         hist_entry__decay(he);
114
115         if (!he->filtered)
116                 hists->stats.total_period -= prev_period - he->period;
117
118         return he->period == 0;
119 }
120
121 static void __hists__decay_entries(struct hists *hists, bool zap_user,
122                                    bool zap_kernel, bool threaded)
123 {
124         struct rb_node *next = rb_first(&hists->entries);
125         struct hist_entry *n;
126
127         while (next) {
128                 n = rb_entry(next, struct hist_entry, rb_node);
129                 next = rb_next(&n->rb_node);
130                 /*
131                  * We may be annotating this, for instance, so keep it here in
132                  * case some it gets new samples, we'll eventually free it when
133                  * the user stops browsing and it agains gets fully decayed.
134                  */
135                 if (((zap_user && n->level == '.') ||
136                      (zap_kernel && n->level != '.') ||
137                      hists__decay_entry(hists, n)) &&
138                     !n->used) {
139                         rb_erase(&n->rb_node, &hists->entries);
140
141                         if (sort__need_collapse || threaded)
142                                 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
143
144                         hist_entry__free(n);
145                         --hists->nr_entries;
146                 }
147         }
148 }
149
150 void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
151 {
152         return __hists__decay_entries(hists, zap_user, zap_kernel, false);
153 }
154
155 void hists__decay_entries_threaded(struct hists *hists,
156                                    bool zap_user, bool zap_kernel)
157 {
158         return __hists__decay_entries(hists, zap_user, zap_kernel, true);
159 }
160
161 /*
162  * histogram, sorted on item, collects periods
163  */
164
165 static struct hist_entry *hist_entry__new(struct hist_entry *template)
166 {
167         size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
168         struct hist_entry *self = malloc(sizeof(*self) + callchain_size);
169
170         if (self != NULL) {
171                 *self = *template;
172                 self->nr_events = 1;
173                 if (self->ms.map)
174                         self->ms.map->referenced = true;
175                 if (symbol_conf.use_callchain)
176                         callchain_init(self->callchain);
177         }
178
179         return self;
180 }
181
182 static void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
183 {
184         if (!h->filtered) {
185                 hists__calc_col_len(hists, h);
186                 ++hists->nr_entries;
187                 hists->stats.total_period += h->period;
188         }
189 }
190
191 static u8 symbol__parent_filter(const struct symbol *parent)
192 {
193         if (symbol_conf.exclude_other && parent == NULL)
194                 return 1 << HIST_FILTER__PARENT;
195         return 0;
196 }
197
198 struct hist_entry *__hists__add_entry(struct hists *hists,
199                                       struct addr_location *al,
200                                       struct symbol *sym_parent, u64 period)
201 {
202         struct rb_node **p;
203         struct rb_node *parent = NULL;
204         struct hist_entry *he;
205         struct hist_entry entry = {
206                 .thread = al->thread,
207                 .ms = {
208                         .map    = al->map,
209                         .sym    = al->sym,
210                 },
211                 .cpu    = al->cpu,
212                 .ip     = al->addr,
213                 .level  = al->level,
214                 .period = period,
215                 .parent = sym_parent,
216                 .filtered = symbol__parent_filter(sym_parent),
217         };
218         int cmp;
219
220         pthread_mutex_lock(&hists->lock);
221
222         p = &hists->entries_in->rb_node;
223
224         while (*p != NULL) {
225                 parent = *p;
226                 he = rb_entry(parent, struct hist_entry, rb_node_in);
227
228                 cmp = hist_entry__cmp(&entry, he);
229
230                 if (!cmp) {
231                         he->period += period;
232                         ++he->nr_events;
233
234                         /* If the map of an existing hist_entry has
235                          * become out-of-date due to an exec() or
236                          * similar, update it.  Otherwise we will
237                          * mis-adjust symbol addresses when computing
238                          * the history counter to increment.
239                          */
240                         if (he->ms.map != entry.ms.map) {
241                                 he->ms.map = entry.ms.map;
242                                 if (he->ms.map)
243                                         he->ms.map->referenced = true;
244                         }
245                         goto out;
246                 }
247
248                 if (cmp < 0)
249                         p = &(*p)->rb_left;
250                 else
251                         p = &(*p)->rb_right;
252         }
253
254         he = hist_entry__new(&entry);
255         if (!he)
256                 goto out_unlock;
257
258         rb_link_node(&he->rb_node_in, parent, p);
259         rb_insert_color(&he->rb_node_in, hists->entries_in);
260 out:
261         hist_entry__add_cpumode_period(he, al->cpumode, period);
262 out_unlock:
263         pthread_mutex_unlock(&hists->lock);
264         return he;
265 }
266
267 int64_t
268 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
269 {
270         struct sort_entry *se;
271         int64_t cmp = 0;
272
273         list_for_each_entry(se, &hist_entry__sort_list, list) {
274                 cmp = se->se_cmp(left, right);
275                 if (cmp)
276                         break;
277         }
278
279         return cmp;
280 }
281
282 int64_t
283 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
284 {
285         struct sort_entry *se;
286         int64_t cmp = 0;
287
288         list_for_each_entry(se, &hist_entry__sort_list, list) {
289                 int64_t (*f)(struct hist_entry *, struct hist_entry *);
290
291                 f = se->se_collapse ?: se->se_cmp;
292
293                 cmp = f(left, right);
294                 if (cmp)
295                         break;
296         }
297
298         return cmp;
299 }
300
301 void hist_entry__free(struct hist_entry *he)
302 {
303         free(he);
304 }
305
306 /*
307  * collapse the histogram
308  */
309
310 static bool hists__collapse_insert_entry(struct hists *hists,
311                                          struct rb_root *root,
312                                          struct hist_entry *he)
313 {
314         struct rb_node **p = &root->rb_node;
315         struct rb_node *parent = NULL;
316         struct hist_entry *iter;
317         int64_t cmp;
318
319         while (*p != NULL) {
320                 parent = *p;
321                 iter = rb_entry(parent, struct hist_entry, rb_node_in);
322
323                 cmp = hist_entry__collapse(iter, he);
324
325                 if (!cmp) {
326                         iter->period += he->period;
327                         iter->nr_events += he->nr_events;
328                         if (symbol_conf.use_callchain) {
329                                 callchain_cursor_reset(&hists->callchain_cursor);
330                                 callchain_merge(&hists->callchain_cursor, iter->callchain,
331                                                 he->callchain);
332                         }
333                         hist_entry__free(he);
334                         return false;
335                 }
336
337                 if (cmp < 0)
338                         p = &(*p)->rb_left;
339                 else
340                         p = &(*p)->rb_right;
341         }
342
343         rb_link_node(&he->rb_node_in, parent, p);
344         rb_insert_color(&he->rb_node_in, root);
345         return true;
346 }
347
348 static struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
349 {
350         struct rb_root *root;
351
352         pthread_mutex_lock(&hists->lock);
353
354         root = hists->entries_in;
355         if (++hists->entries_in > &hists->entries_in_array[1])
356                 hists->entries_in = &hists->entries_in_array[0];
357
358         pthread_mutex_unlock(&hists->lock);
359
360         return root;
361 }
362
363 static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
364 {
365         hists__filter_entry_by_dso(hists, he);
366         hists__filter_entry_by_thread(hists, he);
367 }
368
369 static void __hists__collapse_resort(struct hists *hists, bool threaded)
370 {
371         struct rb_root *root;
372         struct rb_node *next;
373         struct hist_entry *n;
374
375         if (!sort__need_collapse && !threaded)
376                 return;
377
378         root = hists__get_rotate_entries_in(hists);
379         next = rb_first(root);
380
381         while (next) {
382                 n = rb_entry(next, struct hist_entry, rb_node_in);
383                 next = rb_next(&n->rb_node_in);
384
385                 rb_erase(&n->rb_node_in, root);
386                 if (hists__collapse_insert_entry(hists, &hists->entries_collapsed, n)) {
387                         /*
388                          * If it wasn't combined with one of the entries already
389                          * collapsed, we need to apply the filters that may have
390                          * been set by, say, the hist_browser.
391                          */
392                         hists__apply_filters(hists, n);
393                 }
394         }
395 }
396
397 void hists__collapse_resort(struct hists *hists)
398 {
399         return __hists__collapse_resort(hists, false);
400 }
401
402 void hists__collapse_resort_threaded(struct hists *hists)
403 {
404         return __hists__collapse_resort(hists, true);
405 }
406
407 /*
408  * reverse the map, sort on period.
409  */
410
411 static void __hists__insert_output_entry(struct rb_root *entries,
412                                          struct hist_entry *he,
413                                          u64 min_callchain_hits)
414 {
415         struct rb_node **p = &entries->rb_node;
416         struct rb_node *parent = NULL;
417         struct hist_entry *iter;
418
419         if (symbol_conf.use_callchain)
420                 callchain_param.sort(&he->sorted_chain, he->callchain,
421                                       min_callchain_hits, &callchain_param);
422
423         while (*p != NULL) {
424                 parent = *p;
425                 iter = rb_entry(parent, struct hist_entry, rb_node);
426
427                 if (he->period > iter->period)
428                         p = &(*p)->rb_left;
429                 else
430                         p = &(*p)->rb_right;
431         }
432
433         rb_link_node(&he->rb_node, parent, p);
434         rb_insert_color(&he->rb_node, entries);
435 }
436
437 static void __hists__output_resort(struct hists *hists, bool threaded)
438 {
439         struct rb_root *root;
440         struct rb_node *next;
441         struct hist_entry *n;
442         u64 min_callchain_hits;
443
444         min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
445
446         if (sort__need_collapse || threaded)
447                 root = &hists->entries_collapsed;
448         else
449                 root = hists->entries_in;
450
451         next = rb_first(root);
452         hists->entries = RB_ROOT;
453
454         hists->nr_entries = 0;
455         hists->stats.total_period = 0;
456         hists__reset_col_len(hists);
457
458         while (next) {
459                 n = rb_entry(next, struct hist_entry, rb_node_in);
460                 next = rb_next(&n->rb_node_in);
461
462                 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits);
463                 hists__inc_nr_entries(hists, n);
464         }
465 }
466
467 void hists__output_resort(struct hists *hists)
468 {
469         return __hists__output_resort(hists, false);
470 }
471
472 void hists__output_resort_threaded(struct hists *hists)
473 {
474         return __hists__output_resort(hists, true);
475 }
476
477 static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
478 {
479         int i;
480         int ret = fprintf(fp, "            ");
481
482         for (i = 0; i < left_margin; i++)
483                 ret += fprintf(fp, " ");
484
485         return ret;
486 }
487
488 static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
489                                           int left_margin)
490 {
491         int i;
492         size_t ret = callchain__fprintf_left_margin(fp, left_margin);
493
494         for (i = 0; i < depth; i++)
495                 if (depth_mask & (1 << i))
496                         ret += fprintf(fp, "|          ");
497                 else
498                         ret += fprintf(fp, "           ");
499
500         ret += fprintf(fp, "\n");
501
502         return ret;
503 }
504
505 static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
506                                      int depth, int depth_mask, int period,
507                                      u64 total_samples, u64 hits,
508                                      int left_margin)
509 {
510         int i;
511         size_t ret = 0;
512
513         ret += callchain__fprintf_left_margin(fp, left_margin);
514         for (i = 0; i < depth; i++) {
515                 if (depth_mask & (1 << i))
516                         ret += fprintf(fp, "|");
517                 else
518                         ret += fprintf(fp, " ");
519                 if (!period && i == depth - 1) {
520                         double percent;
521
522                         percent = hits * 100.0 / total_samples;
523                         ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
524                 } else
525                         ret += fprintf(fp, "%s", "          ");
526         }
527         if (chain->ms.sym)
528                 ret += fprintf(fp, "%s\n", chain->ms.sym->name);
529         else
530                 ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
531
532         return ret;
533 }
534
535 static struct symbol *rem_sq_bracket;
536 static struct callchain_list rem_hits;
537
538 static void init_rem_hits(void)
539 {
540         rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
541         if (!rem_sq_bracket) {
542                 fprintf(stderr, "Not enough memory to display remaining hits\n");
543                 return;
544         }
545
546         strcpy(rem_sq_bracket->name, "[...]");
547         rem_hits.ms.sym = rem_sq_bracket;
548 }
549
550 static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
551                                          u64 total_samples, int depth,
552                                          int depth_mask, int left_margin)
553 {
554         struct rb_node *node, *next;
555         struct callchain_node *child;
556         struct callchain_list *chain;
557         int new_depth_mask = depth_mask;
558         u64 new_total;
559         u64 remaining;
560         size_t ret = 0;
561         int i;
562         uint entries_printed = 0;
563
564         if (callchain_param.mode == CHAIN_GRAPH_REL)
565                 new_total = self->children_hit;
566         else
567                 new_total = total_samples;
568
569         remaining = new_total;
570
571         node = rb_first(&self->rb_root);
572         while (node) {
573                 u64 cumul;
574
575                 child = rb_entry(node, struct callchain_node, rb_node);
576                 cumul = callchain_cumul_hits(child);
577                 remaining -= cumul;
578
579                 /*
580                  * The depth mask manages the output of pipes that show
581                  * the depth. We don't want to keep the pipes of the current
582                  * level for the last child of this depth.
583                  * Except if we have remaining filtered hits. They will
584                  * supersede the last child
585                  */
586                 next = rb_next(node);
587                 if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
588                         new_depth_mask &= ~(1 << (depth - 1));
589
590                 /*
591                  * But we keep the older depth mask for the line separator
592                  * to keep the level link until we reach the last child
593                  */
594                 ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
595                                                    left_margin);
596                 i = 0;
597                 list_for_each_entry(chain, &child->val, list) {
598                         ret += ipchain__fprintf_graph(fp, chain, depth,
599                                                       new_depth_mask, i++,
600                                                       new_total,
601                                                       cumul,
602                                                       left_margin);
603                 }
604                 ret += __callchain__fprintf_graph(fp, child, new_total,
605                                                   depth + 1,
606                                                   new_depth_mask | (1 << depth),
607                                                   left_margin);
608                 node = next;
609                 if (++entries_printed == callchain_param.print_limit)
610                         break;
611         }
612
613         if (callchain_param.mode == CHAIN_GRAPH_REL &&
614                 remaining && remaining != new_total) {
615
616                 if (!rem_sq_bracket)
617                         return ret;
618
619                 new_depth_mask &= ~(1 << (depth - 1));
620
621                 ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
622                                               new_depth_mask, 0, new_total,
623                                               remaining, left_margin);
624         }
625
626         return ret;
627 }
628
629 static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
630                                        u64 total_samples, int left_margin)
631 {
632         struct callchain_list *chain;
633         bool printed = false;
634         int i = 0;
635         int ret = 0;
636         u32 entries_printed = 0;
637
638         list_for_each_entry(chain, &self->val, list) {
639                 if (!i++ && sort__first_dimension == SORT_SYM)
640                         continue;
641
642                 if (!printed) {
643                         ret += callchain__fprintf_left_margin(fp, left_margin);
644                         ret += fprintf(fp, "|\n");
645                         ret += callchain__fprintf_left_margin(fp, left_margin);
646                         ret += fprintf(fp, "---");
647
648                         left_margin += 3;
649                         printed = true;
650                 } else
651                         ret += callchain__fprintf_left_margin(fp, left_margin);
652
653                 if (chain->ms.sym)
654                         ret += fprintf(fp, " %s\n", chain->ms.sym->name);
655                 else
656                         ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
657
658                 if (++entries_printed == callchain_param.print_limit)
659                         break;
660         }
661
662         ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
663
664         return ret;
665 }
666
667 static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
668                                       u64 total_samples)
669 {
670         struct callchain_list *chain;
671         size_t ret = 0;
672
673         if (!self)
674                 return 0;
675
676         ret += callchain__fprintf_flat(fp, self->parent, total_samples);
677
678
679         list_for_each_entry(chain, &self->val, list) {
680                 if (chain->ip >= PERF_CONTEXT_MAX)
681                         continue;
682                 if (chain->ms.sym)
683                         ret += fprintf(fp, "                %s\n", chain->ms.sym->name);
684                 else
685                         ret += fprintf(fp, "                %p\n",
686                                         (void *)(long)chain->ip);
687         }
688
689         return ret;
690 }
691
692 static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
693                                             u64 total_samples, int left_margin)
694 {
695         struct rb_node *rb_node;
696         struct callchain_node *chain;
697         size_t ret = 0;
698         u32 entries_printed = 0;
699
700         rb_node = rb_first(&self->sorted_chain);
701         while (rb_node) {
702                 double percent;
703
704                 chain = rb_entry(rb_node, struct callchain_node, rb_node);
705                 percent = chain->hit * 100.0 / total_samples;
706                 switch (callchain_param.mode) {
707                 case CHAIN_FLAT:
708                         ret += percent_color_fprintf(fp, "           %6.2f%%\n",
709                                                      percent);
710                         ret += callchain__fprintf_flat(fp, chain, total_samples);
711                         break;
712                 case CHAIN_GRAPH_ABS: /* Falldown */
713                 case CHAIN_GRAPH_REL:
714                         ret += callchain__fprintf_graph(fp, chain, total_samples,
715                                                         left_margin);
716                 case CHAIN_NONE:
717                 default:
718                         break;
719                 }
720                 ret += fprintf(fp, "\n");
721                 if (++entries_printed == callchain_param.print_limit)
722                         break;
723                 rb_node = rb_next(rb_node);
724         }
725
726         return ret;
727 }
728
729 void hists__output_recalc_col_len(struct hists *hists, int max_rows)
730 {
731         struct rb_node *next = rb_first(&hists->entries);
732         struct hist_entry *n;
733         int row = 0;
734
735         hists__reset_col_len(hists);
736
737         while (next && row++ < max_rows) {
738                 n = rb_entry(next, struct hist_entry, rb_node);
739                 if (!n->filtered)
740                         hists__calc_col_len(hists, n);
741                 next = rb_next(&n->rb_node);
742         }
743 }
744
745 static int hist_entry__pcnt_snprintf(struct hist_entry *self, char *s,
746                                      size_t size, struct hists *pair_hists,
747                                      bool show_displacement, long displacement,
748                                      bool color, u64 session_total)
749 {
750         u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
751         u64 nr_events;
752         const char *sep = symbol_conf.field_sep;
753         int ret;
754
755         if (symbol_conf.exclude_other && !self->parent)
756                 return 0;
757
758         if (pair_hists) {
759                 period = self->pair ? self->pair->period : 0;
760                 nr_events = self->pair ? self->pair->nr_events : 0;
761                 total = pair_hists->stats.total_period;
762                 period_sys = self->pair ? self->pair->period_sys : 0;
763                 period_us = self->pair ? self->pair->period_us : 0;
764                 period_guest_sys = self->pair ? self->pair->period_guest_sys : 0;
765                 period_guest_us = self->pair ? self->pair->period_guest_us : 0;
766         } else {
767                 period = self->period;
768                 nr_events = self->nr_events;
769                 total = session_total;
770                 period_sys = self->period_sys;
771                 period_us = self->period_us;
772                 period_guest_sys = self->period_guest_sys;
773                 period_guest_us = self->period_guest_us;
774         }
775
776         if (total) {
777                 if (color)
778                         ret = percent_color_snprintf(s, size,
779                                                      sep ? "%.2f" : "   %6.2f%%",
780                                                      (period * 100.0) / total);
781                 else
782                         ret = scnprintf(s, size, sep ? "%.2f" : "   %6.2f%%",
783                                        (period * 100.0) / total);
784                 if (symbol_conf.show_cpu_utilization) {
785                         ret += percent_color_snprintf(s + ret, size - ret,
786                                         sep ? "%.2f" : "   %6.2f%%",
787                                         (period_sys * 100.0) / total);
788                         ret += percent_color_snprintf(s + ret, size - ret,
789                                         sep ? "%.2f" : "   %6.2f%%",
790                                         (period_us * 100.0) / total);
791                         if (perf_guest) {
792                                 ret += percent_color_snprintf(s + ret,
793                                                 size - ret,
794                                                 sep ? "%.2f" : "   %6.2f%%",
795                                                 (period_guest_sys * 100.0) /
796                                                                 total);
797                                 ret += percent_color_snprintf(s + ret,
798                                                 size - ret,
799                                                 sep ? "%.2f" : "   %6.2f%%",
800                                                 (period_guest_us * 100.0) /
801                                                                 total);
802                         }
803                 }
804         } else
805                 ret = scnprintf(s, size, sep ? "%" PRIu64 : "%12" PRIu64 " ", period);
806
807         if (symbol_conf.show_nr_samples) {
808                 if (sep)
809                         ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
810                 else
811                         ret += scnprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
812         }
813
814         if (symbol_conf.show_total_period) {
815                 if (sep)
816                         ret += scnprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period);
817                 else
818                         ret += scnprintf(s + ret, size - ret, " %12" PRIu64, period);
819         }
820
821         if (pair_hists) {
822                 char bf[32];
823                 double old_percent = 0, new_percent = 0, diff;
824
825                 if (total > 0)
826                         old_percent = (period * 100.0) / total;
827                 if (session_total > 0)
828                         new_percent = (self->period * 100.0) / session_total;
829
830                 diff = new_percent - old_percent;
831
832                 if (fabs(diff) >= 0.01)
833                         ret += scnprintf(bf, sizeof(bf), "%+4.2F%%", diff);
834                 else
835                         ret += scnprintf(bf, sizeof(bf), " ");
836
837                 if (sep)
838                         ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
839                 else
840                         ret += scnprintf(s + ret, size - ret, "%11.11s", bf);
841
842                 if (show_displacement) {
843                         if (displacement)
844                                 ret += scnprintf(bf, sizeof(bf), "%+4ld", displacement);
845                         else
846                                 ret += scnprintf(bf, sizeof(bf), " ");
847
848                         if (sep)
849                                 ret += scnprintf(s + ret, size - ret, "%c%s", *sep, bf);
850                         else
851                                 ret += scnprintf(s + ret, size - ret, "%6.6s", bf);
852                 }
853         }
854
855         return ret;
856 }
857
858 int hist_entry__snprintf(struct hist_entry *he, char *s, size_t size,
859                          struct hists *hists)
860 {
861         const char *sep = symbol_conf.field_sep;
862         struct sort_entry *se;
863         int ret = 0;
864
865         list_for_each_entry(se, &hist_entry__sort_list, list) {
866                 if (se->elide)
867                         continue;
868
869                 ret += scnprintf(s + ret, size - ret, "%s", sep ?: "  ");
870                 ret += se->se_snprintf(he, s + ret, size - ret,
871                                        hists__col_len(hists, se->se_width_idx));
872         }
873
874         return ret;
875 }
876
877 int hist_entry__fprintf(struct hist_entry *he, size_t size, struct hists *hists,
878                         struct hists *pair_hists, bool show_displacement,
879                         long displacement, FILE *fp, u64 session_total)
880 {
881         char bf[512];
882         int ret;
883
884         if (size == 0 || size > sizeof(bf))
885                 size = sizeof(bf);
886
887         ret = hist_entry__pcnt_snprintf(he, bf, size, pair_hists,
888                                         show_displacement, displacement,
889                                         true, session_total);
890         hist_entry__snprintf(he, bf + ret, size - ret, hists);
891         return fprintf(fp, "%s\n", bf);
892 }
893
894 static size_t hist_entry__fprintf_callchain(struct hist_entry *self,
895                                             struct hists *hists, FILE *fp,
896                                             u64 session_total)
897 {
898         int left_margin = 0;
899
900         if (sort__first_dimension == SORT_COMM) {
901                 struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
902                                                          typeof(*se), list);
903                 left_margin = hists__col_len(hists, se->se_width_idx);
904                 left_margin -= thread__comm_len(self->thread);
905         }
906
907         return hist_entry_callchain__fprintf(fp, self, session_total,
908                                              left_margin);
909 }
910
911 size_t hists__fprintf(struct hists *hists, struct hists *pair,
912                       bool show_displacement, bool show_header, int max_rows,
913                       int max_cols, FILE *fp)
914 {
915         struct sort_entry *se;
916         struct rb_node *nd;
917         size_t ret = 0;
918         unsigned long position = 1;
919         long displacement = 0;
920         unsigned int width;
921         const char *sep = symbol_conf.field_sep;
922         const char *col_width = symbol_conf.col_width_list_str;
923         int nr_rows = 0;
924
925         init_rem_hits();
926
927         if (!show_header)
928                 goto print_entries;
929
930         fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
931
932         if (symbol_conf.show_nr_samples) {
933                 if (sep)
934                         fprintf(fp, "%cSamples", *sep);
935                 else
936                         fputs("  Samples  ", fp);
937         }
938
939         if (symbol_conf.show_total_period) {
940                 if (sep)
941                         ret += fprintf(fp, "%cPeriod", *sep);
942                 else
943                         ret += fprintf(fp, "   Period    ");
944         }
945
946         if (symbol_conf.show_cpu_utilization) {
947                 if (sep) {
948                         ret += fprintf(fp, "%csys", *sep);
949                         ret += fprintf(fp, "%cus", *sep);
950                         if (perf_guest) {
951                                 ret += fprintf(fp, "%cguest sys", *sep);
952                                 ret += fprintf(fp, "%cguest us", *sep);
953                         }
954                 } else {
955                         ret += fprintf(fp, "  sys  ");
956                         ret += fprintf(fp, "  us  ");
957                         if (perf_guest) {
958                                 ret += fprintf(fp, "  guest sys  ");
959                                 ret += fprintf(fp, "  guest us  ");
960                         }
961                 }
962         }
963
964         if (pair) {
965                 if (sep)
966                         ret += fprintf(fp, "%cDelta", *sep);
967                 else
968                         ret += fprintf(fp, "  Delta    ");
969
970                 if (show_displacement) {
971                         if (sep)
972                                 ret += fprintf(fp, "%cDisplacement", *sep);
973                         else
974                                 ret += fprintf(fp, " Displ");
975                 }
976         }
977
978         list_for_each_entry(se, &hist_entry__sort_list, list) {
979                 if (se->elide)
980                         continue;
981                 if (sep) {
982                         fprintf(fp, "%c%s", *sep, se->se_header);
983                         continue;
984                 }
985                 width = strlen(se->se_header);
986                 if (symbol_conf.col_width_list_str) {
987                         if (col_width) {
988                                 hists__set_col_len(hists, se->se_width_idx,
989                                                    atoi(col_width));
990                                 col_width = strchr(col_width, ',');
991                                 if (col_width)
992                                         ++col_width;
993                         }
994                 }
995                 if (!hists__new_col_len(hists, se->se_width_idx, width))
996                         width = hists__col_len(hists, se->se_width_idx);
997                 fprintf(fp, "  %*s", width, se->se_header);
998         }
999
1000         fprintf(fp, "\n");
1001         if (max_rows && ++nr_rows >= max_rows)
1002                 goto out;
1003
1004         if (sep)
1005                 goto print_entries;
1006
1007         fprintf(fp, "# ........");
1008         if (symbol_conf.show_nr_samples)
1009                 fprintf(fp, " ..........");
1010         if (symbol_conf.show_total_period)
1011                 fprintf(fp, " ............");
1012         if (pair) {
1013                 fprintf(fp, " ..........");
1014                 if (show_displacement)
1015                         fprintf(fp, " .....");
1016         }
1017         list_for_each_entry(se, &hist_entry__sort_list, list) {
1018                 unsigned int i;
1019
1020                 if (se->elide)
1021                         continue;
1022
1023                 fprintf(fp, "  ");
1024                 width = hists__col_len(hists, se->se_width_idx);
1025                 if (width == 0)
1026                         width = strlen(se->se_header);
1027                 for (i = 0; i < width; i++)
1028                         fprintf(fp, ".");
1029         }
1030
1031         fprintf(fp, "\n");
1032         if (max_rows && ++nr_rows >= max_rows)
1033                 goto out;
1034
1035         fprintf(fp, "#\n");
1036         if (max_rows && ++nr_rows >= max_rows)
1037                 goto out;
1038
1039 print_entries:
1040         for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1041                 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1042
1043                 if (h->filtered)
1044                         continue;
1045
1046                 if (show_displacement) {
1047                         if (h->pair != NULL)
1048                                 displacement = ((long)h->pair->position -
1049                                                 (long)position);
1050                         else
1051                                 displacement = 0;
1052                         ++position;
1053                 }
1054                 ret += hist_entry__fprintf(h, max_cols, hists, pair, show_displacement,
1055                                            displacement, fp, hists->stats.total_period);
1056
1057                 if (symbol_conf.use_callchain)
1058                         ret += hist_entry__fprintf_callchain(h, hists, fp,
1059                                                              hists->stats.total_period);
1060                 if (max_rows && ++nr_rows >= max_rows)
1061                         goto out;
1062
1063                 if (h->ms.map == NULL && verbose > 1) {
1064                         __map_groups__fprintf_maps(&h->thread->mg,
1065                                                    MAP__FUNCTION, verbose, fp);
1066                         fprintf(fp, "%.10s end\n", graph_dotted_line);
1067                 }
1068         }
1069 out:
1070         free(rem_sq_bracket);
1071
1072         return ret;
1073 }
1074
1075 /*
1076  * See hists__fprintf to match the column widths
1077  */
1078 unsigned int hists__sort_list_width(struct hists *hists)
1079 {
1080         struct sort_entry *se;
1081         int ret = 9; /* total % */
1082
1083         if (symbol_conf.show_cpu_utilization) {
1084                 ret += 7; /* count_sys % */
1085                 ret += 6; /* count_us % */
1086                 if (perf_guest) {
1087                         ret += 13; /* count_guest_sys % */
1088                         ret += 12; /* count_guest_us % */
1089                 }
1090         }
1091
1092         if (symbol_conf.show_nr_samples)
1093                 ret += 11;
1094
1095         if (symbol_conf.show_total_period)
1096                 ret += 13;
1097
1098         list_for_each_entry(se, &hist_entry__sort_list, list)
1099                 if (!se->elide)
1100                         ret += 2 + hists__col_len(hists, se->se_width_idx);
1101
1102         if (verbose) /* Addr + origin */
1103                 ret += 3 + BITS_PER_LONG / 4;
1104
1105         return ret;
1106 }
1107
1108 static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
1109                                        enum hist_filter filter)
1110 {
1111         h->filtered &= ~(1 << filter);
1112         if (h->filtered)
1113                 return;
1114
1115         ++hists->nr_entries;
1116         if (h->ms.unfolded)
1117                 hists->nr_entries += h->nr_rows;
1118         h->row_offset = 0;
1119         hists->stats.total_period += h->period;
1120         hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events;
1121
1122         hists__calc_col_len(hists, h);
1123 }
1124
1125
1126 static bool hists__filter_entry_by_dso(struct hists *hists,
1127                                        struct hist_entry *he)
1128 {
1129         if (hists->dso_filter != NULL &&
1130             (he->ms.map == NULL || he->ms.map->dso != hists->dso_filter)) {
1131                 he->filtered |= (1 << HIST_FILTER__DSO);
1132                 return true;
1133         }
1134
1135         return false;
1136 }
1137
1138 void hists__filter_by_dso(struct hists *hists)
1139 {
1140         struct rb_node *nd;
1141
1142         hists->nr_entries = hists->stats.total_period = 0;
1143         hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
1144         hists__reset_col_len(hists);
1145
1146         for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1147                 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1148
1149                 if (symbol_conf.exclude_other && !h->parent)
1150                         continue;
1151
1152                 if (hists__filter_entry_by_dso(hists, h))
1153                         continue;
1154
1155                 hists__remove_entry_filter(hists, h, HIST_FILTER__DSO);
1156         }
1157 }
1158
1159 static bool hists__filter_entry_by_thread(struct hists *hists,
1160                                           struct hist_entry *he)
1161 {
1162         if (hists->thread_filter != NULL &&
1163             he->thread != hists->thread_filter) {
1164                 he->filtered |= (1 << HIST_FILTER__THREAD);
1165                 return true;
1166         }
1167
1168         return false;
1169 }
1170
1171 void hists__filter_by_thread(struct hists *hists)
1172 {
1173         struct rb_node *nd;
1174
1175         hists->nr_entries = hists->stats.total_period = 0;
1176         hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
1177         hists__reset_col_len(hists);
1178
1179         for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
1180                 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
1181
1182                 if (hists__filter_entry_by_thread(hists, h))
1183                         continue;
1184
1185                 hists__remove_entry_filter(hists, h, HIST_FILTER__THREAD);
1186         }
1187 }
1188
1189 int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
1190 {
1191         return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
1192 }
1193
1194 int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1195 {
1196         return symbol__annotate(he->ms.sym, he->ms.map, privsize);
1197 }
1198
1199 void hists__inc_nr_events(struct hists *hists, u32 type)
1200 {
1201         ++hists->stats.nr_events[0];
1202         ++hists->stats.nr_events[type];
1203 }
1204
1205 size_t hists__fprintf_nr_events(struct hists *hists, FILE *fp)
1206 {
1207         int i;
1208         size_t ret = 0;
1209
1210         for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
1211                 const char *name;
1212
1213                 if (hists->stats.nr_events[i] == 0)
1214                         continue;
1215
1216                 name = perf_event__name(i);
1217                 if (!strcmp(name, "UNKNOWN"))
1218                         continue;
1219
1220                 ret += fprintf(fp, "%16s events: %10d\n", name,
1221                                hists->stats.nr_events[i]);
1222         }
1223
1224         return ret;
1225 }