aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorFeng Tang <feng.tang@intel.com>2012-10-29 23:56:04 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-10-29 09:52:53 -0400
commit66517826664fa910d4bc5f32a5abff6bcd8657c5 (patch)
tree0dfb8b6b1320c26f76e97367bb471f7dd07af3e7 /tools/perf
parent49e639e256ea18fb92f609dd6be09883cd9d05aa (diff)
perf scripts browser: Add a browser for perf script
Create a script browser, so that user can check all the available scripts for current perf data file and run them inside the main perf report or annotation browsers, for all perf samples or for samples belong to one thread/symbol. Please be noted: current script browser is only for report use, and doesn't cover the record phase, IOW it must run against one existing perf data file. The work flow is, users can use function key to list all the available scripts for current perf data file in system and chose one, which will be executed with popen("perf script -s xxx.xx",) and all the output lines are put into one ui browser, pressing 'q' or left arrow key will make it return to previous browser. Signed-off-by: Feng Tang <feng.tang@intel.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1351569369-26732-4-git-send-email-feng.tang@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/ui/browsers/scripts.c189
-rw-r--r--tools/perf/util/hist.h7
3 files changed, 200 insertions, 0 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index ec63d53cd87f..7e25f59e5e89 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -593,6 +593,7 @@ ifndef NO_NEWT
593 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o 593 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
594 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o 594 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
595 LIB_OBJS += $(OUTPUT)ui/browsers/map.o 595 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
596 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
596 LIB_OBJS += $(OUTPUT)ui/progress.o 597 LIB_OBJS += $(OUTPUT)ui/progress.o
597 LIB_OBJS += $(OUTPUT)ui/util.o 598 LIB_OBJS += $(OUTPUT)ui/util.o
598 LIB_OBJS += $(OUTPUT)ui/tui/setup.o 599 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
@@ -909,6 +910,9 @@ $(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
909$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 910$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
910 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 911 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
911 912
913$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
914 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
915
912$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 916$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
913 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 917 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
914 918
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
new file mode 100644
index 000000000000..cbbd44b0d93e
--- /dev/null
+++ b/tools/perf/ui/browsers/scripts.c
@@ -0,0 +1,189 @@
1#include <elf.h>
2#include <newt.h>
3#include <inttypes.h>
4#include <sys/ttydefaults.h>
5#include <string.h>
6#include "../../util/sort.h"
7#include "../../util/util.h"
8#include "../../util/hist.h"
9#include "../../util/debug.h"
10#include "../../util/symbol.h"
11#include "../browser.h"
12#include "../helpline.h"
13#include "../libslang.h"
14
15/* 2048 lines should be enough for a script output */
16#define MAX_LINES 2048
17
18/* 160 bytes for one output line */
19#define AVERAGE_LINE_LEN 160
20
21struct script_line {
22 struct list_head node;
23 char line[AVERAGE_LINE_LEN];
24};
25
26struct perf_script_browser {
27 struct ui_browser b;
28 struct list_head entries;
29 const char *script_name;
30 int nr_lines;
31};
32
33#define SCRIPT_NAMELEN 128
34#define SCRIPT_MAX_NO 64
35/*
36 * Usually the full path for a script is:
37 * /home/username/libexec/perf-core/scripts/python/xxx.py
38 * /home/username/libexec/perf-core/scripts/perl/xxx.pl
39 * So 256 should be long enough to contain the full path.
40 */
41#define SCRIPT_FULLPATH_LEN 256
42
43/*
44 * When success, will copy the full path of the selected script
45 * into the buffer pointed by script_name, and return 0.
46 * Return -1 on failure.
47 */
48static int list_scripts(char *script_name)
49{
50 char *buf, *names[SCRIPT_MAX_NO], *paths[SCRIPT_MAX_NO];
51 int i, num, choice, ret = -1;
52
53 /* Preset the script name to SCRIPT_NAMELEN */
54 buf = malloc(SCRIPT_MAX_NO * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN));
55 if (!buf)
56 return ret;
57
58 for (i = 0; i < SCRIPT_MAX_NO; i++) {
59 names[i] = buf + i * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN);
60 paths[i] = names[i] + SCRIPT_NAMELEN;
61 }
62
63 num = find_scripts(names, paths);
64 if (num > 0) {
65 choice = ui__popup_menu(num, names);
66 if (choice < num && choice >= 0) {
67 strcpy(script_name, paths[choice]);
68 ret = 0;
69 }
70 }
71
72 free(buf);
73 return ret;
74}
75
76static void script_browser__write(struct ui_browser *browser,
77 void *entry, int row)
78{
79 struct script_line *sline = list_entry(entry, struct script_line, node);
80 bool current_entry = ui_browser__is_current_entry(browser, row);
81
82 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
83 HE_COLORSET_NORMAL);
84
85 slsmg_write_nstring(sline->line, browser->width);
86}
87
88static int script_browser__run(struct perf_script_browser *self)
89{
90 int key;
91
92 if (ui_browser__show(&self->b, self->script_name,
93 "Press <- or ESC to exit") < 0)
94 return -1;
95
96 while (1) {
97 key = ui_browser__run(&self->b, 0);
98
99 /* We can add some special key handling here if needed */
100 break;
101 }
102
103 ui_browser__hide(&self->b);
104 return key;
105}
106
107
108int script_browse(const char *script_opt)
109{
110 char cmd[SCRIPT_FULLPATH_LEN*2], script_name[SCRIPT_FULLPATH_LEN];
111 char *line = NULL;
112 size_t len = 0;
113 ssize_t retlen;
114 int ret = -1, nr_entries = 0;
115 FILE *fp;
116 void *buf;
117 struct script_line *sline;
118
119 struct perf_script_browser script = {
120 .b = {
121 .refresh = ui_browser__list_head_refresh,
122 .seek = ui_browser__list_head_seek,
123 .write = script_browser__write,
124 },
125 .script_name = script_name,
126 };
127
128 INIT_LIST_HEAD(&script.entries);
129
130 /* Save each line of the output in one struct script_line object. */
131 buf = zalloc((sizeof(*sline)) * MAX_LINES);
132 if (!buf)
133 return -1;
134 sline = buf;
135
136 memset(script_name, 0, SCRIPT_FULLPATH_LEN);
137 if (list_scripts(script_name))
138 goto exit;
139
140 sprintf(cmd, "perf script -s %s ", script_name);
141
142 if (script_opt)
143 strcat(cmd, script_opt);
144
145 if (input_name) {
146 strcat(cmd, " -i ");
147 strcat(cmd, input_name);
148 }
149
150 strcat(cmd, " 2>&1");
151
152 fp = popen(cmd, "r");
153 if (!fp)
154 goto exit;
155
156 while ((retlen = getline(&line, &len, fp)) != -1) {
157 strncpy(sline->line, line, AVERAGE_LINE_LEN);
158
159 /* If one output line is very large, just cut it short */
160 if (retlen >= AVERAGE_LINE_LEN) {
161 sline->line[AVERAGE_LINE_LEN - 1] = '\0';
162 sline->line[AVERAGE_LINE_LEN - 2] = '\n';
163 }
164 list_add_tail(&sline->node, &script.entries);
165
166 if (script.b.width < retlen)
167 script.b.width = retlen;
168
169 if (nr_entries++ >= MAX_LINES - 1)
170 break;
171 sline++;
172 }
173
174 if (script.b.width > AVERAGE_LINE_LEN)
175 script.b.width = AVERAGE_LINE_LEN;
176
177 if (line)
178 free(line);
179 pclose(fp);
180
181 script.nr_lines = nr_entries;
182 script.b.nr_entries = nr_entries;
183 script.b.entries = &script.entries;
184
185 ret = script_browser__run(&script);
186exit:
187 free(buf);
188 return ret;
189}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index c751624d4153..b87460971736 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -165,6 +165,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
165int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 165int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
166 void(*timer)(void *arg), void *arg, 166 void(*timer)(void *arg), void *arg,
167 int refresh); 167 int refresh);
168int script_browse(const char *script_opt);
168#else 169#else
169static inline 170static inline
170int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, 171int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
@@ -186,6 +187,12 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
186{ 187{
187 return 0; 188 return 0;
188} 189}
190
191static inline int script_browse(const char *script_opt)
192{
193 return 0;
194}
195
189#define K_LEFT -1 196#define K_LEFT -1
190#define K_RIGHT -2 197#define K_RIGHT -2
191#endif 198#endif