Commit a77a05e2 authored by Adrian Hunter's avatar Adrian Hunter Committed by Arnaldo Carvalho de Melo

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: default avatarAdrian 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.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent e39a12cb
...@@ -145,9 +145,11 @@ OPTIONS ...@@ -145,9 +145,11 @@ OPTIONS
<start>,<stop>. Times have the format seconds.nanoseconds. If 'start' <start>,<stop>. Times have the format seconds.nanoseconds. If 'start'
is not given (i.e. time string is ',x.y') then analysis starts at 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 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 string is 'x.y,') then analysis goes to the end of the file.
'a1.b1,c1.d1:a2.b2,c2.d2'. Use ':' to separate timestamps for different Multiple ranges can be separated by spaces, which requires the argument
perf.data files. 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'. For example, we get the timestamp information from 'perf script'.
......
...@@ -415,7 +415,8 @@ OPTIONS ...@@ -415,7 +415,8 @@ OPTIONS
have the format seconds.nanoseconds. If start is not given (i.e. time 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 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 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 Also support time percent with multiple time ranges. Time string is
'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'. 'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'.
......
...@@ -364,7 +364,8 @@ include::itrace.txt[] ...@@ -364,7 +364,8 @@ include::itrace.txt[]
have the format seconds.nanoseconds. If start is not given (i.e. time 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 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 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 Also support time percent with multiple time ranges. Time string is
'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'. '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) ...@@ -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); 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; u64 b = 7654321ULL * NSEC_PER_SEC;
struct test_data d = { struct test_data d = {
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <errno.h> #include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include <math.h> #include <math.h>
#include <ctype.h>
#include "perf.h" #include "perf.h"
#include "debug.h" #include "debug.h"
...@@ -116,6 +117,69 @@ int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr) ...@@ -116,6 +117,69 @@ int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
return rc; 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) static int parse_percent(double *pcnt, char *str)
{ {
char *c, *endptr; char *c, *endptr;
...@@ -424,14 +488,12 @@ int perf_time__parse_for_ranges(const char *time_str, ...@@ -424,14 +488,12 @@ int perf_time__parse_for_ranges(const char *time_str,
time_str, time_str,
session->evlist->first_sample_time, session->evlist->first_sample_time,
session->evlist->last_sample_time); session->evlist->last_sample_time);
} else {
num = perf_time__parse_strs(ptime_range, time_str, size);
}
if (num < 0) if (num < 0)
goto error_invalid; goto error_invalid;
} else {
if (perf_time__parse_str(ptime_range, time_str))
goto error_invalid;
num = 1;
}
*range_size = size; *range_size = size;
*range_num = num; *range_num = 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