diff options
| author | Frederik Deweerdt <frederik.deweerdt@xprog.eu> | 2013-03-01 13:02:27 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-03-15 13:01:26 -0400 |
| commit | a7e191c376fad084d9f3c7ac89a1f7c47462ebc8 (patch) | |
| tree | 15f13ba7e2bc804f6993faaac9c72a894fa0135d /tools | |
| parent | d723a55096b81a13c319485f01994e0a539efcf9 (diff) | |
perf stat: Introduce --repeat forever
The following patch causes 'perf stat --repeat 0' to be interpreted as
'forever', displaying the stats for every run.
We act as if a single run was asked, and reset the stats in each
iteration. In this mode SIGINT is passed to perf to be able to stop the
loop with Ctrl+C.
Signed-off-by: Frederik Deweerdt <frederik.deweerdt@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20130301180227.GA24385@ks398093.ip-192-95-24.net
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/Documentation/perf-stat.txt | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-stat.c | 45 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 6 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 1 |
4 files changed, 48 insertions, 6 deletions
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index faf4f4feebcc..23e587ad549e 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt | |||
| @@ -52,7 +52,7 @@ OPTIONS | |||
| 52 | 52 | ||
| 53 | -r:: | 53 | -r:: |
| 54 | --repeat=<n>:: | 54 | --repeat=<n>:: |
| 55 | repeat command and print average + stddev (max: 100) | 55 | repeat command and print average + stddev (max: 100). 0 means forever. |
| 56 | 56 | ||
| 57 | -B:: | 57 | -B:: |
| 58 | --big-num:: | 58 | --big-num:: |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 69fe6ed89627..021783ae2bfa 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
| @@ -94,6 +94,7 @@ static const char *pre_cmd = NULL; | |||
| 94 | static const char *post_cmd = NULL; | 94 | static const char *post_cmd = NULL; |
| 95 | static bool sync_run = false; | 95 | static bool sync_run = false; |
| 96 | static unsigned int interval = 0; | 96 | static unsigned int interval = 0; |
| 97 | static bool forever = false; | ||
| 97 | static struct timespec ref_time; | 98 | static struct timespec ref_time; |
| 98 | static struct cpu_map *sock_map; | 99 | static struct cpu_map *sock_map; |
| 99 | 100 | ||
| @@ -125,6 +126,11 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) | |||
| 125 | return perf_evsel__cpus(evsel)->nr; | 126 | return perf_evsel__cpus(evsel)->nr; |
| 126 | } | 127 | } |
| 127 | 128 | ||
| 129 | static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) | ||
| 130 | { | ||
| 131 | memset(evsel->priv, 0, sizeof(struct perf_stat)); | ||
| 132 | } | ||
| 133 | |||
| 128 | static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) | 134 | static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) |
| 129 | { | 135 | { |
| 130 | evsel->priv = zalloc(sizeof(struct perf_stat)); | 136 | evsel->priv = zalloc(sizeof(struct perf_stat)); |
| @@ -173,6 +179,22 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS]; | |||
| 173 | static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; | 179 | static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; |
| 174 | static struct stats walltime_nsecs_stats; | 180 | static struct stats walltime_nsecs_stats; |
| 175 | 181 | ||
| 182 | static void reset_stats(void) | ||
| 183 | { | ||
| 184 | memset(runtime_nsecs_stats, 0, sizeof(runtime_nsecs_stats)); | ||
| 185 | memset(runtime_cycles_stats, 0, sizeof(runtime_cycles_stats)); | ||
| 186 | memset(runtime_stalled_cycles_front_stats, 0, sizeof(runtime_stalled_cycles_front_stats)); | ||
| 187 | memset(runtime_stalled_cycles_back_stats, 0, sizeof(runtime_stalled_cycles_back_stats)); | ||
| 188 | memset(runtime_branches_stats, 0, sizeof(runtime_branches_stats)); | ||
| 189 | memset(runtime_cacherefs_stats, 0, sizeof(runtime_cacherefs_stats)); | ||
| 190 | memset(runtime_l1_dcache_stats, 0, sizeof(runtime_l1_dcache_stats)); | ||
| 191 | memset(runtime_l1_icache_stats, 0, sizeof(runtime_l1_icache_stats)); | ||
| 192 | memset(runtime_ll_cache_stats, 0, sizeof(runtime_ll_cache_stats)); | ||
| 193 | memset(runtime_itlb_cache_stats, 0, sizeof(runtime_itlb_cache_stats)); | ||
| 194 | memset(runtime_dtlb_cache_stats, 0, sizeof(runtime_dtlb_cache_stats)); | ||
| 195 | memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); | ||
| 196 | } | ||
| 197 | |||
| 176 | static int create_perf_stat_counter(struct perf_evsel *evsel) | 198 | static int create_perf_stat_counter(struct perf_evsel *evsel) |
| 177 | { | 199 | { |
| 178 | struct perf_event_attr *attr = &evsel->attr; | 200 | struct perf_event_attr *attr = &evsel->attr; |
| @@ -1252,7 +1274,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 1252 | OPT_INCR('v', "verbose", &verbose, | 1274 | OPT_INCR('v', "verbose", &verbose, |
| 1253 | "be more verbose (show counter open errors, etc)"), | 1275 | "be more verbose (show counter open errors, etc)"), |
| 1254 | OPT_INTEGER('r', "repeat", &run_count, | 1276 | OPT_INTEGER('r', "repeat", &run_count, |
| 1255 | "repeat command and print average + stddev (max: 100)"), | 1277 | "repeat command and print average + stddev (max: 100, forever: 0)"), |
| 1256 | OPT_BOOLEAN('n', "null", &null_run, | 1278 | OPT_BOOLEAN('n', "null", &null_run, |
| 1257 | "null run - dont start any counters"), | 1279 | "null run - dont start any counters"), |
| 1258 | OPT_INCR('d', "detailed", &detailed_run, | 1280 | OPT_INCR('d', "detailed", &detailed_run, |
| @@ -1355,8 +1377,12 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 1355 | 1377 | ||
| 1356 | if (!argc && !perf_target__has_task(&target)) | 1378 | if (!argc && !perf_target__has_task(&target)) |
| 1357 | usage_with_options(stat_usage, options); | 1379 | usage_with_options(stat_usage, options); |
| 1358 | if (run_count <= 0) | 1380 | if (run_count < 0) { |
| 1359 | usage_with_options(stat_usage, options); | 1381 | usage_with_options(stat_usage, options); |
| 1382 | } else if (run_count == 0) { | ||
| 1383 | forever = true; | ||
| 1384 | run_count = 1; | ||
| 1385 | } | ||
| 1360 | 1386 | ||
| 1361 | /* no_aggr, cgroup are for system-wide only */ | 1387 | /* no_aggr, cgroup are for system-wide only */ |
| 1362 | if ((no_aggr || nr_cgroups) && !perf_target__has_cpu(&target)) { | 1388 | if ((no_aggr || nr_cgroups) && !perf_target__has_cpu(&target)) { |
| @@ -1413,21 +1439,30 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 1413 | * task, but being ignored by perf stat itself: | 1439 | * task, but being ignored by perf stat itself: |
| 1414 | */ | 1440 | */ |
| 1415 | atexit(sig_atexit); | 1441 | atexit(sig_atexit); |
| 1416 | signal(SIGINT, skip_signal); | 1442 | if (!forever) |
| 1443 | signal(SIGINT, skip_signal); | ||
| 1417 | signal(SIGCHLD, skip_signal); | 1444 | signal(SIGCHLD, skip_signal); |
| 1418 | signal(SIGALRM, skip_signal); | 1445 | signal(SIGALRM, skip_signal); |
| 1419 | signal(SIGABRT, skip_signal); | 1446 | signal(SIGABRT, skip_signal); |
| 1420 | 1447 | ||
| 1421 | status = 0; | 1448 | status = 0; |
| 1422 | for (run_idx = 0; run_idx < run_count; run_idx++) { | 1449 | for (run_idx = 0; forever || run_idx < run_count; run_idx++) { |
| 1423 | if (run_count != 1 && verbose) | 1450 | if (run_count != 1 && verbose) |
| 1424 | fprintf(output, "[ perf stat: executing run #%d ... ]\n", | 1451 | fprintf(output, "[ perf stat: executing run #%d ... ]\n", |
| 1425 | run_idx + 1); | 1452 | run_idx + 1); |
| 1426 | 1453 | ||
| 1427 | status = run_perf_stat(argc, argv); | 1454 | status = run_perf_stat(argc, argv); |
| 1455 | if (forever && status != -1) { | ||
| 1456 | print_stat(argc, argv); | ||
| 1457 | list_for_each_entry(pos, &evsel_list->entries, node) { | ||
| 1458 | perf_evsel__reset_stat_priv(pos); | ||
| 1459 | perf_evsel__reset_counts(pos, perf_evsel__nr_cpus(pos)); | ||
| 1460 | } | ||
| 1461 | reset_stats(); | ||
| 1462 | } | ||
| 1428 | } | 1463 | } |
| 1429 | 1464 | ||
| 1430 | if (status != -1 && !interval) | 1465 | if (!forever && status != -1 && !interval) |
| 1431 | print_stat(argc, argv); | 1466 | print_stat(argc, argv); |
| 1432 | out_free_fd: | 1467 | out_free_fd: |
| 1433 | list_for_each_entry(pos, &evsel_list->entries, node) { | 1468 | list_for_each_entry(pos, &evsel_list->entries, node) { |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 7fde9fb79966..1adb824610f0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -633,6 +633,12 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) | |||
| 633 | return 0; | 633 | return 0; |
| 634 | } | 634 | } |
| 635 | 635 | ||
| 636 | void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus) | ||
| 637 | { | ||
| 638 | memset(evsel->counts, 0, (sizeof(*evsel->counts) + | ||
| 639 | (ncpus * sizeof(struct perf_counts_values)))); | ||
| 640 | } | ||
| 641 | |||
| 636 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) | 642 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus) |
| 637 | { | 643 | { |
| 638 | evsel->counts = zalloc((sizeof(*evsel->counts) + | 644 | evsel->counts = zalloc((sizeof(*evsel->counts) + |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index bf758e53c929..3f156ccc1acb 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -121,6 +121,7 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); | |||
| 121 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | 121 | int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); |
| 122 | int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); | 122 | int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); |
| 123 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); | 123 | int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); |
| 124 | void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus); | ||
| 124 | void perf_evsel__free_fd(struct perf_evsel *evsel); | 125 | void perf_evsel__free_fd(struct perf_evsel *evsel); |
| 125 | void perf_evsel__free_id(struct perf_evsel *evsel); | 126 | void perf_evsel__free_id(struct perf_evsel *evsel); |
| 126 | void perf_evsel__free_counts(struct perf_evsel *evsel); | 127 | void perf_evsel__free_counts(struct perf_evsel *evsel); |
