Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent e39a12cb
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -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'.

+2 −1
Original line number Diff line number Diff line
@@ -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,...'.
+2 −1
Original line number Diff line number Diff line
@@ -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,...'.
+17 −0
Original line number Diff line number Diff line
@@ -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 = {
+68 −6
Original line number Diff line number Diff line
@@ -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,14 +488,12 @@ int perf_time__parse_for_ranges(const char *time_str,
				time_str,
				session->evlist->first_sample_time,
				session->evlist->last_sample_time);
	} else {
		num = perf_time__parse_strs(ptime_range, time_str, size);
	}

	if (num < 0)
		goto error_invalid;
	} else {
		if (perf_time__parse_str(ptime_range, time_str))
			goto error_invalid;
		num = 1;
	}

	*range_size = size;
	*range_num = num;