aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/newt.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-03-11 18:12:44 -0500
committerIngo Molnar <mingo@elte.hu>2010-03-12 04:28:46 -0500
commitf9224c5c944b60cf709db4adf1f5195264b8d194 (patch)
tree6c40539b5111a6e9a021e0fe6e22e95997217c3c /tools/perf/util/newt.c
parentdd2ee78dd8e4c6d6f1a333fd60c3dd27d1b07042 (diff)
perf report: Implement initial UI using newt
Newt has widespread availability and provides a rather simple API as can be seen by the size of this patch. The work needed to support it will benefit other frontends too. In this initial patch it just checks if the output is a tty, if not it falls back to the previous behaviour, also if newt-devel/libnewt-dev is not installed the previous behaviour is maintaned. Pressing enter on a symbol will annotate it, ESC in the annotation window will return to the report symbol list. More work will be done to remove the special casing in color_fprintf, stop using fmemopen/FILE in the printing of hist_entries, etc. Also the annotation doesn't need to be done via spawning "perf annotate" and then browsing its output, we can do better by calling directly the builtin-annotate.c functions, that would then be moved to tools/perf/util/annotate.c and shared with perf top, etc But lets go by baby steps, this patch already improves perf usability by allowing to quickly do annotations on symbols from the report screen and provides a first experimentation with libnewt/TUI integration of tools. Tested on RHEL5 and Fedora12 X86_64 and on Debian PARISC64 to browse a perf.data file collected on a Fedora12 x86_64 box. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Avi Kivity <avi@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1268349164-5822-5-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/newt.c')
-rw-r--r--tools/perf/util/newt.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
new file mode 100644
index 000000000000..3d3a936acb67
--- /dev/null
+++ b/tools/perf/util/newt.c
@@ -0,0 +1,194 @@
1#define _GNU_SOURCE
2#include <stdio.h>
3#undef _GNU_SOURCE
4
5#include <stdlib.h>
6#include <newt.h>
7
8#include "cache.h"
9#include "hist.h"
10#include "session.h"
11#include "sort.h"
12#include "symbol.h"
13
14static size_t hist_entry__append_browser(struct hist_entry *self,
15 newtComponent listbox, u64 total)
16{
17 char bf[1024];
18 size_t len;
19 FILE *fp;
20
21 if (symbol_conf.exclude_other && !self->parent)
22 return 0;
23
24 fp = fmemopen(bf, sizeof(bf), "w");
25 if (fp == NULL)
26 return 0;
27
28 len = hist_entry__fprintf(self, NULL, false, 0, fp, total);
29
30 fclose(fp);
31 newtListboxAppendEntry(listbox, bf, self);
32 return len;
33}
34
35static void hist_entry__annotate_browser(struct hist_entry *self)
36{
37 FILE *fp;
38 struct winsize ws;
39 newtComponent form, listbox;
40 struct newtExitStruct es;
41 char *str;
42 size_t line_len, max_line_len = 0;
43 size_t max_usable_width;
44 char *line = NULL;
45
46 if (self->sym == NULL)
47 return;
48
49 if (asprintf(&str, "perf annotate %s | expand", self->sym->name) < 0)
50 return;
51
52 fp = popen(str, "r");
53 if (fp == NULL)
54 goto out_free_str;
55
56 newtPushHelpLine("Press ESC to exit");
57 get_term_dimensions(&ws);
58 listbox = newtListbox(0, 0, ws.ws_row - 5, NEWT_FLAG_SCROLL);
59
60 while (!feof(fp)) {
61 if (getline(&line, &line_len, fp) < 0 || !line_len)
62 break;
63 while (line_len != 0 && isspace(line[line_len - 1]))
64 line[--line_len] = '\0';
65
66 if (line_len > max_line_len)
67 max_line_len = line_len;
68 newtListboxAppendEntry(listbox, line, NULL);
69 }
70 fclose(fp);
71 free(line);
72
73 max_usable_width = ws.ws_col - 22;
74 if (max_line_len > max_usable_width)
75 max_line_len = max_usable_width;
76
77 newtListboxSetWidth(listbox, max_line_len);
78
79 newtCenteredWindow(max_line_len + 2, ws.ws_row - 5, self->sym->name);
80 form = newtForm(NULL, NULL, 0);
81 newtFormAddHotKey(form, NEWT_KEY_ESCAPE);
82 newtFormAddComponents(form, listbox, NULL);
83
84 newtFormRun(form, &es);
85 newtFormDestroy(form);
86 newtPopWindow();
87 newtPopHelpLine();
88out_free_str:
89 free(str);
90}
91
92void perf_session__browse_hists(struct rb_root *hists, u64 session_total,
93 const char *helpline)
94{
95 struct sort_entry *se;
96 struct rb_node *nd;
97 unsigned int width;
98 char *col_width = symbol_conf.col_width_list_str;
99 struct winsize ws;
100 size_t max_len = 0;
101 char str[1024];
102 newtComponent form, listbox;
103 struct newtExitStruct es;
104
105 snprintf(str, sizeof(str), "Samples: %Ld", session_total);
106 newtDrawRootText(0, 0, str);
107 newtPushHelpLine(helpline);
108
109 get_term_dimensions(&ws);
110
111 form = newtForm(NULL, NULL, 0);
112 newtFormAddHotKey(form, NEWT_KEY_ESCAPE);
113
114 listbox = newtListbox(1, 1, ws.ws_row - 2, (NEWT_FLAG_SCROLL |
115 NEWT_FLAG_BORDER |
116 NEWT_FLAG_RETURNEXIT));
117
118 list_for_each_entry(se, &hist_entry__sort_list, list) {
119 if (se->elide)
120 continue;
121 width = strlen(se->header);
122 if (se->width) {
123 if (symbol_conf.col_width_list_str) {
124 if (col_width) {
125 *se->width = atoi(col_width);
126 col_width = strchr(col_width, ',');
127 if (col_width)
128 ++col_width;
129 }
130 }
131 *se->width = max(*se->width, width);
132 }
133 }
134
135 for (nd = rb_first(hists); nd; nd = rb_next(nd)) {
136 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
137 size_t len = hist_entry__append_browser(h, listbox, session_total);
138 if (len > max_len)
139 max_len = len;
140 }
141
142 newtListboxSetWidth(listbox, max_len);
143 newtFormAddComponents(form, listbox, NULL);
144
145 while (1) {
146 struct hist_entry *selection;
147
148 newtFormRun(form, &es);
149 if (es.reason == NEWT_EXIT_HOTKEY)
150 break;
151 selection = newtListboxGetCurrent(listbox);
152 hist_entry__annotate_browser(selection);
153 }
154
155 newtFormDestroy(form);
156}
157
158int browser__show_help(const char *format, va_list ap)
159{
160 int ret;
161 static int backlog;
162 static char msg[1024];
163
164 ret = vsnprintf(msg + backlog, sizeof(msg) - backlog, format, ap);
165 backlog += ret;
166
167 if (msg[backlog - 1] == '\n') {
168 newtPopHelpLine();
169 newtPushHelpLine(msg);
170 newtRefresh();
171 backlog = 0;
172 }
173
174 return ret;
175}
176
177bool use_browser;
178
179void setup_browser(void)
180{
181 if (!isatty(1))
182 return;
183
184 use_browser = true;
185 newtInit();
186 newtCls();
187 newtPushHelpLine(" ");
188}
189
190void exit_browser(void)
191{
192 if (use_browser)
193 newtFinished();
194}