Commit f1f8ad52 authored by yuzhoujian's avatar yuzhoujian Committed by Arnaldo Carvalho de Melo

perf stat: Add support to print counts after a period of time

Introduce a new option to print counts after N milliseconds and update
'perf stat' documentation accordingly.

Show below is the output of the new option for perf stat.

  $ perf stat --time 2000 -e cycles -a
  Performance counter stats for 'system wide':

        157,260,423      cycles

        2.003060766 seconds time elapsed

We can print the count deltas after N milliseconds with this new
introduced option. This option is not supported with "-I" option.

In addition, according to Kangliang's patch(19afd104), the
monitoring overhead for system-wide core event could be very high if the
interval-print parameter was below 100ms, and the limitation value is
10ms.

So the same warning will be displayed when the time is set between 10ms
to 100ms, and the minimal time is limited to 10ms. Users can make a
decision according to their spcific cases.

Committer notes:

This actually stops the workload after the specified time, then prints
the counts.

So I renamed the option to --timeout and updated the documentation to
state that it will not just print the counts after the specified time,
but will really stop the 'perf stat' session and print the counts.

The rename from 'time' to 'timeout' also fixes the build in systems
where 'time' is used by glibc and can't be used as a name of a variable,
such as centos:5 and centos:6.

Changes since v3:
- none.

Changes since v2:
- modify the time check in __run_perf_stat func to keep some consistency
  with the workload case.
- add the warning when the time is set between 10ms to 100ms.
- add the pr_err when the time is set below 10ms.

Changes since v1:
- none.
Signed-off-by: default avataryuzhoujian <yuzhoujian@didichuxing.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Milian Wolff <milian.wolff@kdab.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1517217923-8302-3-git-send-email-ufo19890607@gmail.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent db06a269
...@@ -151,6 +151,11 @@ Print count deltas for fixed number of times. ...@@ -151,6 +151,11 @@ Print count deltas for fixed number of times.
This option should be used together with "-I" option. This option should be used together with "-I" option.
example: 'perf stat -I 1000 --interval-count 2 -e cycles -a' example: 'perf stat -I 1000 --interval-count 2 -e cycles -a'
--timeout msecs::
Stop the 'perf stat' session and print count deltas after N milliseconds (minimum: 10 ms).
This option is not supported with the "-I" option.
example: 'perf stat --time 2000 -e cycles -a'
--metric-only:: --metric-only::
Only print computed metrics. Print them in a single line. Only print computed metrics. Print them in a single line.
Don't show any raw values. Not supported with --per-thread. Don't show any raw values. Not supported with --per-thread.
......
...@@ -573,6 +573,7 @@ static int __run_perf_stat(int argc, const char **argv) ...@@ -573,6 +573,7 @@ static int __run_perf_stat(int argc, const char **argv)
{ {
int interval = stat_config.interval; int interval = stat_config.interval;
int times = stat_config.times; int times = stat_config.times;
int timeout = stat_config.timeout;
char msg[BUFSIZ]; char msg[BUFSIZ];
unsigned long long t0, t1; unsigned long long t0, t1;
struct perf_evsel *counter; struct perf_evsel *counter;
...@@ -586,6 +587,9 @@ static int __run_perf_stat(int argc, const char **argv) ...@@ -586,6 +587,9 @@ static int __run_perf_stat(int argc, const char **argv)
if (interval) { if (interval) {
ts.tv_sec = interval / USEC_PER_MSEC; ts.tv_sec = interval / USEC_PER_MSEC;
ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC; ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC;
} else if (timeout) {
ts.tv_sec = timeout / USEC_PER_MSEC;
ts.tv_nsec = (timeout % USEC_PER_MSEC) * NSEC_PER_MSEC;
} else { } else {
ts.tv_sec = 1; ts.tv_sec = 1;
ts.tv_nsec = 0; ts.tv_nsec = 0;
...@@ -698,9 +702,11 @@ static int __run_perf_stat(int argc, const char **argv) ...@@ -698,9 +702,11 @@ static int __run_perf_stat(int argc, const char **argv)
perf_evlist__start_workload(evsel_list); perf_evlist__start_workload(evsel_list);
enable_counters(); enable_counters();
if (interval) { if (interval || timeout) {
while (!waitpid(child_pid, &status, WNOHANG)) { while (!waitpid(child_pid, &status, WNOHANG)) {
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
if (timeout)
break;
process_interval(); process_interval();
if (interval_count && !(--times)) if (interval_count && !(--times))
break; break;
...@@ -720,6 +726,8 @@ static int __run_perf_stat(int argc, const char **argv) ...@@ -720,6 +726,8 @@ static int __run_perf_stat(int argc, const char **argv)
enable_counters(); enable_counters();
while (!done) { while (!done) {
nanosleep(&ts, NULL); nanosleep(&ts, NULL);
if (timeout)
break;
if (interval) { if (interval) {
process_interval(); process_interval();
if (interval_count && !(--times)) if (interval_count && !(--times))
...@@ -1900,6 +1908,8 @@ static const struct option stat_options[] = { ...@@ -1900,6 +1908,8 @@ static const struct option stat_options[] = {
"print counts at regular interval in ms (>= 10)"), "print counts at regular interval in ms (>= 10)"),
OPT_INTEGER(0, "interval-count", &stat_config.times, OPT_INTEGER(0, "interval-count", &stat_config.times,
"print counts for fixed number of times"), "print counts for fixed number of times"),
OPT_UINTEGER(0, "timeout", &stat_config.timeout,
"stop workload and print counts after a timeout period in ms (>= 10ms)"),
OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode,
"aggregate counts per processor socket", AGGR_SOCKET), "aggregate counts per processor socket", AGGR_SOCKET),
OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode, OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode,
...@@ -2697,7 +2707,7 @@ int cmd_stat(int argc, const char **argv) ...@@ -2697,7 +2707,7 @@ int cmd_stat(int argc, const char **argv)
int status = -EINVAL, run_idx; int status = -EINVAL, run_idx;
const char *mode; const char *mode;
FILE *output = stderr; FILE *output = stderr;
unsigned int interval; unsigned int interval, timeout;
const char * const stat_subcommands[] = { "record", "report" }; const char * const stat_subcommands[] = { "record", "report" };
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
...@@ -2728,6 +2738,7 @@ int cmd_stat(int argc, const char **argv) ...@@ -2728,6 +2738,7 @@ int cmd_stat(int argc, const char **argv)
return __cmd_report(argc, argv); return __cmd_report(argc, argv);
interval = stat_config.interval; interval = stat_config.interval;
timeout = stat_config.timeout;
/* /*
* For record command the -o is already taken care of. * For record command the -o is already taken care of.
...@@ -2879,6 +2890,7 @@ int cmd_stat(int argc, const char **argv) ...@@ -2879,6 +2890,7 @@ int cmd_stat(int argc, const char **argv)
"The overhead percentage could be high in some cases. " "The overhead percentage could be high in some cases. "
"Please proceed with caution.\n"); "Please proceed with caution.\n");
} }
if (stat_config.times && interval) if (stat_config.times && interval)
interval_count = true; interval_count = true;
else if (stat_config.times && !interval) { else if (stat_config.times && !interval) {
...@@ -2889,6 +2901,23 @@ int cmd_stat(int argc, const char **argv) ...@@ -2889,6 +2901,23 @@ int cmd_stat(int argc, const char **argv)
goto out; goto out;
} }
if (timeout && timeout < 100) {
if (timeout < 10) {
pr_err("timeout must be >= 10ms.\n");
parse_options_usage(stat_usage, stat_options, "timeout", 0);
goto out;
} else
pr_warning("timeout < 100ms. "
"The overhead percentage could be high in some cases. "
"Please proceed with caution.\n");
}
if (timeout && interval) {
pr_err("timeout option is not supported with interval-print.\n");
parse_options_usage(stat_usage, stat_options, "timeout", 0);
parse_options_usage(stat_usage, stat_options, "I", 1);
goto out;
}
if (perf_evlist__alloc_stats(evsel_list, interval)) if (perf_evlist__alloc_stats(evsel_list, interval))
goto out; goto out;
......
...@@ -90,6 +90,7 @@ struct perf_stat_config { ...@@ -90,6 +90,7 @@ struct perf_stat_config {
bool scale; bool scale;
FILE *output; FILE *output;
unsigned int interval; unsigned int interval;
unsigned int timeout;
int times; int times;
struct runtime_stat *stats; struct runtime_stat *stats;
int stats_num; int stats_num;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment