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>
This commit is contained in:
parent
e39a12cbd2
commit
a77a05e233
|
@ -145,9 +145,11 @@ OPTIONS
|
|||
<start>,<stop>. 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'.
|
||||
|
||||
|
|
|
@ -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,...'.
|
||||
|
|
|
@ -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,...'.
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#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;
|
||||
|
|
Loading…
Reference in New Issue