From f79a7689d99366aee9f89d785bca6c52ed6b76eb Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Jun 2019 16:00:10 +0300 Subject: perf time-utils: Treat time ranges consistently Currently, options allow only 1 explicit (non-percentage) time range. In preparation for adding support for multiple explicit time ranges, treat time ranges consistently. Instead of treating some time ranges as inclusive and some as excluding the end time, treat all time ranges as inclusive. This is only a 1 nanosecond change but is necessary to treat multiple explicit time ranges in a consistent manner. Note, there is a later patch that adds a test for time-utils. Signed-off-by: Adrian Hunter Cc: Jin Yao Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190604130017.31207-13-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/time-utils.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'tools/perf/util/time-utils.c') diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 20663a460df3..1d67cf1216c7 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -389,13 +389,12 @@ bool perf_time__ranges_skip_sample(struct perf_time_interval *ptime_buf, ptime = &ptime_buf[i]; if (timestamp >= ptime->start && - ((timestamp < ptime->end && i < num - 1) || - (timestamp <= ptime->end && i == num - 1))) { - break; + (timestamp <= ptime->end || !ptime->end)) { + return false; } } - return (i == num) ? true : false; + return true; } int perf_time__parse_for_ranges(const char *time_str, -- cgit From c763242a5e742f8fefda0bb6cfdf6a5a34ae5e10 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Jun 2019 16:00:11 +0300 Subject: perf time-utils: Factor out set_percent_time() Factor out set_percent_time() so it can be reused. Signed-off-by: Adrian Hunter Cc: Jin Yao Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190604130017.31207-14-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/time-utils.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) (limited to 'tools/perf/util/time-utils.c') diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 1d67cf1216c7..69441faab3d0 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -135,12 +135,27 @@ static int parse_percent(double *pcnt, char *str) return 0; } +static int set_percent_time(struct perf_time_interval *ptime, double start_pcnt, + double end_pcnt, u64 start, u64 end) +{ + u64 total = end - start; + + if (start_pcnt < 0.0 || start_pcnt > 1.0 || + end_pcnt < 0.0 || end_pcnt > 1.0) { + return -1; + } + + ptime->start = start + round(start_pcnt * total); + ptime->end = start + round(end_pcnt * total); + + return 0; +} + static int percent_slash_split(char *str, struct perf_time_interval *ptime, u64 start, u64 end) { char *p, *end_str; double pcnt, start_pcnt, end_pcnt; - u64 total = end - start; int i; /* @@ -168,15 +183,7 @@ static int percent_slash_split(char *str, struct perf_time_interval *ptime, start_pcnt = pcnt * (i - 1); end_pcnt = pcnt * i; - if (start_pcnt < 0.0 || start_pcnt > 1.0 || - end_pcnt < 0.0 || end_pcnt > 1.0) { - return -1; - } - - ptime->start = start + round(start_pcnt * total); - ptime->end = start + round(end_pcnt * total); - - return 0; + return set_percent_time(ptime, start_pcnt, end_pcnt, start, end); } static int percent_dash_split(char *str, struct perf_time_interval *ptime, @@ -184,7 +191,6 @@ static int percent_dash_split(char *str, struct perf_time_interval *ptime, { char *start_str = NULL, *end_str; double start_pcnt, end_pcnt; - u64 total = end - start; int ret; /* @@ -203,16 +209,7 @@ static int percent_dash_split(char *str, struct perf_time_interval *ptime, free(start_str); - if (start_pcnt < 0.0 || start_pcnt > 1.0 || - end_pcnt < 0.0 || end_pcnt > 1.0 || - start_pcnt > end_pcnt) { - return -1; - } - - ptime->start = start + round(start_pcnt * total); - ptime->end = start + round(end_pcnt * total); - - return 0; + return set_percent_time(ptime, start_pcnt, end_pcnt, start, end); } typedef int (*time_pecent_split)(char *, struct perf_time_interval *, -- cgit From b16bfeb3db1b50273e95f539953c337be759500d Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Jun 2019 16:00:12 +0300 Subject: perf time-utils: Prevent percentage time range overlap Prevent percentage time range overlap. This is only a 1 nanosecond change but makes the results more logical e.g. a sample cannot be in both the first 10% and the second 20%. Note, there is a later patch that adds a test for time-utils. Signed-off-by: Adrian Hunter Cc: Jin Yao Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190604130017.31207-15-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/time-utils.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/perf/util/time-utils.c') diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 69441faab3d0..3e87c21c293c 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -148,6 +148,9 @@ static int set_percent_time(struct perf_time_interval *ptime, double start_pcnt, ptime->start = start + round(start_pcnt * total); ptime->end = start + round(end_pcnt * total); + if (ptime->end > ptime->start && ptime->end != end) + ptime->end -= 1; + return 0; } -- cgit From 2a8afddc084a5f5f933382758dd2767ed8a69f77 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Jun 2019 16:00:14 +0300 Subject: perf time-utils: Simplify perf_time__parse_for_ranges() error paths slightly Simplify perf_time__parse_for_ranges() error paths slightly. Signed-off-by: Adrian Hunter Cc: Jin Yao Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190604130017.31207-17-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/time-utils.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'tools/perf/util/time-utils.c') diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 3e87c21c293c..9a463752dba8 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -403,7 +403,7 @@ int perf_time__parse_for_ranges(const char *time_str, int *range_size, int *range_num) { struct perf_time_interval *ptime_range; - int size, num, ret; + int size, num, ret = -EINVAL; ptime_range = perf_time__range_alloc(time_str, &size); if (!ptime_range) @@ -415,7 +415,6 @@ int perf_time__parse_for_ranges(const char *time_str, pr_err("HINT: no first/last sample time found in perf data.\n" "Please use latest perf binary to execute 'perf record'\n" "(if '--buildid-all' is enabled, please set '--timestamp-boundary').\n"); - ret = -EINVAL; goto error; } @@ -425,11 +424,8 @@ int perf_time__parse_for_ranges(const char *time_str, session->evlist->first_sample_time, session->evlist->last_sample_time); - if (num < 0) { - pr_err("Invalid time string\n"); - ret = -EINVAL; - goto error; - } + if (num < 0) + goto error_invalid; } else { num = 1; } @@ -439,6 +435,8 @@ int perf_time__parse_for_ranges(const char *time_str, *ranges = ptime_range; return 0; +error_invalid: + pr_err("Invalid time string\n"); error: free(ptime_range); return ret; -- cgit From 929afa0092d0ea6be2fbd0ac087319092595eba6 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Jun 2019 16:00:15 +0300 Subject: perf time-utils: Make perf_time__parse_for_ranges() more logical Explicit time ranges never contain a percent sign whereas percentage ranges always do, so it is possible to call the correct parser. Signed-off-by: Adrian Hunter Cc: Jin Yao Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190604130017.31207-18-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/time-utils.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools/perf/util/time-utils.c') diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 9a463752dba8..d942840356e3 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -402,6 +402,7 @@ int perf_time__parse_for_ranges(const char *time_str, struct perf_time_interval **ranges, int *range_size, int *range_num) { + bool has_percent = strchr(time_str, '%'); struct perf_time_interval *ptime_range; int size, num, ret = -EINVAL; @@ -409,7 +410,7 @@ int perf_time__parse_for_ranges(const char *time_str, if (!ptime_range) return -ENOMEM; - if (perf_time__parse_str(ptime_range, time_str) != 0) { + if (has_percent) { if (session->evlist->first_sample_time == 0 && session->evlist->last_sample_time == 0) { pr_err("HINT: no first/last sample time found in perf data.\n" @@ -427,6 +428,8 @@ int perf_time__parse_for_ranges(const char *time_str, if (num < 0) goto error_invalid; } else { + if (perf_time__parse_str(ptime_range, time_str)) + goto error_invalid; num = 1; } -- cgit From a77a05e2337df1347f4de96bfa313db7008fe8bd Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 4 Jun 2019 16:00:17 +0300 Subject: perf time-utils: Add support for multiple explicit time intervals Currently only a single explicit time range is accepted. Add support for multiple ranges separated by spaces, which requires the string to be quoted. Update the time utils test accordingly. Signed-off-by: Adrian Hunter Cc: Jin Yao Cc: Jiri Olsa Link: http://lkml.kernel.org/r/20190604130017.31207-20-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-diff.txt | 8 ++-- tools/perf/Documentation/perf-report.txt | 3 +- tools/perf/Documentation/perf-script.txt | 3 +- tools/perf/tests/time-utils-test.c | 17 ++++++++ tools/perf/util/time-utils.c | 74 +++++++++++++++++++++++++++++--- 5 files changed, 94 insertions(+), 11 deletions(-) (limited to 'tools/perf/util/time-utils.c') diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index 5732f69580ab..facd91e4e945 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt @@ -145,9 +145,11 @@ OPTIONS ,. Times have the format seconds.nanoseconds. If 'start' is not given (i.e. time string is ',x.y') then analysis starts at the beginning of the file. If stop time is not given (i.e. time - string is 'x.y,') then analysis goes to the end of the file. Time string is - 'a1.b1,c1.d1:a2.b2,c2.d2'. Use ':' to separate timestamps for different - perf.data files. + string is 'x.y,') then analysis goes to the end of the file. + Multiple ranges can be separated by spaces, which requires the argument + to be quoted e.g. --time "1234.567,1234.789 1235," + Time string is'a1.b1,c1.d1:a2.b2,c2.d2'. Use ':' to separate timestamps + for different perf.data files. For example, we get the timestamp information from 'perf script'. diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 3de029f6881d..8c4372819e11 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -415,7 +415,8 @@ OPTIONS have the format seconds.nanoseconds. If start is not given (i.e. time string is ',x.y') then analysis starts at the beginning of the file. If stop time is not given (i.e. time string is 'x.y,') then analysis goes - to end of file. + to end of file. Multiple ranges can be separated by spaces, which + requires the argument to be quoted e.g. --time "1234.567,1234.789 1235," Also support time percent with multiple time ranges. Time string is 'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'. diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 878349cce968..d4e2e18a5881 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt @@ -364,7 +364,8 @@ include::itrace.txt[] have the format seconds.nanoseconds. If start is not given (i.e. time string is ',x.y') then analysis starts at the beginning of the file. If stop time is not given (i.e. time string is 'x.y,') then analysis goes - to end of file. + to end of file. Multiple ranges can be separated by spaces, which + requires the argument to be quoted e.g. --time "1234.567,1234.789 1235," Also support time percent with multiple time ranges. Time string is 'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'. diff --git a/tools/perf/tests/time-utils-test.c b/tools/perf/tests/time-utils-test.c index 7504046b111c..4f53006233a1 100644 --- a/tools/perf/tests/time-utils-test.c +++ b/tools/perf/tests/time-utils-test.c @@ -168,6 +168,23 @@ int test__time_utils(struct test *t __maybe_unused, int subtest __maybe_unused) pass &= test__perf_time__parse_for_ranges(&d); } + { + u64 b = 1234567123456789ULL; + u64 c = 7654321987654321ULL; + u64 e = 8000000000000000ULL; + struct test_data d = { + .str = "1234567.123456789,1234567.123456790 " + "7654321.987654321,7654321.987654444 " + "8000000,8000000.000000005", + .ptime = { {b, b + 1}, {c, c + 123}, {e, e + 5}, }, + .num = 3, + .skip = { b - 1, b + 2, c - 1, c + 124, e - 1, e + 6 }, + .noskip = { b, b + 1, c, c + 123, e, e + 5 }, + }; + + pass &= test__perf_time__parse_for_ranges(&d); + } + { u64 b = 7654321ULL * NSEC_PER_SEC; struct test_data d = { diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index d942840356e3..2b48816a2d2e 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "perf.h" #include "debug.h" @@ -116,6 +117,69 @@ int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr) return rc; } +static int perf_time__parse_strs(struct perf_time_interval *ptime, + const char *ostr, int size) +{ + const char *cp; + char *str, *arg, *p; + int i, num = 0, rc = 0; + + /* Count the commas */ + for (cp = ostr; *cp; cp++) + num += !!(*cp == ','); + + if (!num) + return -EINVAL; + + BUG_ON(num > size); + + str = strdup(ostr); + if (!str) + return -ENOMEM; + + /* Split the string and parse each piece, except the last */ + for (i = 0, p = str; i < num - 1; i++) { + arg = p; + /* Find next comma, there must be one */ + p = strchr(p, ',') + 1; + /* Skip white space */ + while (isspace(*p)) + p++; + /* Skip the value, must not contain space or comma */ + while (*p && !isspace(*p)) { + if (*p++ == ',') { + rc = -EINVAL; + goto out; + } + } + /* Split and parse */ + if (*p) + *p++ = 0; + rc = perf_time__parse_str(ptime + i, arg); + if (rc < 0) + goto out; + } + + /* Parse the last piece */ + rc = perf_time__parse_str(ptime + i, p); + if (rc < 0) + goto out; + + /* Check there is no overlap */ + for (i = 0; i < num - 1; i++) { + if (ptime[i].end >= ptime[i + 1].start) { + rc = -EINVAL; + goto out; + } + } + + rc = num; +out: + free(str); + + return rc; +} + static int parse_percent(double *pcnt, char *str) { char *c, *endptr; @@ -424,15 +488,13 @@ int perf_time__parse_for_ranges(const char *time_str, time_str, session->evlist->first_sample_time, session->evlist->last_sample_time); - - if (num < 0) - goto error_invalid; } else { - if (perf_time__parse_str(ptime_range, time_str)) - goto error_invalid; - num = 1; + num = perf_time__parse_strs(ptime_range, time_str, size); } + if (num < 0) + goto error_invalid; + *range_size = size; *range_num = num; *ranges = ptime_range; -- cgit From bd9860bf050f77c4e260a9ae10a5587009ad6e07 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 21:13:51 -0300 Subject: perf tools: Use linux/ctype.h in more places There were a few places where we still were using the libc version of ctype.h, switch to the one in tools/lib/ctype.c that the rest of perf uses. Cc: Adrian Hunter Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-wa4nz4kt61eze88eprk20tfd@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/s390/util/header.c | 2 +- tools/perf/util/metricgroup.c | 2 +- tools/perf/util/time-utils.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tools/perf/util/time-utils.c') diff --git a/tools/perf/arch/s390/util/header.c b/tools/perf/arch/s390/util/header.c index 3db85cd2069e..a25896135abe 100644 --- a/tools/perf/arch/s390/util/header.c +++ b/tools/perf/arch/s390/util/header.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include "../../util/header.h" #include "../../util/util.h" diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 699e020737d9..a0cf3cd95ced 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -17,7 +17,7 @@ #include "pmu-events/pmu-events.h" #include "strlist.h" #include -#include +#include struct metric_event *metricgroup__lookup(struct rblist *metric_events, struct perf_evsel *evsel, diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 2b48816a2d2e..369fa19dd596 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "perf.h" #include "debug.h" -- cgit From 9bb5a27ac7958ce11cb02463b5a5f7f160d60916 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Jun 2019 21:39:18 -0300 Subject: perf time-utils: Use skip_spaces() No change in behaviour intended. Cc: Adrian Hunter Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Link: https://lkml.kernel.org/n/tip-cpugv7qd5vzhbtvnlydo90jv@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/time-utils.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'tools/perf/util/time-utils.c') diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c index 369fa19dd596..c2abc259b51d 100644 --- a/tools/perf/util/time-utils.c +++ b/tools/perf/util/time-utils.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include #include +#include #include #include #include @@ -141,10 +142,7 @@ static int perf_time__parse_strs(struct perf_time_interval *ptime, for (i = 0, p = str; i < num - 1; i++) { arg = p; /* Find next comma, there must be one */ - p = strchr(p, ',') + 1; - /* Skip white space */ - while (isspace(*p)) - p++; + p = skip_spaces(strchr(p, ',') + 1); /* Skip the value, must not contain space or comma */ while (*p && !isspace(*p)) { if (*p++ == ',') { -- cgit