| From bb9f5d0044074d3dc9624418b52bc60818a8bfdd Mon Sep 17 00:00:00 2001 |
| From: Srikar Dronamraju <srikar@linux.vnet.ibm.com> |
| Date: Wed, 4 Sep 2019 15:17:37 +0530 |
| Subject: [PATCH] perf stat: Reset previous counts on repeat with interval |
| |
| commit b63fd11cced17fcb8e133def29001b0f6aaa5e06 upstream. |
| |
| When using 'perf stat' with repeat and interval option, it shows wrong |
| values for events. |
| |
| The wrong values will be shown for the first interval on the second and |
| subsequent repetitions. |
| |
| Without the fix: |
| |
| # perf stat -r 3 -I 2000 -e faults -e sched:sched_switch -a sleep 5 |
| |
| 2.000282489 53 faults |
| 2.000282489 513 sched:sched_switch |
| 4.005478208 3,721 faults |
| 4.005478208 2,666 sched:sched_switch |
| 5.025470933 395 faults |
| 5.025470933 1,307 sched:sched_switch |
| 2.009602825 1,84,46,74,40,73,70,95,47,520 faults <------ |
| 2.009602825 1,84,46,74,40,73,70,95,49,568 sched:sched_switch <------ |
| 4.019612206 4,730 faults |
| 4.019612206 2,746 sched:sched_switch |
| 5.039615484 3,953 faults |
| 5.039615484 1,496 sched:sched_switch |
| 2.000274620 1,84,46,74,40,73,70,95,47,520 faults <------ |
| 2.000274620 1,84,46,74,40,73,70,95,47,520 sched:sched_switch <------ |
| 4.000480342 4,282 faults |
| 4.000480342 2,303 sched:sched_switch |
| 5.000916811 1,322 faults |
| 5.000916811 1,064 sched:sched_switch |
| # |
| |
| prev_raw_counts is allocated when using intervals. This is used when |
| calculating the difference in the counts of events when using interval. |
| |
| The current counts are stored in prev_raw_counts to calculate the |
| differences in the next iteration. |
| |
| On the first interval of the second and subsequent repetitions, |
| prev_raw_counts would be the values stored in the last interval of the |
| previous repetitions, while the current counts will only be for the |
| first interval of the current repetition. |
| |
| Hence there is a possibility of events showing up as big number. |
| |
| Fix this by resetting prev_raw_counts whenever perf stat repeats the |
| command. |
| |
| With the fix: |
| |
| # perf stat -r 3 -I 2000 -e faults -e sched:sched_switch -a sleep 5 |
| |
| 2.019349347 2,597 faults |
| 2.019349347 2,753 sched:sched_switch |
| 4.019577372 3,098 faults |
| 4.019577372 2,532 sched:sched_switch |
| 5.019415481 1,879 faults |
| 5.019415481 1,356 sched:sched_switch |
| 2.000178813 8,468 faults |
| 2.000178813 2,254 sched:sched_switch |
| 4.000404621 7,440 faults |
| 4.000404621 1,266 sched:sched_switch |
| 5.040196079 2,458 faults |
| 5.040196079 556 sched:sched_switch |
| 2.000191939 6,870 faults |
| 2.000191939 1,170 sched:sched_switch |
| 4.000414103 541 faults |
| 4.000414103 902 sched:sched_switch |
| 5.000809863 450 faults |
| 5.000809863 364 sched:sched_switch |
| # |
| |
| Committer notes: |
| |
| This was broken since the cset introducing the --interval feature, i.e. |
| --repeat + --interval wasn't tested at that point, add the Fixes tag so |
| that automatic scripts can pick this up. |
| |
| Fixes: 13370a9b5bb8 ("perf stat: Add interval printing") |
| Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> |
| Acked-by: Jiri Olsa <jolsa@kernel.org> |
| Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Tested-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> |
| Cc: Namhyung Kim <namhyung@kernel.org> |
| Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> |
| Cc: Stephane Eranian <eranian@google.com> |
| Cc: stable@vger.kernel.org # v3.9+ |
| Link: http://lore.kernel.org/lkml/20190904094738.9558-2-srikar@linux.vnet.ibm.com |
| [ Fixed up conflicts with libperf, i.e. some perf_{evsel,evlist} lost the 'perf' prefix ] |
| Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| [PG: use 5.3.x stable version here on 5.2.x] |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c |
| index 15bbcd54b657..05af100ffa81 100644 |
| --- a/tools/perf/builtin-stat.c |
| +++ b/tools/perf/builtin-stat.c |
| @@ -1886,6 +1886,9 @@ int cmd_stat(int argc, const char **argv) |
| fprintf(output, "[ perf stat: executing run #%d ... ]\n", |
| run_idx + 1); |
| |
| + if (run_idx != 0) |
| + perf_evlist__reset_prev_raw_counts(evsel_list); |
| + |
| status = run_perf_stat(argc, argv, run_idx); |
| if (forever && status != -1 && !interval) { |
| print_counters(NULL, argc, argv); |
| diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c |
| index c3115d939b0b..e2ce6021e6c4 100644 |
| --- a/tools/perf/util/stat.c |
| +++ b/tools/perf/util/stat.c |
| @@ -154,6 +154,15 @@ static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel) |
| evsel->prev_raw_counts = NULL; |
| } |
| |
| +static void perf_evsel__reset_prev_raw_counts(struct perf_evsel *evsel) |
| +{ |
| + if (evsel->prev_raw_counts) { |
| + evsel->prev_raw_counts->aggr.val = 0; |
| + evsel->prev_raw_counts->aggr.ena = 0; |
| + evsel->prev_raw_counts->aggr.run = 0; |
| + } |
| +} |
| + |
| static int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw) |
| { |
| int ncpus = perf_evsel__nr_cpus(evsel); |
| @@ -204,6 +213,14 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist) |
| } |
| } |
| |
| +void perf_evlist__reset_prev_raw_counts(struct perf_evlist *evlist) |
| +{ |
| + struct perf_evsel *evsel; |
| + |
| + evlist__for_each_entry(evlist, evsel) |
| + perf_evsel__reset_prev_raw_counts(evsel); |
| +} |
| + |
| static void zero_per_pkg(struct perf_evsel *counter) |
| { |
| if (counter->per_pkg_mask) |
| diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h |
| index 2f9c9159a364..55b4fc151a42 100644 |
| --- a/tools/perf/util/stat.h |
| +++ b/tools/perf/util/stat.h |
| @@ -193,6 +193,7 @@ void perf_stat__collect_metric_expr(struct perf_evlist *); |
| int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw); |
| void perf_evlist__free_stats(struct perf_evlist *evlist); |
| void perf_evlist__reset_stats(struct perf_evlist *evlist); |
| +void perf_evlist__reset_prev_raw_counts(struct perf_evlist *evlist); |
| |
| int perf_stat_process_counter(struct perf_stat_config *config, |
| struct perf_evsel *counter); |
| -- |
| 2.7.4 |
| |