aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorFeng Tang <feng.tang@intel.com>2013-02-03 01:38:20 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-02-06 16:09:24 -0500
commit341487ab561f3937a5283dd77c5660b1ee3b1f9e (patch)
tree0daeec601b75739c1d1b6ae26cee0ff6d8f48330 /tools/perf
parent0fbdad078a70ed72248c3d30fe32e45e83be00d1 (diff)
perf hists browser: Add option for runtime switching perf data file
Based on perf report/top/scripts browser integration idea from acme. This will enable user to runtime switch the data file, when this option is selected, it will popup all the legal data files in current working directory, and the filename selected by user is saved in the global variable "input_name", and a new key 'K_SWITCH_INPUT_DATA' will be passed back to the built-in command which will perform the switch. This initial version only enables it for 'perf report'. v2: rebase to latest 'perf/core' branch (6e1d4dd) of acme's perf tree 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/1359873501-24541-1-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/ui/browsers/hists.c112
-rw-r--r--tools/perf/ui/keysyms.h1
2 files changed, 112 insertions, 1 deletions
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 20ccd57753f7..aa22704047d6 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1241,6 +1241,96 @@ static inline bool is_report_browser(void *timer)
1241 return timer == NULL; 1241 return timer == NULL;
1242} 1242}
1243 1243
1244/*
1245 * Only runtime switching of perf data file will make "input_name" point
1246 * to a malloced buffer. So add "is_input_name_malloced" flag to decide
1247 * whether we need to call free() for current "input_name" during the switch.
1248 */
1249static bool is_input_name_malloced = false;
1250
1251static int switch_data_file(void)
1252{
1253 char *pwd, *options[32], *abs_path[32], *tmp;
1254 DIR *pwd_dir;
1255 int nr_options = 0, choice = -1, ret = -1;
1256 struct dirent *dent;
1257
1258 pwd = getenv("PWD");
1259 if (!pwd)
1260 return ret;
1261
1262 pwd_dir = opendir(pwd);
1263 if (!pwd_dir)
1264 return ret;
1265
1266 memset(options, 0, sizeof(options));
1267 memset(options, 0, sizeof(abs_path));
1268
1269 while ((dent = readdir(pwd_dir))) {
1270 char path[PATH_MAX];
1271 u64 magic;
1272 char *name = dent->d_name;
1273 FILE *file;
1274
1275 if (!(dent->d_type == DT_REG))
1276 continue;
1277
1278 snprintf(path, sizeof(path), "%s/%s", pwd, name);
1279
1280 file = fopen(path, "r");
1281 if (!file)
1282 continue;
1283
1284 if (fread(&magic, 1, 8, file) < 8)
1285 goto close_file_and_continue;
1286
1287 if (is_perf_magic(magic)) {
1288 options[nr_options] = strdup(name);
1289 if (!options[nr_options])
1290 goto close_file_and_continue;
1291
1292 abs_path[nr_options] = strdup(path);
1293 if (!abs_path[nr_options]) {
1294 free(options[nr_options]);
1295 ui__warning("Can't search all data files due to memory shortage.\n");
1296 fclose(file);
1297 break;
1298 }
1299
1300 nr_options++;
1301 }
1302
1303close_file_and_continue:
1304 fclose(file);
1305 if (nr_options >= 32) {
1306 ui__warning("Too many perf data files in PWD!\n"
1307 "Only the first 32 files will be listed.\n");
1308 break;
1309 }
1310 }
1311 closedir(pwd_dir);
1312
1313 if (nr_options) {
1314 choice = ui__popup_menu(nr_options, options);
1315 if (choice < nr_options && choice >= 0) {
1316 tmp = strdup(abs_path[choice]);
1317 if (tmp) {
1318 if (is_input_name_malloced)
1319 free((void *)input_name);
1320 input_name = tmp;
1321 is_input_name_malloced = true;
1322 ret = 0;
1323 } else
1324 ui__warning("Data switch failed due to memory shortage!\n");
1325 }
1326 }
1327
1328 free_popup_options(options, nr_options);
1329 free_popup_options(abs_path, nr_options);
1330 return ret;
1331}
1332
1333
1244static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, 1334static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1245 const char *helpline, const char *ev_name, 1335 const char *helpline, const char *ev_name,
1246 bool left_exits, 1336 bool left_exits,
@@ -1275,7 +1365,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1275 int choice = 0, 1365 int choice = 0,
1276 annotate = -2, zoom_dso = -2, zoom_thread = -2, 1366 annotate = -2, zoom_dso = -2, zoom_thread = -2,
1277 annotate_f = -2, annotate_t = -2, browse_map = -2; 1367 annotate_f = -2, annotate_t = -2, browse_map = -2;
1278 int scripts_comm = -2, scripts_symbol = -2, scripts_all = -2; 1368 int scripts_comm = -2, scripts_symbol = -2,
1369 scripts_all = -2, switch_data = -2;
1279 1370
1280 nr_options = 0; 1371 nr_options = 0;
1281 1372
@@ -1332,6 +1423,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1332 if (is_report_browser(hbt)) 1423 if (is_report_browser(hbt))
1333 goto do_scripts; 1424 goto do_scripts;
1334 continue; 1425 continue;
1426 case 's':
1427 if (is_report_browser(hbt))
1428 goto do_data_switch;
1429 continue;
1335 case K_F1: 1430 case K_F1:
1336 case 'h': 1431 case 'h':
1337 case '?': 1432 case '?':
@@ -1351,6 +1446,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1351 "d Zoom into current DSO\n" 1446 "d Zoom into current DSO\n"
1352 "t Zoom into current Thread\n" 1447 "t Zoom into current Thread\n"
1353 "r Run available scripts('perf report' only)\n" 1448 "r Run available scripts('perf report' only)\n"
1449 "s Switch to another data file in PWD ('perf report' only)\n"
1354 "P Print histograms to perf.hist.N\n" 1450 "P Print histograms to perf.hist.N\n"
1355 "V Verbose (DSO names in callchains, etc)\n" 1451 "V Verbose (DSO names in callchains, etc)\n"
1356 "/ Filter symbol by name"); 1452 "/ Filter symbol by name");
@@ -1458,6 +1554,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1458 if (asprintf(&options[nr_options], "Run scripts for all samples") > 0) 1554 if (asprintf(&options[nr_options], "Run scripts for all samples") > 0)
1459 scripts_all = nr_options++; 1555 scripts_all = nr_options++;
1460 1556
1557 if (is_report_browser(hbt) && asprintf(&options[nr_options],
1558 "Switch to another data file in PWD") > 0)
1559 switch_data = nr_options++;
1461add_exit_option: 1560add_exit_option:
1462 options[nr_options++] = (char *)"Exit"; 1561 options[nr_options++] = (char *)"Exit";
1463retry_popup_menu: 1562retry_popup_menu:
@@ -1568,6 +1667,16 @@ do_scripts:
1568 1667
1569 script_browse(script_opt); 1668 script_browse(script_opt);
1570 } 1669 }
1670 /* Switch to another data file */
1671 else if (choice == switch_data) {
1672do_data_switch:
1673 if (!switch_data_file()) {
1674 key = K_SWITCH_INPUT_DATA;
1675 break;
1676 } else
1677 ui__warning("Won't switch the data files due to\n"
1678 "no valid data file get selected!\n");
1679 }
1571 } 1680 }
1572out_free_stack: 1681out_free_stack:
1573 pstack__delete(fstack); 1682 pstack__delete(fstack);
@@ -1694,6 +1803,7 @@ browse_hists:
1694 "Do you really want to exit?")) 1803 "Do you really want to exit?"))
1695 continue; 1804 continue;
1696 /* Fall thru */ 1805 /* Fall thru */
1806 case K_SWITCH_INPUT_DATA:
1697 case 'q': 1807 case 'q':
1698 case CTRL('c'): 1808 case CTRL('c'):
1699 goto out; 1809 goto out;
diff --git a/tools/perf/ui/keysyms.h b/tools/perf/ui/keysyms.h
index 809eca5707fa..65092d576b4e 100644
--- a/tools/perf/ui/keysyms.h
+++ b/tools/perf/ui/keysyms.h
@@ -23,5 +23,6 @@
23#define K_TIMER -1 23#define K_TIMER -1
24#define K_ERROR -2 24#define K_ERROR -2
25#define K_RESIZE -3 25#define K_RESIZE -3
26#define K_SWITCH_INPUT_DATA -4
26 27
27#endif /* _PERF_KEYSYMS_H_ */ 28#endif /* _PERF_KEYSYMS_H_ */