Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf script: Allow creating per-event dump files

Introduce a new option to dump trace output to files named by the
monitored events and update perf-script documentation accordingly.

Shown below is output of perf script command with the newly introduced
option.

$ perf record -e cycles -e cs -ag -- sleep 1
$ perf script --per-event-dump
$ ls
perf.data.cycles.dump perf.data.cs.dump

Without per-event-dump support, drawing flamegraphs for different events
would require post processing to separate events. You can monitor only
one event at a time if you want to get flamegraphs for different events.
Using this option, you can get the trace output files named by the
monitored events, and could draw flamegraphs according to the event's
name.

Based-on-a-patch-by: yuzhoujian <yuzhoujian@didichuxing.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1508921599-10832-3-git-send-email-yuzhoujian@didichuxing.com
Link: http://lkml.kernel.org/n/tip-8ngzsjdhgiovkupl3r5yy570@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+62 -1
+4
tools/perf/Documentation/perf-script.txt
··· 325 325 Set the maximum number of program blocks to print with brstackasm for 326 326 each sample. 327 327 328 + --per-event-dump:: 329 + Create per event files with a "perf.data.EVENT.dump" name instead of 330 + printing to stdout, useful, for instance, for generating flamegraphs. 331 + 328 332 --inline:: 329 333 If a callgraph address belongs to an inlined function, the inline stack 330 334 will be printed. Each entry has function name and file/line. Enabled by
+58 -1
tools/perf/builtin-script.c
··· 1392 1392 bool show_switch_events; 1393 1393 bool show_namespace_events; 1394 1394 bool allocated; 1395 + bool per_event_dump; 1395 1396 struct cpu_map *cpus; 1396 1397 struct thread_map *threads; 1397 1398 int name_width; ··· 1439 1438 struct thread *thread = al->thread; 1440 1439 struct perf_event_attr *attr = &evsel->attr; 1441 1440 unsigned int type = output_type(attr->type); 1442 - FILE *fp = stdout; 1441 + FILE *fp = evsel->priv; 1443 1442 1444 1443 if (output[type].fields == 0) 1445 1444 return; ··· 1888 1887 session_done = 1; 1889 1888 } 1890 1889 1890 + static void perf_script__fclose_per_event_dump(struct perf_script *script) 1891 + { 1892 + struct perf_evlist *evlist = script->session->evlist; 1893 + struct perf_evsel *evsel; 1894 + 1895 + evlist__for_each_entry(evlist, evsel) { 1896 + if (!evsel->priv) 1897 + break; 1898 + fclose(evsel->priv); 1899 + evsel->priv = NULL; 1900 + } 1901 + } 1902 + 1903 + static int perf_script__fopen_per_event_dump(struct perf_script *script) 1904 + { 1905 + struct perf_evsel *evsel; 1906 + 1907 + evlist__for_each_entry(script->session->evlist, evsel) { 1908 + char filename[PATH_MAX]; 1909 + snprintf(filename, sizeof(filename), "%s.%s.dump", 1910 + script->session->file->path, perf_evsel__name(evsel)); 1911 + evsel->priv = fopen(filename, "w"); 1912 + if (evsel->priv == NULL) 1913 + goto out_err_fclose; 1914 + } 1915 + 1916 + return 0; 1917 + 1918 + out_err_fclose: 1919 + perf_script__fclose_per_event_dump(script); 1920 + return -1; 1921 + } 1922 + 1923 + static int perf_script__setup_per_event_dump(struct perf_script *script) 1924 + { 1925 + struct perf_evsel *evsel; 1926 + 1927 + if (script->per_event_dump) 1928 + return perf_script__fopen_per_event_dump(script); 1929 + 1930 + evlist__for_each_entry(script->session->evlist, evsel) 1931 + evsel->priv = stdout; 1932 + 1933 + return 0; 1934 + } 1935 + 1891 1936 static int __cmd_script(struct perf_script *script) 1892 1937 { 1893 1938 int ret; ··· 1955 1908 if (script->show_namespace_events) 1956 1909 script->tool.namespaces = process_namespaces_event; 1957 1910 1911 + if (perf_script__setup_per_event_dump(script)) { 1912 + pr_err("Couldn't create the per event dump files\n"); 1913 + return -1; 1914 + } 1915 + 1958 1916 ret = perf_session__process_events(script->session); 1917 + 1918 + if (script->per_event_dump) 1919 + perf_script__fclose_per_event_dump(script); 1959 1920 1960 1921 if (debug_mode) 1961 1922 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); ··· 2882 2827 "Show context switch events (if recorded)"), 2883 2828 OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events, 2884 2829 "Show namespace events (if recorded)"), 2830 + OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump, 2831 + "Dump trace output to files named by the monitored events"), 2885 2832 OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 2886 2833 OPT_INTEGER(0, "max-blocks", &max_blocks, 2887 2834 "Maximum number of code blocks to dump with brstackinsn"),