linux/tools/perf/ui/gtk/hists.c
<<
>>
Prefs
   1#include "../evlist.h"
   2#include "../cache.h"
   3#include "../evsel.h"
   4#include "../sort.h"
   5#include "../hist.h"
   6#include "../helpline.h"
   7#include "gtk.h"
   8
   9#define MAX_COLUMNS                     32
  10
  11static int __percent_color_snprintf(char *buf, size_t size, double percent)
  12{
  13        int ret = 0;
  14        const char *markup;
  15
  16        markup = perf_gtk__get_percent_color(percent);
  17        if (markup)
  18                ret += scnprintf(buf, size, markup);
  19
  20        ret += scnprintf(buf + ret, size - ret, " %6.2f%%", percent);
  21
  22        if (markup)
  23                ret += scnprintf(buf + ret, size - ret, "</span>");
  24
  25        return ret;
  26}
  27
  28
  29static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
  30                            u64 (*get_field)(struct hist_entry *))
  31{
  32        int ret;
  33        double percent = 0.0;
  34        struct hists *hists = he->hists;
  35        struct perf_evsel *evsel = hists_to_evsel(hists);
  36
  37        if (hists->stats.total_period)
  38                percent = 100.0 * get_field(he) / hists->stats.total_period;
  39
  40        ret = __percent_color_snprintf(hpp->buf, hpp->size, percent);
  41
  42        if (perf_evsel__is_group_event(evsel)) {
  43                int prev_idx, idx_delta;
  44                struct hist_entry *pair;
  45                int nr_members = evsel->nr_members;
  46
  47                prev_idx = perf_evsel__group_idx(evsel);
  48
  49                list_for_each_entry(pair, &he->pairs.head, pairs.node) {
  50                        u64 period = get_field(pair);
  51                        u64 total = pair->hists->stats.total_period;
  52
  53                        evsel = hists_to_evsel(pair->hists);
  54                        idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
  55
  56                        while (idx_delta--) {
  57                                /*
  58                                 * zero-fill group members in the middle which
  59                                 * have no sample
  60                                 */
  61                                ret += __percent_color_snprintf(hpp->buf + ret,
  62                                                                hpp->size - ret,
  63                                                                0.0);
  64                        }
  65
  66                        percent = 100.0 * period / total;
  67                        ret += __percent_color_snprintf(hpp->buf + ret,
  68                                                        hpp->size - ret,
  69                                                        percent);
  70
  71                        prev_idx = perf_evsel__group_idx(evsel);
  72                }
  73
  74                idx_delta = nr_members - prev_idx - 1;
  75
  76                while (idx_delta--) {
  77                        /*
  78                         * zero-fill group members at last which have no sample
  79                         */
  80                        ret += __percent_color_snprintf(hpp->buf + ret,
  81                                                        hpp->size - ret,
  82                                                        0.0);
  83                }
  84        }
  85        return ret;
  86}
  87
  88#define __HPP_COLOR_PERCENT_FN(_type, _field)                                   \
  89static u64 he_get_##_field(struct hist_entry *he)                               \
  90{                                                                               \
  91        return he->stat._field;                                                 \
  92}                                                                               \
  93                                                                                \
  94static int perf_gtk__hpp_color_##_type(struct perf_hpp *hpp,                    \
  95                                       struct hist_entry *he)                   \
  96{                                                                               \
  97        return __hpp__color_fmt(hpp, he, he_get_##_field);                      \
  98}
  99
 100__HPP_COLOR_PERCENT_FN(overhead, period)
 101__HPP_COLOR_PERCENT_FN(overhead_sys, period_sys)
 102__HPP_COLOR_PERCENT_FN(overhead_us, period_us)
 103__HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys)
 104__HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
 105
 106#undef __HPP_COLOR_PERCENT_FN
 107
 108
 109void perf_gtk__init_hpp(void)
 110{
 111        perf_hpp__column_enable(PERF_HPP__OVERHEAD);
 112
 113        perf_hpp__init();
 114
 115        perf_hpp__format[PERF_HPP__OVERHEAD].color =
 116                                perf_gtk__hpp_color_overhead;
 117        perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color =
 118                                perf_gtk__hpp_color_overhead_sys;
 119        perf_hpp__format[PERF_HPP__OVERHEAD_US].color =
 120                                perf_gtk__hpp_color_overhead_us;
 121        perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].color =
 122                                perf_gtk__hpp_color_overhead_guest_sys;
 123        perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].color =
 124                                perf_gtk__hpp_color_overhead_guest_us;
 125}
 126
 127static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
 128                                 float min_pcnt)
 129{
 130        struct perf_hpp_fmt *fmt;
 131        GType col_types[MAX_COLUMNS];
 132        GtkCellRenderer *renderer;
 133        struct sort_entry *se;
 134        GtkListStore *store;
 135        struct rb_node *nd;
 136        GtkWidget *view;
 137        int col_idx;
 138        int nr_cols;
 139        char s[512];
 140
 141        struct perf_hpp hpp = {
 142                .buf            = s,
 143                .size           = sizeof(s),
 144                .ptr            = hists_to_evsel(hists),
 145        };
 146
 147        nr_cols = 0;
 148
 149        perf_hpp__for_each_format(fmt)
 150                col_types[nr_cols++] = G_TYPE_STRING;
 151
 152        list_for_each_entry(se, &hist_entry__sort_list, list) {
 153                if (se->elide)
 154                        continue;
 155
 156                col_types[nr_cols++] = G_TYPE_STRING;
 157        }
 158
 159        store = gtk_list_store_newv(nr_cols, col_types);
 160
 161        view = gtk_tree_view_new();
 162
 163        renderer = gtk_cell_renderer_text_new();
 164
 165        col_idx = 0;
 166
 167        perf_hpp__for_each_format(fmt) {
 168                fmt->header(&hpp);
 169
 170                gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
 171                                                            -1, ltrim(s),
 172                                                            renderer, "markup",
 173                                                            col_idx++, NULL);
 174        }
 175
 176        list_for_each_entry(se, &hist_entry__sort_list, list) {
 177                if (se->elide)
 178                        continue;
 179
 180                gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
 181                                                            -1, se->se_header,
 182                                                            renderer, "text",
 183                                                            col_idx++, NULL);
 184        }
 185
 186        gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
 187
 188        g_object_unref(GTK_TREE_MODEL(store));
 189
 190        for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
 191                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
 192                GtkTreeIter iter;
 193                float percent = h->stat.period * 100.0 /
 194                                        hists->stats.total_period;
 195
 196                if (h->filtered)
 197                        continue;
 198
 199                if (percent < min_pcnt)
 200                        continue;
 201
 202                gtk_list_store_append(store, &iter);
 203
 204                col_idx = 0;
 205
 206                perf_hpp__for_each_format(fmt) {
 207                        if (fmt->color)
 208                                fmt->color(&hpp, h);
 209                        else
 210                                fmt->entry(&hpp, h);
 211
 212                        gtk_list_store_set(store, &iter, col_idx++, s, -1);
 213                }
 214
 215                list_for_each_entry(se, &hist_entry__sort_list, list) {
 216                        if (se->elide)
 217                                continue;
 218
 219                        se->se_snprintf(h, s, ARRAY_SIZE(s),
 220                                        hists__col_len(hists, se->se_width_idx));
 221
 222                        gtk_list_store_set(store, &iter, col_idx++, s, -1);
 223                }
 224        }
 225
 226        gtk_container_add(GTK_CONTAINER(window), view);
 227}
 228
 229int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
 230                                  const char *help,
 231                                  struct hist_browser_timer *hbt __maybe_unused,
 232                                  float min_pcnt)
 233{
 234        struct perf_evsel *pos;
 235        GtkWidget *vbox;
 236        GtkWidget *notebook;
 237        GtkWidget *info_bar;
 238        GtkWidget *statbar;
 239        GtkWidget *window;
 240
 241        signal(SIGSEGV, perf_gtk__signal);
 242        signal(SIGFPE,  perf_gtk__signal);
 243        signal(SIGINT,  perf_gtk__signal);
 244        signal(SIGQUIT, perf_gtk__signal);
 245        signal(SIGTERM, perf_gtk__signal);
 246
 247        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 248
 249        gtk_window_set_title(GTK_WINDOW(window), "perf report");
 250
 251        g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
 252
 253        pgctx = perf_gtk__activate_context(window);
 254        if (!pgctx)
 255                return -1;
 256
 257        vbox = gtk_vbox_new(FALSE, 0);
 258
 259        notebook = gtk_notebook_new();
 260
 261        gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
 262
 263        info_bar = perf_gtk__setup_info_bar();
 264        if (info_bar)
 265                gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
 266
 267        statbar = perf_gtk__setup_statusbar();
 268        gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
 269
 270        gtk_container_add(GTK_CONTAINER(window), vbox);
 271
 272        list_for_each_entry(pos, &evlist->entries, node) {
 273                struct hists *hists = &pos->hists;
 274                const char *evname = perf_evsel__name(pos);
 275                GtkWidget *scrolled_window;
 276                GtkWidget *tab_label;
 277                char buf[512];
 278                size_t size = sizeof(buf);
 279
 280                if (symbol_conf.event_group) {
 281                        if (!perf_evsel__is_group_leader(pos))
 282                                continue;
 283
 284                        if (pos->nr_members > 1) {
 285                                perf_evsel__group_desc(pos, buf, size);
 286                                evname = buf;
 287                        }
 288                }
 289
 290                scrolled_window = gtk_scrolled_window_new(NULL, NULL);
 291
 292                gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
 293                                                        GTK_POLICY_AUTOMATIC,
 294                                                        GTK_POLICY_AUTOMATIC);
 295
 296                perf_gtk__show_hists(scrolled_window, hists, min_pcnt);
 297
 298                tab_label = gtk_label_new(evname);
 299
 300                gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
 301        }
 302
 303        gtk_widget_show_all(window);
 304
 305        perf_gtk__resize_window(window);
 306
 307        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 308
 309        ui_helpline__push(help);
 310
 311        gtk_main();
 312
 313        perf_gtk__deactivate_context(&pgctx);
 314
 315        return 0;
 316}
 317