aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2019-03-09 00:56:20 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-03-11 13:03:43 -0400
commit75065a85a9705ad4c0135f07fd4467d46ff342a3 (patch)
tree26c02de0a7d36c1a0aee67525195f747dbd413d6
parente51f806198306a8ad7ae6e34d1af0716ef73da80 (diff)
perf report: Use less for scripts output
The UI viewer for scripts output has a lot of limitations: limited size, no search or save function, slow, and various other issues. Just use 'less' to display directly on the terminal instead. This won't work in GTK mode, but GTK doesn't support these context menus anyways. If that is ever done could use an terminal for the output. Signed-off-by: Andi Kleen <ak@linux.intel.com> Acked-by: Feng Tang <feng.tang@intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Link: http://lkml.kernel.org/r/20190309055628.21617-8-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/ui/browsers/scripts.c130
1 files changed, 17 insertions, 113 deletions
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
index 90a32ac69e76..7f36630694bf 100644
--- a/tools/perf/ui/browsers/scripts.c
+++ b/tools/perf/ui/browsers/scripts.c
@@ -1,35 +1,12 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <elf.h>
3#include <inttypes.h>
4#include <sys/ttydefaults.h>
5#include <string.h>
6#include "../../util/sort.h" 2#include "../../util/sort.h"
7#include "../../util/util.h" 3#include "../../util/util.h"
8#include "../../util/hist.h" 4#include "../../util/hist.h"
9#include "../../util/debug.h" 5#include "../../util/debug.h"
10#include "../../util/symbol.h" 6#include "../../util/symbol.h"
11#include "../browser.h" 7#include "../browser.h"
12#include "../helpline.h"
13#include "../libslang.h" 8#include "../libslang.h"
14 9
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 10#define SCRIPT_NAMELEN 128
34#define SCRIPT_MAX_NO 64 11#define SCRIPT_MAX_NO 64
35/* 12/*
@@ -73,69 +50,29 @@ static int list_scripts(char *script_name)
73 return ret; 50 return ret;
74} 51}
75 52
76static void script_browser__write(struct ui_browser *browser, 53static void run_script(char *cmd)
77 void *entry, int row)
78{ 54{
79 struct script_line *sline = list_entry(entry, struct script_line, node); 55 pr_debug("Running %s\n", cmd);
80 bool current_entry = ui_browser__is_current_entry(browser, row); 56 SLang_reset_tty();
81 57 if (system(cmd) < 0)
82 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : 58 pr_warning("Cannot run %s\n", cmd);
83 HE_COLORSET_NORMAL); 59 /*
84 60 * SLang doesn't seem to reset the whole terminal, so be more
85 ui_browser__write_nstring(browser, sline->line, browser->width); 61 * forceful to get back to the original state.
62 */
63 printf("\033[c\033[H\033[J");
64 fflush(stdout);
65 SLang_init_tty(0, 0, 0);
66 SLsmg_refresh();
86} 67}
87 68
88static int script_browser__run(struct perf_script_browser *browser)
89{
90 int key;
91
92 if (ui_browser__show(&browser->b, browser->script_name,
93 "Press ESC to exit") < 0)
94 return -1;
95
96 while (1) {
97 key = ui_browser__run(&browser->b, 0);
98
99 /* We can add some special key handling here if needed */
100 break;
101 }
102
103 ui_browser__hide(&browser->b);
104 return key;
105}
106
107
108int script_browse(const char *script_opt) 69int script_browse(const char *script_opt)
109{ 70{
110 char cmd[SCRIPT_FULLPATH_LEN*2], script_name[SCRIPT_FULLPATH_LEN]; 71 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 72
136 memset(script_name, 0, SCRIPT_FULLPATH_LEN); 73 memset(script_name, 0, SCRIPT_FULLPATH_LEN);
137 if (list_scripts(script_name)) 74 if (list_scripts(script_name))
138 goto exit; 75 return -1;
139 76
140 sprintf(cmd, "perf script -s %s ", script_name); 77 sprintf(cmd, "perf script -s %s ", script_name);
141 78
@@ -147,42 +84,9 @@ int script_browse(const char *script_opt)
147 strcat(cmd, input_name); 84 strcat(cmd, input_name);
148 } 85 }
149 86
150 strcat(cmd, " 2>&1"); 87 strcat(cmd, " 2>&1 | less");
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 free(line);
178 pclose(fp);
179 88
180 script.nr_lines = nr_entries; 89 run_script(cmd);
181 script.b.nr_entries = nr_entries;
182 script.b.entries = &script.entries;
183 90
184 ret = script_browser__run(&script); 91 return 0;
185exit:
186 free(buf);
187 return ret;
188} 92}