diff options
-rw-r--r-- | tools/perf/Documentation/perf-diff.txt | 8 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 3 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-script.txt | 3 | ||||
-rw-r--r-- | tools/perf/tests/time-utils-test.c | 17 | ||||
-rw-r--r-- | tools/perf/util/time-utils.c | 74 |
5 files changed, 94 insertions, 11 deletions
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 | |||
145 | <start>,<stop>. Times have the format seconds.nanoseconds. If 'start' | 145 | <start>,<stop>. Times have the format seconds.nanoseconds. If 'start' |
146 | is not given (i.e. time string is ',x.y') then analysis starts at | 146 | is not given (i.e. time string is ',x.y') then analysis starts at |
147 | the beginning of the file. If stop time is not given (i.e. time | 147 | the beginning of the file. If stop time is not given (i.e. time |
148 | string is 'x.y,') then analysis goes to the end of the file. Time string is | 148 | string is 'x.y,') then analysis goes to the end of the file. |
149 | 'a1.b1,c1.d1:a2.b2,c2.d2'. Use ':' to separate timestamps for different | 149 | Multiple ranges can be separated by spaces, which requires the argument |
150 | perf.data files. | 150 | to be quoted e.g. --time "1234.567,1234.789 1235," |
151 | Time string is'a1.b1,c1.d1:a2.b2,c2.d2'. Use ':' to separate timestamps | ||
152 | for different perf.data files. | ||
151 | 153 | ||
152 | For example, we get the timestamp information from 'perf script'. | 154 | For example, we get the timestamp information from 'perf script'. |
153 | 155 | ||
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 | |||
415 | have the format seconds.nanoseconds. If start is not given (i.e. time | 415 | have the format seconds.nanoseconds. If start is not given (i.e. time |
416 | string is ',x.y') then analysis starts at the beginning of the file. If | 416 | string is ',x.y') then analysis starts at the beginning of the file. If |
417 | stop time is not given (i.e. time string is 'x.y,') then analysis goes | 417 | stop time is not given (i.e. time string is 'x.y,') then analysis goes |
418 | to end of file. | 418 | to end of file. Multiple ranges can be separated by spaces, which |
419 | requires the argument to be quoted e.g. --time "1234.567,1234.789 1235," | ||
419 | 420 | ||
420 | Also support time percent with multiple time ranges. Time string is | 421 | Also support time percent with multiple time ranges. Time string is |
421 | 'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'. | 422 | '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[] | |||
364 | have the format seconds.nanoseconds. If start is not given (i.e. time | 364 | have the format seconds.nanoseconds. If start is not given (i.e. time |
365 | string is ',x.y') then analysis starts at the beginning of the file. If | 365 | string is ',x.y') then analysis starts at the beginning of the file. If |
366 | stop time is not given (i.e. time string is 'x.y,') then analysis goes | 366 | stop time is not given (i.e. time string is 'x.y,') then analysis goes |
367 | to end of file. | 367 | to end of file. Multiple ranges can be separated by spaces, which |
368 | requires the argument to be quoted e.g. --time "1234.567,1234.789 1235," | ||
368 | 369 | ||
369 | Also support time percent with multiple time ranges. Time string is | 370 | Also support time percent with multiple time ranges. Time string is |
370 | 'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'. | 371 | '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 | |||
@@ -169,6 +169,23 @@ int test__time_utils(struct test *t __maybe_unused, int subtest __maybe_unused) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | { | 171 | { |
172 | u64 b = 1234567123456789ULL; | ||
173 | u64 c = 7654321987654321ULL; | ||
174 | u64 e = 8000000000000000ULL; | ||
175 | struct test_data d = { | ||
176 | .str = "1234567.123456789,1234567.123456790 " | ||
177 | "7654321.987654321,7654321.987654444 " | ||
178 | "8000000,8000000.000000005", | ||
179 | .ptime = { {b, b + 1}, {c, c + 123}, {e, e + 5}, }, | ||
180 | .num = 3, | ||
181 | .skip = { b - 1, b + 2, c - 1, c + 124, e - 1, e + 6 }, | ||
182 | .noskip = { b, b + 1, c, c + 123, e, e + 5 }, | ||
183 | }; | ||
184 | |||
185 | pass &= test__perf_time__parse_for_ranges(&d); | ||
186 | } | ||
187 | |||
188 | { | ||
172 | u64 b = 7654321ULL * NSEC_PER_SEC; | 189 | u64 b = 7654321ULL * NSEC_PER_SEC; |
173 | struct test_data d = { | 190 | struct test_data d = { |
174 | .str = "10%/1", | 191 | .str = "10%/1", |
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 @@ | |||
7 | #include <errno.h> | 7 | #include <errno.h> |
8 | #include <inttypes.h> | 8 | #include <inttypes.h> |
9 | #include <math.h> | 9 | #include <math.h> |
10 | #include <ctype.h> | ||
10 | 11 | ||
11 | #include "perf.h" | 12 | #include "perf.h" |
12 | #include "debug.h" | 13 | #include "debug.h" |
@@ -116,6 +117,69 @@ int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr) | |||
116 | return rc; | 117 | return rc; |
117 | } | 118 | } |
118 | 119 | ||
120 | static int perf_time__parse_strs(struct perf_time_interval *ptime, | ||
121 | const char *ostr, int size) | ||
122 | { | ||
123 | const char *cp; | ||
124 | char *str, *arg, *p; | ||
125 | int i, num = 0, rc = 0; | ||
126 | |||
127 | /* Count the commas */ | ||
128 | for (cp = ostr; *cp; cp++) | ||
129 | num += !!(*cp == ','); | ||
130 | |||
131 | if (!num) | ||
132 | return -EINVAL; | ||
133 | |||
134 | BUG_ON(num > size); | ||
135 | |||
136 | str = strdup(ostr); | ||
137 | if (!str) | ||
138 | return -ENOMEM; | ||
139 | |||
140 | /* Split the string and parse each piece, except the last */ | ||
141 | for (i = 0, p = str; i < num - 1; i++) { | ||
142 | arg = p; | ||
143 | /* Find next comma, there must be one */ | ||
144 | p = strchr(p, ',') + 1; | ||
145 | /* Skip white space */ | ||
146 | while (isspace(*p)) | ||
147 | p++; | ||
148 | /* Skip the value, must not contain space or comma */ | ||
149 | while (*p && !isspace(*p)) { | ||
150 | if (*p++ == ',') { | ||
151 | rc = -EINVAL; | ||
152 | goto out; | ||
153 | } | ||
154 | } | ||
155 | /* Split and parse */ | ||
156 | if (*p) | ||
157 | *p++ = 0; | ||
158 | rc = perf_time__parse_str(ptime + i, arg); | ||
159 | if (rc < 0) | ||
160 | goto out; | ||
161 | } | ||
162 | |||
163 | /* Parse the last piece */ | ||
164 | rc = perf_time__parse_str(ptime + i, p); | ||
165 | if (rc < 0) | ||
166 | goto out; | ||
167 | |||
168 | /* Check there is no overlap */ | ||
169 | for (i = 0; i < num - 1; i++) { | ||
170 | if (ptime[i].end >= ptime[i + 1].start) { | ||
171 | rc = -EINVAL; | ||
172 | goto out; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | rc = num; | ||
177 | out: | ||
178 | free(str); | ||
179 | |||
180 | return rc; | ||
181 | } | ||
182 | |||
119 | static int parse_percent(double *pcnt, char *str) | 183 | static int parse_percent(double *pcnt, char *str) |
120 | { | 184 | { |
121 | char *c, *endptr; | 185 | char *c, *endptr; |
@@ -424,15 +488,13 @@ int perf_time__parse_for_ranges(const char *time_str, | |||
424 | time_str, | 488 | time_str, |
425 | session->evlist->first_sample_time, | 489 | session->evlist->first_sample_time, |
426 | session->evlist->last_sample_time); | 490 | session->evlist->last_sample_time); |
427 | |||
428 | if (num < 0) | ||
429 | goto error_invalid; | ||
430 | } else { | 491 | } else { |
431 | if (perf_time__parse_str(ptime_range, time_str)) | 492 | num = perf_time__parse_strs(ptime_range, time_str, size); |
432 | goto error_invalid; | ||
433 | num = 1; | ||
434 | } | 493 | } |
435 | 494 | ||
495 | if (num < 0) | ||
496 | goto error_invalid; | ||
497 | |||
436 | *range_size = size; | 498 | *range_size = size; |
437 | *range_num = num; | 499 | *range_num = num; |
438 | *ranges = ptime_range; | 500 | *ranges = ptime_range; |