All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/6] perf report/script: Support percent and multiple range in --time option
@ 2017-09-20 15:12 Jin Yao
  2017-09-20 15:12 ` [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header Jin Yao
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Jin Yao @ 2017-09-20 15:12 UTC (permalink / raw)
  To: acme, jolsa, peterz, mingo, alexander.shishkin
  Cc: Linux-kernel, ak, kan.liang, yao.jin, Jin Yao

Current perf report/script/... have a --time option to limit the time
range of output. But it only supports the absolute time.

The patch series extend this option to let it support percent of time
and support the multiple time ranges.

For example:

1. Select the second 10% time slice
   perf report --time 10%/2

2. Select from 0% to 10% time slice
   perf report --time 0%-10%

It also support the multiple time ranges.

3. Select the first and second 10% time slices
   perf report --time 10%/1,10%/2

4. Select from 0% to 10% and 30% to 40% slices
   perf report --time 0%-10%,30%-40%

Jin Yao (6):
  perf record: Record the first sample time and last sample time to perf
    file header
  perf Documentation: Update perf.data-file-format.txt
  perf util: Create function to parse time percent
  perf util: Create function to perform multiple time range checking
  perf report: support time percent and multiple time ranges
  perf script: support time percent and multiple time ranges

 tools/perf/Documentation/perf-report.txt           |  16 ++
 tools/perf/Documentation/perf-script.txt           |  16 ++
 tools/perf/Documentation/perf.data-file-format.txt |  27 ++-
 tools/perf/builtin-record.c                        |  15 ++
 tools/perf/builtin-report.c                        |  24 ++-
 tools/perf/builtin-script.c                        |  21 +-
 tools/perf/util/header.c                           |  59 +++++-
 tools/perf/util/header.h                           |   4 +
 tools/perf/util/session.h                          |   2 +
 tools/perf/util/time-utils.c                       | 224 +++++++++++++++++++--
 tools/perf/util/time-utils.h                       |   6 +
 11 files changed, 383 insertions(+), 31 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header
  2017-09-20 15:12 [PATCH v1 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
@ 2017-09-20 15:12 ` Jin Yao
  2017-09-21 15:17   ` Jiri Olsa
  2017-09-21 15:18   ` Jiri Olsa
  2017-09-20 15:12 ` [PATCH v1 2/6] perf Documentation: Update perf.data-file-format.txt Jin Yao
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 11+ messages in thread
From: Jin Yao @ 2017-09-20 15:12 UTC (permalink / raw)
  To: acme, jolsa, peterz, mingo, alexander.shishkin
  Cc: Linux-kernel, ak, kan.liang, yao.jin, Jin Yao

perf report/script/... have a --time option to limit the time range
of output. That's very useful to slice large traces, e.g. when processing
the output of perf script for some analysis.

But right now --time only supports absolute time. Also there is no fast
way to get the start/end times of a given trace except for looking at it.
This makes it hard to e.g. only decode the first half of the trace, which
is useful for parallelization of scripts

Another problem is that perf records are variable size and there is no
synchronization mechanism. So the only way to find the last sample reliably
would be to walk all samples. But we want to avoid that in perf report/...
because it is already quite expensive. That is why storing the first sample
time and last sample time in perf record is better.

In perf record, it's walked on all samples yet. So it's very easy to get
the first/last samples and save the times in perf file header.

In later, perf record/script will fetch the time from perf file header.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
 tools/perf/builtin-record.c | 15 ++++++++++++
 tools/perf/util/header.c    | 59 ++++++++++++++++++++++++++++++++++++++++++---
 tools/perf/util/header.h    |  4 +++
 tools/perf/util/session.h   |  2 ++
 4 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 9b379f3..72be480 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -80,6 +80,8 @@ struct record {
 	bool			timestamp_filename;
 	struct switch_output	switch_output;
 	unsigned long long	samples;
+	u64			first_sample_time;
+	u64			last_sample_time;
 };
 
 static volatile int auxtrace_record__snapshot_started;
@@ -488,6 +490,11 @@ static int process_sample_event(struct perf_tool *tool,
 
 	rec->samples++;
 
+	if (rec->first_sample_time == 0)
+		rec->first_sample_time = sample->time;
+
+	rec->last_sample_time = sample->time;
+
 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
 }
 
@@ -1201,6 +1208,14 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
 
 	perf_hooks__invoke_record_end();
 
+	if (!err && !file->is_pipe) {
+		err = perf_header__update_sample_time(fd,
+						      rec->first_sample_time,
+						      rec->last_sample_time);
+		if (err < 0)
+			goto out_child;
+	}
+
 	if (!err && !quiet) {
 		char samples[128];
 		const char *postfix = rec->timestamp_filename ?
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 605bbd5..66c9b3e 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2277,6 +2277,37 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
 	return 0;
 }
 
+int perf_header__update_sample_time(int fd, u64 first_time, u64 last_time)
+{
+	struct perf_file_header header;
+	struct feat_fd ff;
+	off_t tmp;
+	ssize_t ret;
+	int err = -1;
+
+	tmp = lseek(fd, 0, SEEK_CUR);
+
+	lseek(fd, 0, SEEK_SET);
+	ret = readn(fd, &header, sizeof(header));
+	if (ret < 0)
+		goto exit;
+
+	header.first_sample_time = first_time;
+	header.last_sample_time = last_time;
+
+	lseek(fd, 0, SEEK_SET);
+	ff = (struct feat_fd){ .fd = fd};
+	err = do_write(&ff, &header, sizeof(header));
+	if (err < 0)
+		goto exit;
+
+	err = 0;
+
+exit:
+	lseek(fd, tmp, SEEK_SET);
+	return err;
+}
+
 static int do_write_feat(struct feat_fd *ff, int type,
 			 struct perf_file_section **p,
 			 struct perf_evlist *evlist)
@@ -2440,6 +2471,7 @@ int perf_session__write_header(struct perf_session *session,
 			.size	= header->data_size,
 		},
 		/* event_types is ignored, store zeros */
+		/* first_sample_time and last_sample_time store 0 */
 	};
 
 	memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
@@ -2627,6 +2659,8 @@ int perf_file_header__read(struct perf_file_header *header,
 			   struct perf_header *ph, int fd)
 {
 	ssize_t ret;
+	bool format_feature = true;
+	bool format_time = true;
 
 	lseek(fd, 0, SEEK_SET);
 
@@ -2647,11 +2681,22 @@ int perf_file_header__read(struct perf_file_header *header,
 
 	if (header->size != sizeof(*header)) {
 		/* Support the previous format */
-		if (header->size == offsetof(typeof(*header), adds_features))
+		if (header->size == offsetof(typeof(*header), adds_features)) {
 			bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
-		else
+			header->first_sample_time = 0;
+			header->last_sample_time = 0;
+			format_feature = false;
+			format_time = false;
+		} else if (header->size == offsetof(typeof(*header),
+				first_sample_time)) {
+			header->first_sample_time = 0;
+			header->last_sample_time = 0;
+			format_time = false;
+		} else
 			return -1;
-	} else if (ph->needs_swap) {
+	}
+
+	if (ph->needs_swap && format_feature) {
 		/*
 		 * feature bitmap is declared as an array of unsigned longs --
 		 * not good since its size can differ between the host that
@@ -2686,6 +2731,11 @@ int perf_file_header__read(struct perf_file_header *header,
 		}
 	}
 
+	if (ph->needs_swap && format_time) {
+		header->first_sample_time = bswap_64(header->first_sample_time);
+		header->last_sample_time = bswap_64(header->last_sample_time);
+	}
+
 	memcpy(&ph->adds_features, &header->adds_features,
 	       sizeof(ph->adds_features));
 
@@ -2942,6 +2992,9 @@ int perf_session__read_header(struct perf_session *session)
 		lseek(fd, tmp, SEEK_SET);
 	}
 
+	session->first_sample_time = f_header.first_sample_time;
+	session->last_sample_time = f_header.last_sample_time;
+
 	symbol_conf.nr_events = nr_attrs;
 
 	perf_header__process_sections(header, fd, &session->tevent,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index f7a16ee..cba51e8 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -56,6 +56,8 @@ struct perf_file_header {
 	/* event_types is ignored */
 	struct perf_file_section	event_types;
 	DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
+	u64				first_sample_time;
+	u64				last_sample_time;
 };
 
 struct perf_pipe_file_header {
@@ -101,6 +103,8 @@ int perf_header__process_sections(struct perf_header *header, int fd,
 
 int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
 
+int perf_header__update_sample_time(int fd, u64 first_time, u64 last_time);
+
 int perf_event__synthesize_features(struct perf_tool *tool,
 				    struct perf_session *session,
 				    struct perf_evlist *evlist,
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 47b5e7d..f98a3ca 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -31,6 +31,8 @@ struct perf_session {
 	bool			one_mmap;
 	void			*one_mmap_addr;
 	u64			one_mmap_offset;
+	u64			first_sample_time;
+	u64			last_sample_time;
 	struct ordered_events	ordered_events;
 	struct perf_data_file	*file;
 	struct perf_tool	*tool;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 2/6] perf Documentation: Update perf.data-file-format.txt
  2017-09-20 15:12 [PATCH v1 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
  2017-09-20 15:12 ` [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header Jin Yao
@ 2017-09-20 15:12 ` Jin Yao
  2017-09-20 15:12 ` [PATCH v1 3/6] perf util: Create function to parse time percent Jin Yao
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Jin Yao @ 2017-09-20 15:12 UTC (permalink / raw)
  To: acme, jolsa, peterz, mingo, alexander.shishkin
  Cc: Linux-kernel, ak, kan.liang, yao.jin, Jin Yao

Currently the perf.data file starts with a perf_file_header,
while in the document, it's perf_header. So update it by the
new definition.

It also adds the description for new fields first_sample_time
and last_sample_time. The new fields will be used in perf
record/script/... to slice the traces.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
 tools/perf/Documentation/perf.data-file-format.txt | 27 +++++++++++++---------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index e90c59c..7c27403 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -14,17 +14,18 @@ format that does not rely on seeking to adjust data offsets.  This
 format is described in "Pipe-mode data" section. The pipe data version can be
 augmented with additional events using perf inject.
 
-The file starts with a perf_header:
-
-struct perf_header {
-	char magic[8];		/* PERFILE2 */
-	uint64_t size;		/* size of the header */
-	uint64_t attr_size;	/* size of an attribute in attrs */
-	struct perf_file_section attrs;
-	struct perf_file_section data;
-	struct perf_file_section event_types;
-	uint64_t flags;
-	uint64_t flags1[3];
+The file starts with a perf_file_header:
+
+struct perf_file_header {
+	u64				magic;
+	u64				size;
+	u64				attr_size;
+	struct perf_file_section	attrs;
+	struct perf_file_section	data;
+	struct perf_file_section	event_types;
+	DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
+	u64				first_sample_time;
+	u64				last_sample_time;
 };
 
 The magic number identifies the perf file and the version. Current perf versions
@@ -416,6 +417,10 @@ An array bound by the perf_file_section size.
 
 ids points to a array of uint64_t defining the ids for event attr attr.
 
+first_sample_time and last_sample_time record the timestmaps of first sample
+and last sample. In later, perf record will fetch the time from perf file
+header and use them to slice the traces for parallelization.
+
 Pipe-mode data
 
 Pipe-mode avoid seeks in the file by removing the perf_file_section and flags
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 3/6] perf util: Create function to parse time percent
  2017-09-20 15:12 [PATCH v1 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
  2017-09-20 15:12 ` [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header Jin Yao
  2017-09-20 15:12 ` [PATCH v1 2/6] perf Documentation: Update perf.data-file-format.txt Jin Yao
@ 2017-09-20 15:12 ` Jin Yao
  2017-09-20 15:12 ` [PATCH v1 4/6] perf util: Create function to perform multiple time range checking Jin Yao
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Jin Yao @ 2017-09-20 15:12 UTC (permalink / raw)
  To: acme, jolsa, peterz, mingo, alexander.shishkin
  Cc: Linux-kernel, ak, kan.liang, yao.jin, Jin Yao

Current perf report/script/... have a --time option to limit the time
range of output. But right now it only supports absolute time.

For easy using, now it can support a percent of time usage.

For example:

1. Select the second 10% time slice
   perf report --time 10%/2

2. Select from 0% to 10% time slice
   perf report --time 0%-10%

It also support the multiple time ranges.

3. Select the first and second 10% time slices
   perf report --time 10%/1,10%/2

4. Select from 0% to 10% and 30% to 40% slices
   perf report --time 0%-10%,30%-40%

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
 tools/perf/util/time-utils.c | 203 ++++++++++++++++++++++++++++++++++++++++---
 tools/perf/util/time-utils.h |   3 +
 2 files changed, 194 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index 5b5d021..d46490f 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -5,6 +5,7 @@
 #include <time.h>
 #include <errno.h>
 #include <inttypes.h>
+#include <math.h>
 
 #include "perf.h"
 #include "debug.h"
@@ -59,11 +60,10 @@ static int parse_timestr_sec_nsec(struct perf_time_interval *ptime,
 	return 0;
 }
 
-int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
+static int split_start_end(char **start, char **end, const char *ostr, char ch)
 {
 	char *start_str, *end_str;
 	char *d, *str;
-	int rc = 0;
 
 	if (ostr == NULL || *ostr == '\0')
 		return 0;
@@ -73,25 +73,35 @@ int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
 	if (str == NULL)
 		return -ENOMEM;
 
-	ptime->start = 0;
-	ptime->end = 0;
-
-	/* str has the format: <start>,<stop>
-	 * variations: <start>,
-	 *             ,<stop>
-	 *             ,
-	 */
 	start_str = str;
-	d = strchr(start_str, ',');
+	d = strchr(start_str, ch);
 	if (d) {
 		*d = '\0';
 		++d;
 	}
 	end_str = d;
 
+	*start = start_str;
+	*end = end_str;
+
+	return 0;
+}
+
+int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
+{
+	char *start_str = NULL, *end_str;
+	int rc;
+
+	rc = split_start_end(&start_str, &end_str, ostr, ',');
+	if (rc || !start_str)
+		return rc;
+
+	ptime->start = 0;
+	ptime->end = 0;
+
 	rc = parse_timestr_sec_nsec(ptime, start_str, end_str);
 
-	free(str);
+	free(start_str);
 
 	/* make sure end time is after start time if it was given */
 	if (rc == 0 && ptime->end && ptime->end < ptime->start)
@@ -103,6 +113,175 @@ int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
 	return rc;
 }
 
+static int parse_percent(double *pcnt, char *str)
+{
+	char *c;
+
+	c = strchr(str, '%');
+	if (c)
+		*c = '\0';
+	else
+		return -1;
+
+	*pcnt = atof(str) / 100.0;
+
+	return 0;
+}
+
+static int percent_slash_split(char *str, struct perf_time_interval *ptime,
+			       u64 start, u64 end)
+{
+	char *p;
+	double pcnt, start_pcnt, end_pcnt;
+	u64 total = end - start;
+	int i;
+
+	/*
+	 * Example:
+	 * 10%/2: select the second 10% slice and the third 10% slice
+	 */
+
+	/* We can modify this string since the original one is copied */
+	p = strchr(str, '/');
+	if (!p)
+		return -1;
+
+	*p = '\0';
+	if (parse_percent(&pcnt, str) < 0)
+		return -1;
+
+	p++;
+	i = atoi(p);
+
+	if (pcnt <= 0.0)
+		return -1;
+
+	start_pcnt = pcnt * (i - 1);
+	end_pcnt = pcnt * i;
+
+	if (start_pcnt < 0.0 || start_pcnt > 1.0 ||
+	    end_pcnt < 0.0 || end_pcnt > 1.0) {
+		return -1;
+	}
+
+	ptime->start = start + round(start_pcnt * total);
+	ptime->end = start + round(end_pcnt * total);
+
+	return 0;
+}
+
+static int percent_dash_split(char *str, struct perf_time_interval *ptime,
+			      u64 start, u64 end)
+{
+	char *start_str = NULL, *end_str;
+	double start_pcnt, end_pcnt;
+	u64 total = end - start;
+	int ret;
+
+	/*
+	 * Example: 0%-10%
+	 */
+
+	ret = split_start_end(&start_str, &end_str, str, '-');
+	if (ret || !start_str)
+		return ret;
+
+	if ((parse_percent(&start_pcnt, start_str) != 0) ||
+	    (parse_percent(&end_pcnt, end_str) != 0)) {
+		free(start_str);
+		return -1;
+	}
+
+	free(start_str);
+
+	if (start_pcnt < 0.0 || start_pcnt > 1.0 ||
+	    end_pcnt < 0.0 || end_pcnt > 1.0 ||
+	    start_pcnt > end_pcnt) {
+		return -1;
+	}
+
+	ptime->start = start + round(start_pcnt * total);
+	ptime->end = start + round(end_pcnt * total);
+
+	return 0;
+}
+
+typedef int (*time_pecent_split)(char *, struct perf_time_interval *,
+				 u64 start, u64 end);
+
+static int percent_comma_split(struct perf_time_interval *ptime_buf, int num,
+			       const char *ostr, u64 start, u64 end,
+			       time_pecent_split func)
+{
+	char *str, *p1, *p2;
+	int len, ret, i = 0;
+
+	str = strdup(ostr);
+	if (str == NULL)
+		return -ENOMEM;
+
+	len = strlen(str);
+	p1 = str;
+
+	while (p1 < str + len) {
+		if (i >= num) {
+			free(str);
+			return -1;
+		}
+
+		p2 = strchr(p1, ',');
+		if (p2)
+			*p2 = '\0';
+
+		ret = (func)(p1, &ptime_buf[i], start, end);
+		if (ret < 0) {
+			free(str);
+			return -1;
+		}
+
+		pr_debug("start time %d: %" PRIu64 ", ", i, ptime_buf[i].start);
+		pr_debug("end time %d: %" PRIu64 "\n", i, ptime_buf[i].end);
+
+		i++;
+
+		if (p2)
+			p1 = p2 + 1;
+		else
+			break;
+	}
+
+	free(str);
+	return i;
+}
+
+int perf_time__percent_parse_str(struct perf_time_interval *ptime_buf, int num,
+				 const char *ostr, u64 start, u64 end)
+{
+	char *c;
+
+	/*
+	 * ostr example:
+	 * 10%/2,10%/3: select the second 10% slice and the third 10% slice
+	 * 0%-10%,30%-40%: multiple time range
+	 */
+
+	memset(ptime_buf, 0, sizeof(*ptime_buf) * num);
+
+	c = strchr(ostr, '/');
+	if (c) {
+		return percent_comma_split(ptime_buf, num, ostr, start,
+					   end, percent_slash_split);
+	}
+
+	c = strchr(ostr, '-');
+	if (c) {
+		return percent_comma_split(ptime_buf, num, ostr, start,
+					   end, percent_dash_split);
+	}
+
+	return -1;
+}
+
 bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp)
 {
 	/* if time is not set don't drop sample */
diff --git a/tools/perf/util/time-utils.h b/tools/perf/util/time-utils.h
index 8656be0..fd018e2 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -12,6 +12,9 @@ int parse_nsec_time(const char *str, u64 *ptime);
 
 int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr);
 
+int perf_time__percent_parse_str(struct perf_time_interval *ptime_buf, int num,
+				 const char *ostr, u64 start, u64 end);
+
 bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp);
 
 int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 4/6] perf util: Create function to perform multiple time range checking
  2017-09-20 15:12 [PATCH v1 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
                   ` (2 preceding siblings ...)
  2017-09-20 15:12 ` [PATCH v1 3/6] perf util: Create function to parse time percent Jin Yao
@ 2017-09-20 15:12 ` Jin Yao
  2017-09-20 15:12 ` [PATCH v1 5/6] perf report: support time percent and multiple time ranges Jin Yao
  2017-09-20 15:12 ` [PATCH v1 6/6] perf script: " Jin Yao
  5 siblings, 0 replies; 11+ messages in thread
From: Jin Yao @ 2017-09-20 15:12 UTC (permalink / raw)
  To: acme, jolsa, peterz, mingo, alexander.shishkin
  Cc: Linux-kernel, ak, kan.liang, yao.jin, Jin Yao

Previous patch supports the multiple time range.

For example, select the first and second 10% time slices.
perf report --time 10%/1,10%/2

We need a function to check if a timestamp is in the ranges of
[0, 10%) and [10%, 20%).

This patch implments a new function perf_time__ranges_skip_sample.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
 tools/perf/util/time-utils.c | 21 +++++++++++++++++++++
 tools/perf/util/time-utils.h |  3 +++
 2 files changed, 24 insertions(+)

diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index d46490f..d1f5121 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -297,6 +297,27 @@ bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp)
 	return false;
 }
 
+bool perf_time__ranges_skip_sample(struct perf_time_interval *ptime_buf,
+				   int num, u64 timestamp)
+{
+	struct perf_time_interval *ptime;
+	int i;
+
+	if ((timestamp == 0) || (num == 0))
+		return false;
+
+	for (i = 0; i < num; i++) {
+		ptime = &ptime_buf[i];
+
+		if ((timestamp >= ptime->start) &&
+		    (timestamp < ptime->end)) {
+			break;
+		}
+	}
+
+	return (i == num) ? true : false;
+}
+
 int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
 {
 	u64  sec = timestamp / NSEC_PER_SEC;
diff --git a/tools/perf/util/time-utils.h b/tools/perf/util/time-utils.h
index fd018e2..de279ea 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -17,6 +17,9 @@ int perf_time__percent_parse_str(struct perf_time_interval *ptime_buf, int num,
 
 bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp);
 
+bool perf_time__ranges_skip_sample(struct perf_time_interval *ptime_buf,
+				   int num, u64 timestamp);
+
 int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz);
 
 int fetch_current_timestamp(char *buf, size_t sz);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 5/6] perf report: support time percent and multiple time ranges
  2017-09-20 15:12 [PATCH v1 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
                   ` (3 preceding siblings ...)
  2017-09-20 15:12 ` [PATCH v1 4/6] perf util: Create function to perform multiple time range checking Jin Yao
@ 2017-09-20 15:12 ` Jin Yao
  2017-09-20 15:12 ` [PATCH v1 6/6] perf script: " Jin Yao
  5 siblings, 0 replies; 11+ messages in thread
From: Jin Yao @ 2017-09-20 15:12 UTC (permalink / raw)
  To: acme, jolsa, peterz, mingo, alexander.shishkin
  Cc: Linux-kernel, ak, kan.liang, yao.jin, Jin Yao

perf report has a --time option to limit the time range of output.
It only supports absolute time.

Now this option is extended to support multiple time ranges and
support the percent of time.

For example:

1. Select the first and second 10% time slices
perf report --time 10%/1,10%/2

2. Select from 0% to 10% and 30% to 40% slices
perf report --time 0%-10%,30%-40%

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
 tools/perf/Documentation/perf-report.txt | 16 ++++++++++++++++
 tools/perf/builtin-report.c              | 24 ++++++++++++++++++++++--
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 383a98d..3a0975c 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -402,6 +402,22 @@ OPTIONS
 	stop time is not given (i.e, time string is 'x.y,') then analysis goes
 	to end of file.
 
+	Also support time percent with multipe time range. Time string is
+	'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'. The maximum number of slices is 10.
+
+	For example:
+	Select the second 10% time slice
+	perf report --time 10%/2
+
+	Select from 0% to 10% time slice
+	perf report --time 0%-10%
+
+	Select the first and second 10% time slices
+	perf report --time 10%/1,10%/2
+
+	Select from 0% to 10% and 30% to 40% slices
+	perf report --time 0%-10%,30%-40%
+
 --itrace::
 	Options for decoding instruction tracing data. The options are:
 
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f9dff65..1bf25e0 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -51,6 +51,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#define PTIME_RANGE_MAX	10
+
 struct report {
 	struct perf_tool	tool;
 	struct perf_session	*session;
@@ -69,6 +71,8 @@ struct report {
 	const char		*symbol_filter_str;
 	const char		*time_str;
 	struct perf_time_interval ptime;
+	struct perf_time_interval ptime_range[PTIME_RANGE_MAX];
+	int			range_num;
 	float			min_percent;
 	u64			nr_entries;
 	u64			queue_size;
@@ -185,8 +189,11 @@ static int process_sample_event(struct perf_tool *tool,
 	};
 	int ret = 0;
 
-	if (perf_time__skip_sample(&rep->ptime, sample->time))
+	if (perf_time__skip_sample(&rep->ptime, sample->time) ||
+	    perf_time__ranges_skip_sample(rep->ptime_range, rep->range_num,
+					  sample->time)) {
 		return 0;
+	}
 
 	if (machine__resolve(machine, &al, sample) < 0) {
 		pr_debug("problem processing %d event, skipping it.\n",
@@ -1074,7 +1081,20 @@ int cmd_report(int argc, const char **argv)
 		goto error;
 
 	if (perf_time__parse_str(&report.ptime, report.time_str) != 0) {
-		pr_err("Invalid time string\n");
+		report.range_num = perf_time__percent_parse_str(
+					report.ptime_range, PTIME_RANGE_MAX,
+					report.time_str,
+					session->first_sample_time,
+					session->last_sample_time);
+
+		if (report.range_num < 0) {
+			pr_err("Invalid time string\n");
+			return -EINVAL;
+		}
+	}
+
+	if (report.range_num > 0 && perf_data_file__is_pipe(session->file)) {
+		pr_err("Time percent range is not supported in pipe\n");
 		return -EINVAL;
 	}
 
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v1 6/6] perf script: support time percent and multiple time ranges
  2017-09-20 15:12 [PATCH v1 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
                   ` (4 preceding siblings ...)
  2017-09-20 15:12 ` [PATCH v1 5/6] perf report: support time percent and multiple time ranges Jin Yao
@ 2017-09-20 15:12 ` Jin Yao
  5 siblings, 0 replies; 11+ messages in thread
From: Jin Yao @ 2017-09-20 15:12 UTC (permalink / raw)
  To: acme, jolsa, peterz, mingo, alexander.shishkin
  Cc: Linux-kernel, ak, kan.liang, yao.jin, Jin Yao

perf script has a --time option to limit the time range of output.
It only supports absolute time.

Now this option is extended to support multiple time ranges and
support the percent of time.

For example:

1. Select the first and second 10% time slices
   perf script --time 10%/1,10%/2

2. Select from 0% to 10% and 30% to 40% slices
   perf script --time 0%-10%,30%-40%

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
 tools/perf/Documentation/perf-script.txt | 16 ++++++++++++++++
 tools/perf/builtin-script.c              | 21 ++++++++++++++++++---
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 18dfcfa..f772f37 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -321,6 +321,22 @@ include::itrace.txt[]
 	stop time is not given (i.e, time string is 'x.y,') then analysis goes
 	to end of file.
 
+	Also support time percent with multipe time range. Time string is
+	'a%/n,b%/m,...' or 'a%-b%,c%-%d,...'. The maximum number of slices is 10.
+
+	For example:
+	Select the second 10% time slice
+	perf script --time 10%/2
+
+	Select from 0% to 10% time slice
+	perf script --time 0%-10%
+
+	Select the first and second 10% time slices
+	perf script --time 10%/1,10%/2
+
+	Select from 0% to 10% and 30% to 40% slices
+	perf script --time 0%-10%,30%-40%
+
 --max-blocks::
 	Set the maximum number of program blocks to print with brstackasm for
 	each sample.
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 3d4c3b5..ddb9516 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1332,6 +1332,8 @@ static void print_sample_synth(struct perf_sample *sample,
 	}
 }
 
+#define PTIME_RANGE_MAX	10
+
 struct perf_script {
 	struct perf_tool	tool;
 	struct perf_session	*session;
@@ -1345,6 +1347,8 @@ struct perf_script {
 	int			name_width;
 	const char              *time_str;
 	struct perf_time_interval ptime;
+	struct perf_time_interval ptime_range[PTIME_RANGE_MAX];
+	int			range_num;
 };
 
 static int perf_evlist__max_name_len(struct perf_evlist *evlist)
@@ -1537,8 +1541,11 @@ static int process_sample_event(struct perf_tool *tool,
 	struct perf_script *scr = container_of(tool, struct perf_script, tool);
 	struct addr_location al;
 
-	if (perf_time__skip_sample(&scr->ptime, sample->time))
+	if (perf_time__skip_sample(&scr->ptime, sample->time) ||
+	    perf_time__ranges_skip_sample(scr->ptime_range, scr->range_num,
+					  sample->time)) {
 		return 0;
+	}
 
 	if (debug_mode) {
 		if (sample->time < last_timestamp) {
@@ -3074,8 +3081,16 @@ int cmd_script(int argc, const char **argv)
 
 	/* needs to be parsed after looking up reference time */
 	if (perf_time__parse_str(&script.ptime, script.time_str) != 0) {
-		pr_err("Invalid time string\n");
-		return -EINVAL;
+		script.range_num = perf_time__percent_parse_str(
+					script.ptime_range, PTIME_RANGE_MAX,
+					script.time_str,
+					session->first_sample_time,
+					session->last_sample_time);
+
+		if (script.range_num < 0) {
+			pr_err("Invalid time string\n");
+			return -EINVAL;
+		}
 	}
 
 	err = __cmd_script(&script);
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header
  2017-09-20 15:12 ` [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header Jin Yao
@ 2017-09-21 15:17   ` Jiri Olsa
  2017-09-21 15:18   ` Jiri Olsa
  1 sibling, 0 replies; 11+ messages in thread
From: Jiri Olsa @ 2017-09-21 15:17 UTC (permalink / raw)
  To: Jin Yao
  Cc: acme, jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

On Wed, Sep 20, 2017 at 11:12:32PM +0800, Jin Yao wrote:

SNIP

> @@ -2686,6 +2731,11 @@ int perf_file_header__read(struct perf_file_header *header,
>  		}
>  	}
>  
> +	if (ph->needs_swap && format_time) {
> +		header->first_sample_time = bswap_64(header->first_sample_time);
> +		header->last_sample_time = bswap_64(header->last_sample_time);
> +	}
> +
>  	memcpy(&ph->adds_features, &header->adds_features,
>  	       sizeof(ph->adds_features));
>  
> @@ -2942,6 +2992,9 @@ int perf_session__read_header(struct perf_session *session)
>  		lseek(fd, tmp, SEEK_SET);
>  	}
>  
> +	session->first_sample_time = f_header.first_sample_time;
> +	session->last_sample_time = f_header.last_sample_time;
> +
>  	symbol_conf.nr_events = nr_attrs;
>  
>  	perf_header__process_sections(header, fd, &session->tevent,
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index f7a16ee..cba51e8 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -56,6 +56,8 @@ struct perf_file_header {
>  	/* event_types is ignored */
>  	struct perf_file_section	event_types;
>  	DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
> +	u64				first_sample_time;
> +	u64				last_sample_time;

you can't add it here just like that, because you lose the
backward compatibility.. you need to add new feature

jirka

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header
  2017-09-20 15:12 ` [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header Jin Yao
  2017-09-21 15:17   ` Jiri Olsa
@ 2017-09-21 15:18   ` Jiri Olsa
  2017-09-21 15:21     ` Jiri Olsa
  1 sibling, 1 reply; 11+ messages in thread
From: Jiri Olsa @ 2017-09-21 15:18 UTC (permalink / raw)
  To: Jin Yao
  Cc: acme, jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

On Wed, Sep 20, 2017 at 11:12:32PM +0800, Jin Yao wrote:

SNIP

> @@ -2647,11 +2681,22 @@ int perf_file_header__read(struct perf_file_header *header,
>  
>  	if (header->size != sizeof(*header)) {
>  		/* Support the previous format */
> -		if (header->size == offsetof(typeof(*header), adds_features))
> +		if (header->size == offsetof(typeof(*header), adds_features)) {
>  			bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
> -		else
> +			header->first_sample_time = 0;
> +			header->last_sample_time = 0;
> +			format_feature = false;
> +			format_time = false;
> +		} else if (header->size == offsetof(typeof(*header),
> +				first_sample_time)) {
> +			header->first_sample_time = 0;
> +			header->last_sample_time = 0;
> +			format_time = false;
> +		} else

ok, disregard my previou comment.. I should have read the full patch first ;-)

jirka

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header
  2017-09-21 15:18   ` Jiri Olsa
@ 2017-09-21 15:21     ` Jiri Olsa
  2017-09-22  0:46       ` Jin, Yao
  0 siblings, 1 reply; 11+ messages in thread
From: Jiri Olsa @ 2017-09-21 15:21 UTC (permalink / raw)
  To: Jin Yao
  Cc: acme, jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

On Thu, Sep 21, 2017 at 05:18:42PM +0200, Jiri Olsa wrote:
> On Wed, Sep 20, 2017 at 11:12:32PM +0800, Jin Yao wrote:
> 
> SNIP
> 
> > @@ -2647,11 +2681,22 @@ int perf_file_header__read(struct perf_file_header *header,
> >  
> >  	if (header->size != sizeof(*header)) {
> >  		/* Support the previous format */
> > -		if (header->size == offsetof(typeof(*header), adds_features))
> > +		if (header->size == offsetof(typeof(*header), adds_features)) {
> >  			bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
> > -		else
> > +			header->first_sample_time = 0;
> > +			header->last_sample_time = 0;
> > +			format_feature = false;
> > +			format_time = false;
> > +		} else if (header->size == offsetof(typeof(*header),
> > +				first_sample_time)) {
> > +			header->first_sample_time = 0;
> > +			header->last_sample_time = 0;
> > +			format_time = false;
> > +		} else
> 
> ok, disregard my previou comment.. I should have read the full patch first ;-)

still using the feature looks better to me.. I think we could
add some generic TLV data feature for cases like this

jirka

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header
  2017-09-21 15:21     ` Jiri Olsa
@ 2017-09-22  0:46       ` Jin, Yao
  0 siblings, 0 replies; 11+ messages in thread
From: Jin, Yao @ 2017-09-22  0:46 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: acme, jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin



On 9/21/2017 11:21 PM, Jiri Olsa wrote:
> On Thu, Sep 21, 2017 at 05:18:42PM +0200, Jiri Olsa wrote:
>> On Wed, Sep 20, 2017 at 11:12:32PM +0800, Jin Yao wrote:
>>
>> SNIP
>>
>>> @@ -2647,11 +2681,22 @@ int perf_file_header__read(struct perf_file_header *header,
>>>  
>>>  	if (header->size != sizeof(*header)) {
>>>  		/* Support the previous format */
>>> -		if (header->size == offsetof(typeof(*header), adds_features))
>>> +		if (header->size == offsetof(typeof(*header), adds_features)) {
>>>  			bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
>>> -		else
>>> +			header->first_sample_time = 0;
>>> +			header->last_sample_time = 0;
>>> +			format_feature = false;
>>> +			format_time = false;
>>> +		} else if (header->size == offsetof(typeof(*header),
>>> +				first_sample_time)) {
>>> +			header->first_sample_time = 0;
>>> +			header->last_sample_time = 0;
>>> +			format_time = false;
>>> +		} else
>>
>> ok, disregard my previou comment.. I should have read the full patch first ;-)
> 
> still using the feature looks better to me.. I think we could
> add some generic TLV data feature for cases like this
> 
> jirka
> 

Thanks for the comments!

I will check how to add generic TLV data feature to record the first sample time and last sample time.

Thanks
Jin Yao

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-09-22  0:46 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-20 15:12 [PATCH v1 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
2017-09-20 15:12 ` [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header Jin Yao
2017-09-21 15:17   ` Jiri Olsa
2017-09-21 15:18   ` Jiri Olsa
2017-09-21 15:21     ` Jiri Olsa
2017-09-22  0:46       ` Jin, Yao
2017-09-20 15:12 ` [PATCH v1 2/6] perf Documentation: Update perf.data-file-format.txt Jin Yao
2017-09-20 15:12 ` [PATCH v1 3/6] perf util: Create function to parse time percent Jin Yao
2017-09-20 15:12 ` [PATCH v1 4/6] perf util: Create function to perform multiple time range checking Jin Yao
2017-09-20 15:12 ` [PATCH v1 5/6] perf report: support time percent and multiple time ranges Jin Yao
2017-09-20 15:12 ` [PATCH v1 6/6] perf script: " Jin Yao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.