From 642ee1c6df4c8571d8a6846a2623fb54f925ef92 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 30 Oct 2017 13:11:15 -0300 Subject: [PATCH] perf script: Print information about per-event-dump files For a file generated by "perf sched record sleep 50": # perf script --per-event-dump [ perf script: Wrote 23.121 MB perf.data.sched:sched_switch.dump (206015 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_stat_wait.dump (0 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_stat_sleep.dump (0 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_stat_iowait.dump (0 samples) ] [ perf script: Wrote 17.680 MB perf.data.sched:sched_stat_runtime.dump (129342 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_process_fork.dump (24 samples) ] [ perf script: Wrote 11.328 MB perf.data.sched:sched_wakeup.dump (106770 samples) ] [ perf script: Wrote 0.000 MB perf.data.sched:sched_wakeup_new.dump (24 samples) ] [ perf script: Wrote 2.477 MB perf.data.sched:sched_migrate_task.dump (20434 samples) ] # Similar to what is generated by 'perf record'. Based-on-a-patch-by: yuzhoujian Suggested-by: Jiri Olsa Cc: Adrian Hunter Cc: David Ahern Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/r/1508921599-10832-3-git-send-email-yuzhoujian@didichuxing.com Link: http://lkml.kernel.org/n/tip-xuketkkjuk2c0qz546ypd1u7@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 77 +++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 8 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index fb5e49b3bc44..4d198f73b29a 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -210,6 +210,51 @@ static struct { }, }; +struct perf_evsel_script { + char *filename; + FILE *fp; + u64 samples; +}; + +static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel, + struct perf_data_file *file) +{ + struct perf_evsel_script *es = malloc(sizeof(*es)); + + if (es != NULL) { + if (asprintf(&es->filename, "%s.%s.dump", file->path, perf_evsel__name(evsel)) < 0) + goto out_free; + es->fp = fopen(es->filename, "w"); + if (es->fp == NULL) + goto out_free_filename; + es->samples = 0; + } + + return es; +out_free_filename: + zfree(&es->filename); +out_free: + free(es); + return NULL; +} + +static void perf_evsel_script__delete(struct perf_evsel_script *es) +{ + zfree(&es->filename); + fclose(es->fp); + es->fp = NULL; + free(es); +} + +static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp) +{ + struct stat st; + + fstat(fileno(es->fp), &st); + return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n", + st.st_size / 1024.0 / 1024.0, es->filename, es->samples); +} + static inline int output_type(unsigned int type) { switch (type) { @@ -1439,11 +1484,14 @@ 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 = evsel->priv; + struct perf_evsel_script *es = evsel->priv; + FILE *fp = es->fp; if (output[type].fields == 0) return; + ++es->samples; + perf_sample__fprintf_start(sample, thread, evsel, fp); if (PRINT_FIELD(PERIOD)) @@ -1896,7 +1944,7 @@ static void perf_script__fclose_per_event_dump(struct perf_script *script) evlist__for_each_entry(evlist, evsel) { if (!evsel->priv) break; - fclose(evsel->priv); + perf_evsel_script__delete(evsel->priv); evsel->priv = NULL; } } @@ -1906,10 +1954,7 @@ static int perf_script__fopen_per_event_dump(struct perf_script *script) struct perf_evsel *evsel; evlist__for_each_entry(script->session->evlist, evsel) { - char filename[PATH_MAX]; - snprintf(filename, sizeof(filename), "%s.%s.dump", - script->session->file->path, perf_evsel__name(evsel)); - evsel->priv = fopen(filename, "w"); + evsel->priv = perf_evsel_script__new(evsel, script->session->file); if (evsel->priv == NULL) goto out_err_fclose; } @@ -1924,16 +1969,32 @@ static int perf_script__fopen_per_event_dump(struct perf_script *script) static int perf_script__setup_per_event_dump(struct perf_script *script) { struct perf_evsel *evsel; + static struct perf_evsel_script es_stdout; if (script->per_event_dump) return perf_script__fopen_per_event_dump(script); + es_stdout.fp = stdout; + evlist__for_each_entry(script->session->evlist, evsel) - evsel->priv = stdout; + evsel->priv = &es_stdout; return 0; } +static void perf_script__exit_per_event_dump_stats(struct perf_script *script) +{ + struct perf_evsel *evsel; + + evlist__for_each_entry(script->session->evlist, evsel) { + struct perf_evsel_script *es = evsel->priv; + + perf_evsel_script__fprintf(es, stdout); + perf_evsel_script__delete(es); + evsel->priv = NULL; + } +} + static int __cmd_script(struct perf_script *script) { int ret; @@ -1963,7 +2024,7 @@ static int __cmd_script(struct perf_script *script) ret = perf_session__process_events(script->session); if (script->per_event_dump) - perf_script__fclose_per_event_dump(script); + perf_script__exit_per_event_dump_stats(script); if (debug_mode) pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);