This patch will make all print functions receive the fp, add the fp_selection_helper function to select the fp(stdout or the dump_event fp) and open the dump file for all print functions. When the perf script is over, closes the dump_event file and calculates its size.
Changes since v4: - the fp_selection_helper will be invoked by process_event not process_sample_event - replace some printf with fprintf in process_event Changes since v3: - free the evsel->priv by zfree() Changes since v2: - remove the file_name variable and get the data file name from struct perf_session - remove the per_event_dump_file variable and get the dump_event fp from struct perf_evsel - add the fp_selection_helper function to select the fp(stdout or the dump_event fp) and open the dump file for all print functions if evname and last evsel name is not the same. - close the dump file for all the evsels and calculate the dump file's size at the end of the perf script. - solve the segmentation fault generated by perf script --per-event-dump --show-mmap-events Changes since v1: - modify the dump file name to <ORIGINAL PERF DATA FILE NAME>-script-dump-<EVENT NAME>.txt ect. perf.data-script-dump-cycles.txt, perf.data-script-dump-cs.txt - split the original patch(Make all those related functions receive the file pointer) to two patches, and this is the second part of the original one. Signed-off-by: yuzhoujian <yuzhouj...@didichuxing.com> --- tools/perf/builtin-script.c | 107 +++++++++++++++++++++++++++++++++++--------- tools/perf/util/session.c | 19 ++++++++ 2 files changed, 106 insertions(+), 20 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 81f141f..8d98349 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1431,6 +1431,50 @@ static int data_src__fprintf(u64 data_src, FILE *fp) return fprintf(fp, "%-*s", maxlen, out); } +static FILE *fp_selection_helper(struct perf_script *script, struct perf_evsel *evsel) +{ + const char *evname; + char *filename; + FILE *fp; + struct perf_tool *tool = &script->tool; + struct perf_script_evsel *ps; + + evname = perf_evsel__name(evsel); + if (tool->per_event_dump) { + ps = (struct perf_script_evsel *)evsel->priv; + + /* if evname and last evsel name is not the same, opens another dump file. */ + if (evname != tool->last_evsel_name) { + if (asprintf(&filename, "%s%s%s%s", script->session->file->path, + "-script-dump-", evname, ".txt") < 0) + BUG_ON("fail to add the suffix for dump file's name!\n"); + + fp = fopen(filename, "a+"); + if (!fp) + BUG_ON("fail to open the dump file!\n"); + + if (!ps) { + ps = zalloc(sizeof(struct perf_script_evsel)); + if (!ps) + BUG_ON("fail to create a perf_script_evsel struct!\n"); + ps->samples = 0; + } + ps->filename = filename; + ps->dump_evsel_fp = fp; + tool->last_evsel_name = evname; + evsel->priv = ps; + } else { + if (ps->dump_evsel_fp) + fp = ps->dump_evsel_fp; + else + BUG_ON("fail to get the dump file's fp!\n"); + } + } else { + fp = stdout; + } + return fp; +} + static void process_event(struct perf_script *script, struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al, @@ -1439,15 +1483,25 @@ static void process_event(struct perf_script *script, struct thread *thread = al->thread; struct perf_event_attr *attr = &evsel->attr; unsigned int type = output_type(attr->type); - FILE *fp = stdout; + struct perf_script_evsel *ps; + struct perf_tool *tool = &script->tool; + FILE *fp; + + fp = fp_selection_helper(script, evsel); if (output[type].fields == 0) return; + if (tool->per_event_dump) { + ps = (struct perf_script_evsel *)evsel->priv; + ps->samples++; + evsel->priv = ps; + } + perf_sample__fprintf_start(sample, thread, evsel, fp); if (PRINT_FIELD(PERIOD)) - printf("%10" PRIu64 " ", sample->period); + fprintf(fp, "%10" PRIu64 " ", sample->period); if (PRINT_FIELD(EVNAME)) { const char *evname = perf_evsel__name(evsel); @@ -1455,7 +1509,7 @@ static void process_event(struct perf_script *script, if (!script->name_width) script->name_width = perf_evlist__max_name_len(script->session->evlist); - printf("%*s: ", script->name_width, + fprintf(fp, "%*s: ", script->name_width, evname ? evname : "[unknown]"); } @@ -1513,8 +1567,8 @@ static void process_event(struct perf_script *script, perf_sample__fprintf_insn(sample, attr, thread, machine, fp); if (PRINT_FIELD(PHYS_ADDR)) - printf("%16" PRIx64, sample->phys_addr); - printf("\n"); + fprintf(fp, "%16" PRIx64, sample->phys_addr); + fprintf(fp, "\n"); } static struct scripting_ops *scripting_ops; @@ -1671,6 +1725,7 @@ static int process_comm_event(struct perf_tool *tool, struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + FILE *fp; int ret = -1; thread = machine__findnew_thread(machine, event->comm.pid, event->comm.tid); @@ -1688,8 +1743,9 @@ static int process_comm_event(struct perf_tool *tool, sample->tid = event->comm.tid; sample->pid = event->comm.pid; } - perf_sample__fprintf_start(sample, thread, evsel, stdout); - perf_event__fprintf(event, stdout); + fp = fp_selection_helper(script, evsel); + perf_sample__fprintf_start(sample, thread, evsel, fp); + perf_event__fprintf(event, fp); ret = 0; out: thread__put(thread); @@ -1705,6 +1761,7 @@ static int process_namespaces_event(struct perf_tool *tool, struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + FILE *fp; int ret = -1; thread = machine__findnew_thread(machine, event->namespaces.pid, @@ -1723,8 +1780,9 @@ static int process_namespaces_event(struct perf_tool *tool, sample->tid = event->namespaces.tid; sample->pid = event->namespaces.pid; } - perf_sample__fprintf_start(sample, thread, evsel, stdout); - perf_event__fprintf(event, stdout); + fp = fp_selection_helper(script, evsel); + perf_sample__fprintf_start(sample, thread, evsel, fp); + perf_event__fprintf(event, fp); ret = 0; out: thread__put(thread); @@ -1740,6 +1798,7 @@ static int process_fork_event(struct perf_tool *tool, struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + FILE *fp; if (perf_event__process_fork(tool, event, sample, machine) < 0) return -1; @@ -1756,8 +1815,9 @@ static int process_fork_event(struct perf_tool *tool, sample->tid = event->fork.tid; sample->pid = event->fork.pid; } - perf_sample__fprintf_start(sample, thread, evsel, stdout); - perf_event__fprintf(event, stdout); + fp = fp_selection_helper(script, evsel); + perf_sample__fprintf_start(sample, thread, evsel, fp); + perf_event__fprintf(event, fp); thread__put(thread); return 0; @@ -1772,6 +1832,7 @@ static int process_exit_event(struct perf_tool *tool, struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + FILE *fp; thread = machine__findnew_thread(machine, event->fork.pid, event->fork.tid); if (thread == NULL) { @@ -1785,8 +1846,9 @@ static int process_exit_event(struct perf_tool *tool, sample->tid = event->fork.tid; sample->pid = event->fork.pid; } - perf_sample__fprintf_start(sample, thread, evsel, stdout); - perf_event__fprintf(event, stdout); + fp = fp_selection_helper(script, evsel); + perf_sample__fprintf_start(sample, thread, evsel, fp); + perf_event__fprintf(event, fp); if (perf_event__process_exit(tool, event, sample, machine) < 0) err = -1; @@ -1804,6 +1866,7 @@ static int process_mmap_event(struct perf_tool *tool, struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + FILE *fp; if (perf_event__process_mmap(tool, event, sample, machine) < 0) return -1; @@ -1820,8 +1883,9 @@ static int process_mmap_event(struct perf_tool *tool, sample->tid = event->mmap.tid; sample->pid = event->mmap.pid; } - perf_sample__fprintf_start(sample, thread, evsel, stdout); - perf_event__fprintf(event, stdout); + fp = fp_selection_helper(script, evsel); + perf_sample__fprintf_start(sample, thread, evsel, fp); + perf_event__fprintf(event, fp); thread__put(thread); return 0; } @@ -1835,6 +1899,7 @@ static int process_mmap2_event(struct perf_tool *tool, struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + FILE *fp; if (perf_event__process_mmap2(tool, event, sample, machine) < 0) return -1; @@ -1851,8 +1916,9 @@ static int process_mmap2_event(struct perf_tool *tool, sample->tid = event->mmap2.tid; sample->pid = event->mmap2.pid; } - perf_sample__fprintf_start(sample, thread, evsel, stdout); - perf_event__fprintf(event, stdout); + fp = fp_selection_helper(script, evsel); + perf_sample__fprintf_start(sample, thread, evsel, fp); + perf_event__fprintf(event, fp); thread__put(thread); return 0; } @@ -1866,6 +1932,7 @@ static int process_switch_event(struct perf_tool *tool, struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, sample->id); + FILE *fp; if (perf_event__process_switch(tool, event, sample, machine) < 0) return -1; @@ -1876,9 +1943,9 @@ static int process_switch_event(struct perf_tool *tool, pr_debug("problem processing SWITCH event, skipping it.\n"); return -1; } - - perf_sample__fprintf_start(sample, thread, evsel, stdout); - perf_event__fprintf(event, stdout); + fp = fp_selection_helper(script, evsel); + perf_sample__fprintf_start(sample, thread, evsel, fp); + perf_event__fprintf(event, fp); thread__put(thread); return 0; } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b3fd62f..0a4784f 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -8,6 +8,8 @@ #include <unistd.h> #include <sys/types.h> #include <sys/mman.h> +#include <sys/stat.h> +#include <stdio.h> #include "evlist.h" #include "evsel.h" @@ -1828,6 +1830,9 @@ static int __perf_session__process_events(struct perf_session *session, { struct ordered_events *oe = &session->ordered_events; struct perf_tool *tool = session->tool; + struct perf_evlist *evlist = session->evlist; + struct perf_evsel *evsel; + struct perf_script_evsel *ps; int fd = perf_data_file__fd(session->file); u64 head, page_offset, file_offset, file_pos, size; int err, mmap_prot, mmap_flags, map_idx = 0; @@ -1835,6 +1840,7 @@ static int __perf_session__process_events(struct perf_session *session, char *buf, *mmaps[NUM_MMAPS]; union perf_event *event; struct ui_progress prog; + struct stat statbuf; s64 skip; perf_tool__fill_defaults(tool); @@ -1940,6 +1946,19 @@ static int __perf_session__process_events(struct perf_session *session, ordered_events__reinit(&session->ordered_events); auxtrace__free_events(session); session->one_mmap = false; + /* Closes the dump_event file and calculates its size at last. */ + if (tool->per_event_dump) { + evlist__for_each_entry(evlist, evsel) { + ps = (struct perf_script_evsel *)evsel->priv; + if (!ps) + BUG_ON("fail to get the perf_script_evsel\n"); + stat(ps->filename, &statbuf); + fprintf(stderr, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n", + statbuf.st_size / 1024.0 / 1024.0, ps->filename, ps->samples); + fclose(ps->dump_evsel_fp); + zfree(&evsel->priv); + } + } return err; } -- 1.8.3.1