Skip to content

Commit

Permalink
perf time-utils: Add support for multiple explicit time intervals
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Adrian Hunter authored and Arnaldo Carvalho de Melo committed Jun 10, 2019
1 parent e39a12c commit a77a05e
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 11 deletions.
8 changes: 5 additions & 3 deletions tools/perf/Documentation/perf-diff.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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'.

Expand Down
3 changes: 2 additions & 1 deletion tools/perf/Documentation/perf-report.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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,...'.
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/Documentation/perf-script.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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,...'.
Expand Down
17 changes: 17 additions & 0 deletions tools/perf/tests/time-utils-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
74 changes: 68 additions & 6 deletions tools/perf/util/time-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <errno.h>
#include <inttypes.h>
#include <math.h>
#include <ctype.h>

#include "perf.h"
#include "debug.h"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit a77a05e

Please sign in to comment.