summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2019-06-04 09:00:17 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2019-06-10 15:20:13 -0400
commita77a05e2337df1347f4de96bfa313db7008fe8bd (patch)
treefe2b2112319ea8ed48a12c215d83687d74118084
parente39a12cbd2496edb4cab0f99efb0d217c55ba273 (diff)
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 <adrian.hunter@intel.com> Cc: Jin Yao <yao.jin@linux.intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Link: http://lkml.kernel.org/r/20190604130017.31207-20-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Documentation/perf-diff.txt8
-rw-r--r--tools/perf/Documentation/perf-report.txt3
-rw-r--r--tools/perf/Documentation/perf-script.txt3
-rw-r--r--tools/perf/tests/time-utils-test.c17
-rw-r--r--tools/perf/util/time-utils.c74
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
120static 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;
177out:
178 free(str);
179
180 return rc;
181}
182
119static int parse_percent(double *pcnt, char *str) 183static 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;