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/perf | |
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/perf')
-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); |