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