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

v7:
---
v7 doesn't have functional change. The update is only:

1. Rebase to latest perf/core branch

2. Update patch description according to Arnaldo's comments.

Impacted patch:
---------------
  perf header: Record first sample time and last sample time in perf file header
  perf record: Get the first sample time and last sample time

v6:
---
1. Create a new option "--timestamp-boundary" in perf record.
   
   Currently '--buildid-all' is not enabled by default. So the walking
   on all samples is the default operation. There is no big overhead
   to calculate the timestamp boundary in process_sample_event handler
   once we already go through all samples. So the timestamp boundary
   calculation is enabled by default when '--buildid-all' is not enabled.

   While if '--buildid-all' is enabled, we creates a new option
   "--timestamp-boundary" for user to decide if it enables the
   timestamp boundary calculation.

   Impacted patch:
   ---------------
   perf record: Get the first sample time and last sample time

2. Fix the merge issue with the latest perf/core branch.
   No functional changes.

   Impacted patch:
   ---------------
   perf report: support time percent and multiple time ranges
   perf script: support time percent and multiple time ranges

v5:
---
1. There is an issue that the sample walking can only work when
   '--buildid-all' is not enabled. So we need to let the walking
   be able to work even if '--buildid-all' is enabled and let the
   processing skips the dso hit marking for this case.

2. Check if first/last sample time is recorded in perf data file.
   If it's not recorded, return error message to user.

Patched modified in v5:
   perf record: Get the first sample time and last sample time
   perf report: support time percent and multiple time ranges
   perf script: support time percent and multiple time ranges

v4:
---
1. Use perf script time style for timestamp printing. Also add with
   the printing of sample duration. For example:

   perf report --header

   time of first sample : 5276531.323099
   time of last sample : 5276555.345625
   sample duration :  24022.526 ms

2. Fix an invalid time string issue. For example,

   perf script --time 10%/10x12321xsdfdasfdsafdsafdsa

   Now in code, it uses strtol to replace atoi.

3. Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample
   in perf report/perf script.

v3:
---
1. Move the definitions of first_sample_time/last_sample_time from
   perf_session and struct record to perf_evlist and update the
   related code.

v2:
---
1. This patch creates a new header feature type HEADER_SAMPLE_TIME and related
   ops. Save the first sample time and the last sample time to the feature
   section in perf file header.

2. Add checking for last element in time range.

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

   Note that now it includes the last element in [10%, 20%] but it
   doesn't include the last element in [0, 10%). It's to avoid
   the overlap.

Following patches are changed:

   perf header: Record first sample time and last sample time in perf file header
   perf record: Get the first sample time and last sample time
   perf util: Create function to perform multiple time range checking

v1: initial post
----------------

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 header: Record first sample time and last sample time in perf
    file header
  perf record: Get the first sample time and last sample time
  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-record.txt           |   3 +
 tools/perf/Documentation/perf-report.txt           |  16 ++
 tools/perf/Documentation/perf-script.txt           |  16 ++
 tools/perf/Documentation/perf.data-file-format.txt |   4 +
 tools/perf/builtin-record.c                        |  18 +-
 tools/perf/builtin-report.c                        |  31 ++-
 tools/perf/builtin-script.c                        |  34 ++-
 tools/perf/util/evlist.h                           |   2 +
 tools/perf/util/header.c                           |  60 ++++++
 tools/perf/util/header.h                           |   1 +
 tools/perf/util/time-utils.c                       | 233 +++++++++++++++++++--
 tools/perf/util/time-utils.h                       |   6 +
 12 files changed, 398 insertions(+), 26 deletions(-)

-- 
2.7.4

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

* [PATCH v7 1/6] perf header: Record first sample time and last sample time in perf file header
  2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
@ 2017-12-08 13:13 ` Jin Yao
  2018-01-11  6:21   ` [tip:perf/core] perf header: Add infrastructure to record first and last sample time tip-bot for Jin Yao
  2017-12-08 13:13 ` [PATCH v7 2/6] perf record: Get the first sample time " Jin Yao
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: Jin Yao @ 2017-12-08 13:13 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.

This patch creates a new header feature type HEADER_SAMPLE_TIME and related
ops. Save the first sample time and the last sample time to the feature
section in perf file header. That will be done when, for instance,
processing build-ids, where we already have to process all samples to
create the build-id table, take advantage of that to further amortize that
processing by storing HEADER_SAMPLE_TIME to make 'perf report/script'
faster when using --time.

Change log:
-----------
v7: 1. Rebase to latest perf/core branch.

    2. Add following clarification in patch description according to
       Arnaldo's suggestion.

       "That will be done when, for instance, processing build-ids,
	where we already have to process all samples to create the
	build-id table, take advantage of that to further amortize
	that processing by storing HEADER_SAMPLE_TIME to make
	'perf report/script' faster when using --time."

v4: Use perf script time style for timestamp printing. Also add with
    the printing of sample duration.

v3: Remove the definitions of first_sample_time/last_sample_time from
    perf_session. Just define them in perf_evlist

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
---
 tools/perf/Documentation/perf.data-file-format.txt |  4 ++
 tools/perf/util/evlist.h                           |  2 +
 tools/perf/util/header.c                           | 60 ++++++++++++++++++++++
 tools/perf/util/header.h                           |  1 +
 4 files changed, 67 insertions(+)

diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index 15e8b48..f7d85e8 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -261,6 +261,10 @@ struct {
 	struct perf_header_string map;
 }[number_of_cache_levels];
 
+	HEADER_SAMPLE_TIME = 21,
+
+Two uint64_t for the time of first sample and the time of last sample.
+
 	other bits are reserved and should ignored for now
 	HEADER_FEAT_BITS	= 256,
 
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 7516066..e7fbca6 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -50,6 +50,8 @@ struct perf_evlist {
 	struct perf_evsel *selected;
 	struct events_stats stats;
 	struct perf_env	*env;
+	u64		first_sample_time;
+	u64		last_sample_time;
 };
 
 struct perf_evsel_str_handler {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ca73aa7..a326e0d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -16,6 +16,7 @@
 #include <linux/stringify.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
+#include <linux/time64.h>
 
 #include "evlist.h"
 #include "evsel.h"
@@ -35,6 +36,7 @@
 #include <api/fs/fs.h>
 #include "asm/bug.h"
 #include "tool.h"
+#include "time-utils.h"
 
 #include "sane_ctype.h"
 
@@ -1180,6 +1182,20 @@ static int write_stat(struct feat_fd *ff __maybe_unused,
 	return 0;
 }
 
+static int write_sample_time(struct feat_fd *ff,
+			     struct perf_evlist *evlist)
+{
+	int ret;
+
+	ret = do_write(ff, &evlist->first_sample_time,
+		       sizeof(evlist->first_sample_time));
+	if (ret < 0)
+		return ret;
+
+	return do_write(ff, &evlist->last_sample_time,
+			sizeof(evlist->last_sample_time));
+}
+
 static void print_hostname(struct feat_fd *ff, FILE *fp)
 {
 	fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
@@ -1505,6 +1521,28 @@ static void print_group_desc(struct feat_fd *ff, FILE *fp)
 	}
 }
 
+static void print_sample_time(struct feat_fd *ff, FILE *fp)
+{
+	struct perf_session *session;
+	char time_buf[32];
+	double d;
+
+	session = container_of(ff->ph, struct perf_session, header);
+
+	timestamp__scnprintf_usec(session->evlist->first_sample_time,
+				  time_buf, sizeof(time_buf));
+	fprintf(fp, "# time of first sample : %s\n", time_buf);
+
+	timestamp__scnprintf_usec(session->evlist->last_sample_time,
+				  time_buf, sizeof(time_buf));
+	fprintf(fp, "# time of last sample : %s\n", time_buf);
+
+	d = (double)(session->evlist->last_sample_time -
+		session->evlist->first_sample_time) / NSEC_PER_MSEC;
+
+	fprintf(fp, "# sample duration : %10.3f ms\n", d);
+}
+
 static int __event_process_build_id(struct build_id_event *bev,
 				    char *filename,
 				    struct perf_session *session)
@@ -2146,6 +2184,27 @@ static int process_cache(struct feat_fd *ff, void *data __maybe_unused)
 	return -1;
 }
 
+static int process_sample_time(struct feat_fd *ff, void *data __maybe_unused)
+{
+	struct perf_session *session;
+	u64 first_sample_time, last_sample_time;
+	int ret;
+
+	session = container_of(ff->ph, struct perf_session, header);
+
+	ret = do_read_u64(ff, &first_sample_time);
+	if (ret)
+		return -1;
+
+	ret = do_read_u64(ff, &last_sample_time);
+	if (ret)
+		return -1;
+
+	session->evlist->first_sample_time = first_sample_time;
+	session->evlist->last_sample_time = last_sample_time;
+	return 0;
+}
+
 struct feature_ops {
 	int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
 	void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2203,6 +2262,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPN(AUXTRACE,	auxtrace,	false),
 	FEAT_OPN(STAT,		stat,		false),
 	FEAT_OPN(CACHE,		cache,		true),
+	FEAT_OPR(SAMPLE_TIME,	sample_time,	false),
 };
 
 struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 317fb90..f28aaaa 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -35,6 +35,7 @@ enum {
 	HEADER_AUXTRACE,
 	HEADER_STAT,
 	HEADER_CACHE,
+	HEADER_SAMPLE_TIME,
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
 };
-- 
2.7.4

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

* [PATCH v7 2/6] perf record: Get the first sample time and last sample time
  2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
  2017-12-08 13:13 ` [PATCH v7 1/6] perf header: Record first sample time and last sample time in perf file header Jin Yao
@ 2017-12-08 13:13 ` Jin Yao
  2018-01-04 19:09   ` Arnaldo Carvalho de Melo
  2018-01-11  6:22   ` [tip:perf/core] perf record: Record the first and last sample time in the header tip-bot for Jin Yao
  2017-12-08 13:13 ` [PATCH v7 3/6] perf util: Create function to parse time percent Jin Yao
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 29+ messages in thread
From: Jin Yao @ 2017-12-08 13:13 UTC (permalink / raw)
  To: acme, jolsa, peterz, mingo, alexander.shishkin
  Cc: Linux-kernel, ak, kan.liang, yao.jin, Jin Yao

In the default 'perf record' configuration, all samples are processed,
to create the HEADER_BUILD_ID table. So it's very easy to get the
first/last samples and save the time to perf file header via the
function write_sample_time().

Later, at post processing time, perf report/script will fetch
the time from perf file header.

Change log:
-----------
v7: Just update the patch description according to Arnaldo's suggestion.

v6: Currently '--buildid-all' is not enabled at default. So the walking
    on all samples is the default operation. There is no big overhead
    to calculate the timestamp boundary in process_sample_event handler
    once we already go through all samples. So the timestamp boundary
    calculation is enabled by default when '--buildid-all' is not enabled.

    While if '--buildid-all' is enabled, we creates a new option
    "--timestamp-boundary" for user to decide if it enables the
    timestamp boundary calculation.

v5: There is an issue that the sample walking can only work when
    '--buildid-all' is not enabled. So we need to let the walking
    be able to work even if '--buildid-all' is enabled and let the
    processing skips the dso hit marking for this case.

    At first, I want to provide a new option "--record-time-boundaries".
    While after consideration, I think a new option is not very
    necessary.

v3: Remove the definitions of first_sample_time and last_sample_time
    from struct record and directly save them in perf_evlist.

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

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 5a626ef..3eea6de 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -430,6 +430,9 @@ Configure all used events to run in user space.
 --timestamp-filename
 Append timestamp to output file name.
 
+--timestamp-boundary::
+Record timestamp boundary (time of first/last samples).
+
 --switch-output[=mode]::
 Generate multiple perf.data files, timestamp prefixed, switching to a new one
 based on 'mode' value:
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 98da8cb..6db7b5a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -78,6 +78,7 @@ struct record {
 	bool			no_buildid_cache_set;
 	bool			buildid_all;
 	bool			timestamp_filename;
+	bool			timestamp_boundary;
 	struct switch_output	switch_output;
 	unsigned long long	samples;
 };
@@ -409,8 +410,15 @@ static int process_sample_event(struct perf_tool *tool,
 {
 	struct record *rec = container_of(tool, struct record, tool);
 
-	rec->samples++;
+	if (rec->evlist->first_sample_time == 0)
+		rec->evlist->first_sample_time = sample->time;
+
+	rec->evlist->last_sample_time = sample->time;
 
+	if (rec->buildid_all)
+		return 0;
+
+	rec->samples++;
 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
 }
 
@@ -435,9 +443,11 @@ static int process_buildids(struct record *rec)
 
 	/*
 	 * If --buildid-all is given, it marks all DSO regardless of hits,
-	 * so no need to process samples.
+	 * so no need to process samples. But if timestamp_boundary is enabled,
+	 * it still needs to walk on all samples to get the timestamps of
+	 * first/last samples.
 	 */
-	if (rec->buildid_all)
+	if (rec->buildid_all && !rec->timestamp_boundary)
 		rec->tool.sample = NULL;
 
 	return perf_session__process_events(session);
@@ -1621,6 +1631,8 @@ static struct option __record_options[] = {
 		    "Record build-id of all DSOs regardless of hits"),
 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
 		    "append timestamp to output filename"),
+	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
+		    "Record timestamp boundary (time of first/last samples)"),
 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
 			  &record.switch_output.set, "signal,size,time",
 			  "Switch output when receive SIGUSR2 or cross size,time threshold",
-- 
2.7.4

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

* [PATCH v7 3/6] perf util: Create function to parse time percent
  2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
  2017-12-08 13:13 ` [PATCH v7 1/6] perf header: Record first sample time and last sample time in perf file header Jin Yao
  2017-12-08 13:13 ` [PATCH v7 2/6] perf record: Get the first sample time " Jin Yao
@ 2017-12-08 13:13 ` Jin Yao
  2018-01-08 14:31   ` Arnaldo Carvalho de Melo
  2018-01-11  6:22   ` [tip:perf/core] perf tools: " tip-bot for Jin Yao
  2017-12-08 13:13 ` [PATCH v7 4/6] perf util: Create function to perform multiple time range checking Jin Yao
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 29+ messages in thread
From: Jin Yao @ 2017-12-08 13:13 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%

Change log:
-----------
v4: An issue is found. Following passes.
    perf script --time 10%/10x12321xsdfdasfdsafdsafdsa

    Now it uses strtol to replace atoi.

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

diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index 81927d0..61c46022 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -6,6 +6,7 @@
 #include <time.h>
 #include <errno.h>
 #include <inttypes.h>
+#include <math.h>
 
 #include "perf.h"
 #include "debug.h"
@@ -60,11 +61,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;
@@ -74,25 +74,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)
@@ -104,6 +114,177 @@ 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, *end_str;
+	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 = (int)strtol(p, &end_str, 10);
+	if (*end_str)
+		return -1;
+
+	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 15b475c..2308723 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -13,6 +13,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] 29+ messages in thread

* [PATCH v7 4/6] perf util: Create function to perform multiple time range checking
  2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
                   ` (2 preceding siblings ...)
  2017-12-08 13:13 ` [PATCH v7 3/6] perf util: Create function to parse time percent Jin Yao
@ 2017-12-08 13:13 ` Jin Yao
  2018-01-11  6:22   ` [tip:perf/core] perf tools: " tip-bot for Jin Yao
  2017-12-08 13:13 ` [PATCH v7 5/6] perf report: support time percent and multiple time ranges Jin Yao
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: Jin Yao @ 2017-12-08 13:13 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%].

Note that it includes the last element in [10%, 20%] but it
doesn't include the last element in [0, 10%). It's to avoid
the overlap.

This patch implments a new function perf_time__ranges_skip_sample
for this checking.

Change log:
-----------
v4: Let perf_time__ranges_skip_sample be compatible with
    perf_time__skip_sample when only one time range.

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

diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index 61c46022..3f7f18f 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -300,6 +300,34 @@ 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;
+
+	if (num == 1)
+		return perf_time__skip_sample(&ptime_buf[0], timestamp);
+
+	/*
+	 * start/end of multiple time ranges must be valid.
+	 */
+	for (i = 0; i < num; i++) {
+		ptime = &ptime_buf[i];
+
+		if (timestamp >= ptime->start &&
+		    ((timestamp < ptime->end && i < num - 1) ||
+		     (timestamp <= ptime->end && i == num - 1))) {
+			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 2308723..34d5eba 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -18,6 +18,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] 29+ messages in thread

* [PATCH v7 5/6] perf report: support time percent and multiple time ranges
  2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
                   ` (3 preceding siblings ...)
  2017-12-08 13:13 ` [PATCH v7 4/6] perf util: Create function to perform multiple time range checking Jin Yao
@ 2017-12-08 13:13 ` Jin Yao
  2018-01-08 14:45   ` Arnaldo Carvalho de Melo
                     ` (2 more replies)
  2017-12-08 13:13 ` [PATCH v7 6/6] perf script: support " Jin Yao
                   ` (2 subsequent siblings)
  7 siblings, 3 replies; 29+ messages in thread
From: Jin Yao @ 2017-12-08 13:13 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%

Change log:
-----------
v6: Fix the merge issue with latest perf/core branch.
    No functional changes.

v5: Add checking of first/last sample time to detect if it's recorded
    in perf.data. If it's not recorded, returns error message to user.

v4: Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample

v3: Since the definitions of first_sample_time/last_sample_time
    are moved from perf_session to perf_evlist so change the
    related code.

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

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index ddde2b5..ed36553 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 eb9ce63..946f146 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -52,6 +52,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#define PTIME_RANGE_MAX	10
+
 struct report {
 	struct perf_tool	tool;
 	struct perf_session	*session;
@@ -69,7 +71,8 @@ struct report {
 	const char		*cpu_list;
 	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;
@@ -186,8 +189,10 @@ static int process_sample_event(struct perf_tool *tool,
 	};
 	int ret = 0;
 
-	if (perf_time__skip_sample(&rep->ptime, sample->time))
+	if (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",
@@ -1077,9 +1082,25 @@ int cmd_report(int argc, const char **argv)
 	if (symbol__init(&session->header.env) < 0)
 		goto error;
 
-	if (perf_time__parse_str(&report.ptime, report.time_str) != 0) {
-		pr_err("Invalid time string\n");
-		return -EINVAL;
+	if (perf_time__parse_str(report.ptime_range, report.time_str) != 0) {
+		if (session->evlist->first_sample_time == 0 &&
+		    session->evlist->last_sample_time == 0) {
+			pr_err("No first/last sample time in perf data\n");
+			return -EINVAL;
+		}
+
+		report.range_num = perf_time__percent_parse_str(
+					report.ptime_range, PTIME_RANGE_MAX,
+					report.time_str,
+					session->evlist->first_sample_time,
+					session->evlist->last_sample_time);
+
+		if (report.range_num < 0) {
+			pr_err("Invalid time string\n");
+			return -EINVAL;
+		}
+	} else {
+		report.range_num = 1;
 	}
 
 	sort__setup_elide(stdout);
-- 
2.7.4

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

* [PATCH v7 6/6] perf script: support time percent and multiple time ranges
  2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
                   ` (4 preceding siblings ...)
  2017-12-08 13:13 ` [PATCH v7 5/6] perf report: support time percent and multiple time ranges Jin Yao
@ 2017-12-08 13:13 ` Jin Yao
  2018-01-11  6:23   ` [tip:perf/core] perf script: Support " tip-bot for Jin Yao
  2017-12-13 14:28 ` [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Arnaldo Carvalho de Melo
  2017-12-14 14:08 ` Jiri Olsa
  7 siblings, 1 reply; 29+ messages in thread
From: Jin Yao @ 2017-12-08 13:13 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%

Change log:
-----------
v6: Fix the merge issue with latest perf/core branch.
    No functional changes.

v5: Add checking of first/last sample time to detect if it's recorded
    in perf.data. If it's not recorded, returns error message to user.

v4: Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample

v3: Since the definitions of first_sample_time/last_sample_time
    are moved from perf_session to perf_evlist so change the
    related code.

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

diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 974ceb1..7b622a8 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -329,6 +329,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 77e47cf..330dcd9 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1436,6 +1436,8 @@ static int perf_sample__fprintf_synth(struct perf_sample *sample,
 	return 0;
 }
 
+#define PTIME_RANGE_MAX	10
+
 struct perf_script {
 	struct perf_tool	tool;
 	struct perf_session	*session;
@@ -1449,7 +1451,8 @@ struct perf_script {
 	struct thread_map	*threads;
 	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)
@@ -1734,8 +1737,10 @@ 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__ranges_skip_sample(scr->ptime_range, scr->range_num,
+					  sample->time)) {
 		return 0;
+	}
 
 	if (debug_mode) {
 		if (sample->time < last_timestamp) {
@@ -3360,10 +3365,27 @@ int cmd_script(int argc, const char **argv)
 		goto out_delete;
 
 	/* 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");
-		err = -EINVAL;
-		goto out_delete;
+	if (perf_time__parse_str(script.ptime_range, script.time_str) != 0) {
+		if (session->evlist->first_sample_time == 0 &&
+		    session->evlist->last_sample_time == 0) {
+			pr_err("No first/last sample time in perf data\n");
+			err = -EINVAL;
+			goto out_delete;
+		}
+
+		script.range_num = perf_time__percent_parse_str(
+					script.ptime_range, PTIME_RANGE_MAX,
+					script.time_str,
+					session->evlist->first_sample_time,
+					session->evlist->last_sample_time);
+
+		if (script.range_num < 0) {
+			pr_err("Invalid time string\n");
+			err = -EINVAL;
+			goto out_delete;
+		}
+	} else {
+		script.range_num = 1;
 	}
 
 	err = __cmd_script(&script);
-- 
2.7.4

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

* Re: [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option
  2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
                   ` (5 preceding siblings ...)
  2017-12-08 13:13 ` [PATCH v7 6/6] perf script: support " Jin Yao
@ 2017-12-13 14:28 ` Arnaldo Carvalho de Melo
  2017-12-14  0:48   ` Jin, Yao
  2017-12-14 14:08 ` Jiri Olsa
  7 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-12-13 14:28 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Fri, Dec 08, 2017 at 09:13:40PM +0800, Jin Yao escreveu:
> v7:
> ---
> v7 doesn't have functional change. The update is only:

Thanks for working on this, will try and get this processed in my next
round.

- Arnaldo
 
> 1. Rebase to latest perf/core branch
> 
> 2. Update patch description according to Arnaldo's comments.
> 
> Impacted patch:
> ---------------
>   perf header: Record first sample time and last sample time in perf file header
>   perf record: Get the first sample time and last sample time
> 
> v6:
> ---
> 1. Create a new option "--timestamp-boundary" in perf record.
>    
>    Currently '--buildid-all' is not enabled by default. So the walking
>    on all samples is the default operation. There is no big overhead
>    to calculate the timestamp boundary in process_sample_event handler
>    once we already go through all samples. So the timestamp boundary
>    calculation is enabled by default when '--buildid-all' is not enabled.
> 
>    While if '--buildid-all' is enabled, we creates a new option
>    "--timestamp-boundary" for user to decide if it enables the
>    timestamp boundary calculation.
> 
>    Impacted patch:
>    ---------------
>    perf record: Get the first sample time and last sample time
> 
> 2. Fix the merge issue with the latest perf/core branch.
>    No functional changes.
> 
>    Impacted patch:
>    ---------------
>    perf report: support time percent and multiple time ranges
>    perf script: support time percent and multiple time ranges
> 
> v5:
> ---
> 1. There is an issue that the sample walking can only work when
>    '--buildid-all' is not enabled. So we need to let the walking
>    be able to work even if '--buildid-all' is enabled and let the
>    processing skips the dso hit marking for this case.
> 
> 2. Check if first/last sample time is recorded in perf data file.
>    If it's not recorded, return error message to user.
> 
> Patched modified in v5:
>    perf record: Get the first sample time and last sample time
>    perf report: support time percent and multiple time ranges
>    perf script: support time percent and multiple time ranges
> 
> v4:
> ---
> 1. Use perf script time style for timestamp printing. Also add with
>    the printing of sample duration. For example:
> 
>    perf report --header
> 
>    time of first sample : 5276531.323099
>    time of last sample : 5276555.345625
>    sample duration :  24022.526 ms
> 
> 2. Fix an invalid time string issue. For example,
> 
>    perf script --time 10%/10x12321xsdfdasfdsafdsafdsa
> 
>    Now in code, it uses strtol to replace atoi.
> 
> 3. Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample
>    in perf report/perf script.
> 
> v3:
> ---
> 1. Move the definitions of first_sample_time/last_sample_time from
>    perf_session and struct record to perf_evlist and update the
>    related code.
> 
> v2:
> ---
> 1. This patch creates a new header feature type HEADER_SAMPLE_TIME and related
>    ops. Save the first sample time and the last sample time to the feature
>    section in perf file header.
> 
> 2. Add checking for last element in time range.
> 
>    For example, select the first and second 10% time slices.
>    perf report --time 10%/1,10%/2
> 
>    Note that now it includes the last element in [10%, 20%] but it
>    doesn't include the last element in [0, 10%). It's to avoid
>    the overlap.
> 
> Following patches are changed:
> 
>    perf header: Record first sample time and last sample time in perf file header
>    perf record: Get the first sample time and last sample time
>    perf util: Create function to perform multiple time range checking
> 
> v1: initial post
> ----------------
> 
> 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 header: Record first sample time and last sample time in perf
>     file header
>   perf record: Get the first sample time and last sample time
>   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-record.txt           |   3 +
>  tools/perf/Documentation/perf-report.txt           |  16 ++
>  tools/perf/Documentation/perf-script.txt           |  16 ++
>  tools/perf/Documentation/perf.data-file-format.txt |   4 +
>  tools/perf/builtin-record.c                        |  18 +-
>  tools/perf/builtin-report.c                        |  31 ++-
>  tools/perf/builtin-script.c                        |  34 ++-
>  tools/perf/util/evlist.h                           |   2 +
>  tools/perf/util/header.c                           |  60 ++++++
>  tools/perf/util/header.h                           |   1 +
>  tools/perf/util/time-utils.c                       | 233 +++++++++++++++++++--
>  tools/perf/util/time-utils.h                       |   6 +
>  12 files changed, 398 insertions(+), 26 deletions(-)
> 
> -- 
> 2.7.4

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

* Re: [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option
  2017-12-13 14:28 ` [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Arnaldo Carvalho de Melo
@ 2017-12-14  0:48   ` Jin, Yao
  0 siblings, 0 replies; 29+ messages in thread
From: Jin, Yao @ 2017-12-14  0:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin



On 12/13/2017 10:28 PM, Arnaldo Carvalho de Melo wrote:
> Em Fri, Dec 08, 2017 at 09:13:40PM +0800, Jin Yao escreveu:
>> v7:
>> ---
>> v7 doesn't have functional change. The update is only:
> 
> Thanks for working on this, will try and get this processed in my next
> round.
> 
> - Arnaldo
>   

Thanks in advance

Thanks
Jin Yao

>> 1. Rebase to latest perf/core branch
>>
>> 2. Update patch description according to Arnaldo's comments.
>>
>> Impacted patch:
>> ---------------
>>    perf header: Record first sample time and last sample time in perf file header
>>    perf record: Get the first sample time and last sample time
>>
>> v6:
>> ---
>> 1. Create a new option "--timestamp-boundary" in perf record.
>>     
>>     Currently '--buildid-all' is not enabled by default. So the walking
>>     on all samples is the default operation. There is no big overhead
>>     to calculate the timestamp boundary in process_sample_event handler
>>     once we already go through all samples. So the timestamp boundary
>>     calculation is enabled by default when '--buildid-all' is not enabled.
>>
>>     While if '--buildid-all' is enabled, we creates a new option
>>     "--timestamp-boundary" for user to decide if it enables the
>>     timestamp boundary calculation.
>>
>>     Impacted patch:
>>     ---------------
>>     perf record: Get the first sample time and last sample time
>>
>> 2. Fix the merge issue with the latest perf/core branch.
>>     No functional changes.
>>
>>     Impacted patch:
>>     ---------------
>>     perf report: support time percent and multiple time ranges
>>     perf script: support time percent and multiple time ranges
>>
>> v5:
>> ---
>> 1. There is an issue that the sample walking can only work when
>>     '--buildid-all' is not enabled. So we need to let the walking
>>     be able to work even if '--buildid-all' is enabled and let the
>>     processing skips the dso hit marking for this case.
>>
>> 2. Check if first/last sample time is recorded in perf data file.
>>     If it's not recorded, return error message to user.
>>
>> Patched modified in v5:
>>     perf record: Get the first sample time and last sample time
>>     perf report: support time percent and multiple time ranges
>>     perf script: support time percent and multiple time ranges
>>
>> v4:
>> ---
>> 1. Use perf script time style for timestamp printing. Also add with
>>     the printing of sample duration. For example:
>>
>>     perf report --header
>>
>>     time of first sample : 5276531.323099
>>     time of last sample : 5276555.345625
>>     sample duration :  24022.526 ms
>>
>> 2. Fix an invalid time string issue. For example,
>>
>>     perf script --time 10%/10x12321xsdfdasfdsafdsafdsa
>>
>>     Now in code, it uses strtol to replace atoi.
>>
>> 3. Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample
>>     in perf report/perf script.
>>
>> v3:
>> ---
>> 1. Move the definitions of first_sample_time/last_sample_time from
>>     perf_session and struct record to perf_evlist and update the
>>     related code.
>>
>> v2:
>> ---
>> 1. This patch creates a new header feature type HEADER_SAMPLE_TIME and related
>>     ops. Save the first sample time and the last sample time to the feature
>>     section in perf file header.
>>
>> 2. Add checking for last element in time range.
>>
>>     For example, select the first and second 10% time slices.
>>     perf report --time 10%/1,10%/2
>>
>>     Note that now it includes the last element in [10%, 20%] but it
>>     doesn't include the last element in [0, 10%). It's to avoid
>>     the overlap.
>>
>> Following patches are changed:
>>
>>     perf header: Record first sample time and last sample time in perf file header
>>     perf record: Get the first sample time and last sample time
>>     perf util: Create function to perform multiple time range checking
>>
>> v1: initial post
>> ----------------
>>
>> 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 header: Record first sample time and last sample time in perf
>>      file header
>>    perf record: Get the first sample time and last sample time
>>    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-record.txt           |   3 +
>>   tools/perf/Documentation/perf-report.txt           |  16 ++
>>   tools/perf/Documentation/perf-script.txt           |  16 ++
>>   tools/perf/Documentation/perf.data-file-format.txt |   4 +
>>   tools/perf/builtin-record.c                        |  18 +-
>>   tools/perf/builtin-report.c                        |  31 ++-
>>   tools/perf/builtin-script.c                        |  34 ++-
>>   tools/perf/util/evlist.h                           |   2 +
>>   tools/perf/util/header.c                           |  60 ++++++
>>   tools/perf/util/header.h                           |   1 +
>>   tools/perf/util/time-utils.c                       | 233 +++++++++++++++++++--
>>   tools/perf/util/time-utils.h                       |   6 +
>>   12 files changed, 398 insertions(+), 26 deletions(-)
>>
>> -- 
>> 2.7.4

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

* Re: [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option
  2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
                   ` (6 preceding siblings ...)
  2017-12-13 14:28 ` [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Arnaldo Carvalho de Melo
@ 2017-12-14 14:08 ` Jiri Olsa
  7 siblings, 0 replies; 29+ messages in thread
From: Jiri Olsa @ 2017-12-14 14:08 UTC (permalink / raw)
  To: Jin Yao
  Cc: acme, jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

On Fri, Dec 08, 2017 at 09:13:40PM +0800, Jin Yao wrote:
> v7:
> ---
> v7 doesn't have functional change. The update is only:
> 
> 1. Rebase to latest perf/core branch
> 
> 2. Update patch description according to Arnaldo's comments.

still looks ok ;-) u can keep the ack

jirka

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

* Re: [PATCH v7 2/6] perf record: Get the first sample time and last sample time
  2017-12-08 13:13 ` [PATCH v7 2/6] perf record: Get the first sample time " Jin Yao
@ 2018-01-04 19:09   ` Arnaldo Carvalho de Melo
  2018-01-05  1:15     ` Jin, Yao
  2018-01-11  6:22   ` [tip:perf/core] perf record: Record the first and last sample time in the header tip-bot for Jin Yao
  1 sibling, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-04 19:09 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Fri, Dec 08, 2017 at 09:13:42PM +0800, Jin Yao escreveu:
> In the default 'perf record' configuration, all samples are processed,
> to create the HEADER_BUILD_ID table. So it's very easy to get the
> first/last samples and save the time to perf file header via the
> function write_sample_time().
> 
> Later, at post processing time, perf report/script will fetch
> the time from perf file header.

So, at this point I was expecting that that record would be present on
the perf.data file:

[acme@jouet perf]$ perf record --timestamp-boundary sleep 1
Cannot read kernel map
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.001 MB perf.data (7 samples) ]
[acme@jouet perf]$ perf report -D | grep PERF_RECORD_SAMPLE | wc -l
7
[acme@jouet perf]$ perf report -D | grep PERF_RECORD_SAMPLE_TIME
[acme@jouet perf]$

What am I doing wrong?

To clarify, this is with just the first two patches in this series
applied.

- Arnaldo
 
> Change log:
> -----------
> v7: Just update the patch description according to Arnaldo's suggestion.
> 
> v6: Currently '--buildid-all' is not enabled at default. So the walking
>     on all samples is the default operation. There is no big overhead
>     to calculate the timestamp boundary in process_sample_event handler
>     once we already go through all samples. So the timestamp boundary
>     calculation is enabled by default when '--buildid-all' is not enabled.
> 
>     While if '--buildid-all' is enabled, we creates a new option
>     "--timestamp-boundary" for user to decide if it enables the
>     timestamp boundary calculation.
> 
> v5: There is an issue that the sample walking can only work when
>     '--buildid-all' is not enabled. So we need to let the walking
>     be able to work even if '--buildid-all' is enabled and let the
>     processing skips the dso hit marking for this case.
> 
>     At first, I want to provide a new option "--record-time-boundaries".
>     While after consideration, I think a new option is not very
>     necessary.
> 
> v3: Remove the definitions of first_sample_time and last_sample_time
>     from struct record and directly save them in perf_evlist.
> 
> Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
> ---
>  tools/perf/Documentation/perf-record.txt |  3 +++
>  tools/perf/builtin-record.c              | 18 +++++++++++++++---
>  2 files changed, 18 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
> index 5a626ef..3eea6de 100644
> --- a/tools/perf/Documentation/perf-record.txt
> +++ b/tools/perf/Documentation/perf-record.txt
> @@ -430,6 +430,9 @@ Configure all used events to run in user space.
>  --timestamp-filename
>  Append timestamp to output file name.
>  
> +--timestamp-boundary::
> +Record timestamp boundary (time of first/last samples).
> +
>  --switch-output[=mode]::
>  Generate multiple perf.data files, timestamp prefixed, switching to a new one
>  based on 'mode' value:
> diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
> index 98da8cb..6db7b5a 100644
> --- a/tools/perf/builtin-record.c
> +++ b/tools/perf/builtin-record.c
> @@ -78,6 +78,7 @@ struct record {
>  	bool			no_buildid_cache_set;
>  	bool			buildid_all;
>  	bool			timestamp_filename;
> +	bool			timestamp_boundary;
>  	struct switch_output	switch_output;
>  	unsigned long long	samples;
>  };
> @@ -409,8 +410,15 @@ static int process_sample_event(struct perf_tool *tool,
>  {
>  	struct record *rec = container_of(tool, struct record, tool);
>  
> -	rec->samples++;
> +	if (rec->evlist->first_sample_time == 0)
> +		rec->evlist->first_sample_time = sample->time;
> +
> +	rec->evlist->last_sample_time = sample->time;
>  
> +	if (rec->buildid_all)
> +		return 0;
> +
> +	rec->samples++;
>  	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
>  }
>  
> @@ -435,9 +443,11 @@ static int process_buildids(struct record *rec)
>  
>  	/*
>  	 * If --buildid-all is given, it marks all DSO regardless of hits,
> -	 * so no need to process samples.
> +	 * so no need to process samples. But if timestamp_boundary is enabled,
> +	 * it still needs to walk on all samples to get the timestamps of
> +	 * first/last samples.
>  	 */
> -	if (rec->buildid_all)
> +	if (rec->buildid_all && !rec->timestamp_boundary)
>  		rec->tool.sample = NULL;
>  
>  	return perf_session__process_events(session);
> @@ -1621,6 +1631,8 @@ static struct option __record_options[] = {
>  		    "Record build-id of all DSOs regardless of hits"),
>  	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
>  		    "append timestamp to output filename"),
> +	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
> +		    "Record timestamp boundary (time of first/last samples)"),
>  	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
>  			  &record.switch_output.set, "signal,size,time",
>  			  "Switch output when receive SIGUSR2 or cross size,time threshold",
> -- 
> 2.7.4

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

* Re: [PATCH v7 2/6] perf record: Get the first sample time and last sample time
  2018-01-04 19:09   ` Arnaldo Carvalho de Melo
@ 2018-01-05  1:15     ` Jin, Yao
  2018-01-05 12:53       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 29+ messages in thread
From: Jin, Yao @ 2018-01-05  1:15 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin



On 1/5/2018 3:09 AM, Arnaldo Carvalho de Melo wrote:
> Em Fri, Dec 08, 2017 at 09:13:42PM +0800, Jin Yao escreveu:
>> In the default 'perf record' configuration, all samples are processed,
>> to create the HEADER_BUILD_ID table. So it's very easy to get the
>> first/last samples and save the time to perf file header via the
>> function write_sample_time().
>>
>> Later, at post processing time, perf report/script will fetch
>> the time from perf file header.
> 
> So, at this point I was expecting that that record would be present on
> the perf.data file:
> 
> [acme@jouet perf]$ perf record --timestamp-boundary sleep 1
> Cannot read kernel map
> [ perf record: Woken up 1 times to write data ]
> [ perf record: Captured and wrote 0.001 MB perf.data (7 samples) ]
> [acme@jouet perf]$ perf report -D | grep PERF_RECORD_SAMPLE | wc -l
> 7
> [acme@jouet perf]$ perf report -D | grep PERF_RECORD_SAMPLE_TIME
> [acme@jouet perf]$
> 
> What am I doing wrong?
> 
> To clarify, this is with just the first two patches in this series
> applied.
> 
> - Arnaldo
>   

Hi Arnaldo,

The timestamp boundary information is saved in perf file header.

So if we want to look at them, we need to add '--header' in perf report.

For example,

root@skl:/tmp# perf report -D --header | grep 'time of'
# time of first sample : 248333.706656
# time of last sample : 248357.215328

Thanks
Jin Yao

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

* Re: [PATCH v7 2/6] perf record: Get the first sample time and last sample time
  2018-01-05  1:15     ` Jin, Yao
@ 2018-01-05 12:53       ` Arnaldo Carvalho de Melo
  2018-01-05 22:55         ` Jin, Yao
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-05 12:53 UTC (permalink / raw)
  To: Jin, Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Fri, Jan 05, 2018 at 09:15:03AM +0800, Jin, Yao escreveu:
> 
> 
> On 1/5/2018 3:09 AM, Arnaldo Carvalho de Melo wrote:
> > Em Fri, Dec 08, 2017 at 09:13:42PM +0800, Jin Yao escreveu:
> > > In the default 'perf record' configuration, all samples are processed,
> > > to create the HEADER_BUILD_ID table. So it's very easy to get the
> > > first/last samples and save the time to perf file header via the
> > > function write_sample_time().
> > > 
> > > Later, at post processing time, perf report/script will fetch
> > > the time from perf file header.
> > 
> > So, at this point I was expecting that that record would be present on
> > the perf.data file:
> > 
> > [acme@jouet perf]$ perf record --timestamp-boundary sleep 1
> > Cannot read kernel map
> > [ perf record: Woken up 1 times to write data ]
> > [ perf record: Captured and wrote 0.001 MB perf.data (7 samples) ]
> > [acme@jouet perf]$ perf report -D | grep PERF_RECORD_SAMPLE | wc -l
> > 7
> > [acme@jouet perf]$ perf report -D | grep PERF_RECORD_SAMPLE_TIME
> > [acme@jouet perf]$
> > 
> > What am I doing wrong?
> > 
> > To clarify, this is with just the first two patches in this series
> > applied.
> > 
> > - Arnaldo
> 
> Hi Arnaldo,
> 
> The timestamp boundary information is saved in perf file header.

Right, my bad, I somehow thought it would be as PERF_RECORD_SAMPLE_TIME,
duh.

Will continue reviewing, sorry about that.

- Arnaldo
 
> So if we want to look at them, we need to add '--header' in perf report.
> 
> For example,
> 
> root@skl:/tmp# perf report -D --header | grep 'time of'
> # time of first sample : 248333.706656
> # time of last sample : 248357.215328
> 
> Thanks
> Jin Yao

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

* Re: [PATCH v7 2/6] perf record: Get the first sample time and last sample time
  2018-01-05 12:53       ` Arnaldo Carvalho de Melo
@ 2018-01-05 22:55         ` Jin, Yao
  0 siblings, 0 replies; 29+ messages in thread
From: Jin, Yao @ 2018-01-05 22:55 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin



On 1/5/2018 8:53 PM, Arnaldo Carvalho de Melo wrote:
> Em Fri, Jan 05, 2018 at 09:15:03AM +0800, Jin, Yao escreveu:
>>
>>
>> On 1/5/2018 3:09 AM, Arnaldo Carvalho de Melo wrote:
>>> Em Fri, Dec 08, 2017 at 09:13:42PM +0800, Jin Yao escreveu:
>>>> In the default 'perf record' configuration, all samples are processed,
>>>> to create the HEADER_BUILD_ID table. So it's very easy to get the
>>>> first/last samples and save the time to perf file header via the
>>>> function write_sample_time().
>>>>
>>>> Later, at post processing time, perf report/script will fetch
>>>> the time from perf file header.
>>>
>>> So, at this point I was expecting that that record would be present on
>>> the perf.data file:
>>>
>>> [acme@jouet perf]$ perf record --timestamp-boundary sleep 1
>>> Cannot read kernel map
>>> [ perf record: Woken up 1 times to write data ]
>>> [ perf record: Captured and wrote 0.001 MB perf.data (7 samples) ]
>>> [acme@jouet perf]$ perf report -D | grep PERF_RECORD_SAMPLE | wc -l
>>> 7
>>> [acme@jouet perf]$ perf report -D | grep PERF_RECORD_SAMPLE_TIME
>>> [acme@jouet perf]$
>>>
>>> What am I doing wrong?
>>>
>>> To clarify, this is with just the first two patches in this series
>>> applied.
>>>
>>> - Arnaldo
>>
>> Hi Arnaldo,
>>
>> The timestamp boundary information is saved in perf file header.
> 
> Right, my bad, I somehow thought it would be as PERF_RECORD_SAMPLE_TIME,
> duh.
> 
> Will continue reviewing, sorry about that.
> 
> - Arnaldo
>   

Thanks for reviewing the patch.

If you see anything I should improve, please let me know.

Thanks
Jin Yao

>> So if we want to look at them, we need to add '--header' in perf report.
>>
>> For example,
>>
>> root@skl:/tmp# perf report -D --header | grep 'time of'
>> # time of first sample : 248333.706656
>> # time of last sample : 248357.215328
>>
>> Thanks
>> Jin Yao

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

* Re: [PATCH v7 3/6] perf util: Create function to parse time percent
  2017-12-08 13:13 ` [PATCH v7 3/6] perf util: Create function to parse time percent Jin Yao
@ 2018-01-08 14:31   ` Arnaldo Carvalho de Melo
  2018-01-08 14:38     ` Arnaldo Carvalho de Melo
  2018-01-11  6:22   ` [tip:perf/core] perf tools: " tip-bot for Jin Yao
  1 sibling, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-08 14:31 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Fri, Dec 08, 2017 at 09:13:43PM +0800, Jin Yao escreveu:
> 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

After applying this patch I'm not being able to get any of these
examples to work:

[root@jouet home]# perf report --header | grep "time of"
# time of first sample : 22947.909226
# time of last sample : 22948.910704
[root@jouet home]# 

Then, when I try the first example:

[root@jouet home]# perf report --stdio --time 1%-20%
Invalid time string
# To display the perf.data header info, please use --header/--header-only options.
#
[root@jouet home]#

What am I doing wrong?
 
> 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%
> 
> Change log:
> -----------
> v4: An issue is found. Following passes.
>     perf script --time 10%/10x12321xsdfdasfdsafdsafdsa
> 
>     Now it uses strtol to replace atoi.
> 
> Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
> ---
>  tools/perf/util/time-utils.c | 205 ++++++++++++++++++++++++++++++++++++++++---
>  tools/perf/util/time-utils.h |   3 +
>  2 files changed, 196 insertions(+), 12 deletions(-)
> 
> diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
> index 81927d0..61c46022 100644
> --- a/tools/perf/util/time-utils.c
> +++ b/tools/perf/util/time-utils.c
> @@ -6,6 +6,7 @@
>  #include <time.h>
>  #include <errno.h>
>  #include <inttypes.h>
> +#include <math.h>
>  
>  #include "perf.h"
>  #include "debug.h"
> @@ -60,11 +61,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;
> @@ -74,25 +74,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)
> @@ -104,6 +114,177 @@ 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, *end_str;
> +	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 = (int)strtol(p, &end_str, 10);
> +	if (*end_str)
> +		return -1;
> +
> +	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 15b475c..2308723 100644
> --- a/tools/perf/util/time-utils.h
> +++ b/tools/perf/util/time-utils.h
> @@ -13,6 +13,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	[flat|nested] 29+ messages in thread

* Re: [PATCH v7 3/6] perf util: Create function to parse time percent
  2018-01-08 14:31   ` Arnaldo Carvalho de Melo
@ 2018-01-08 14:38     ` Arnaldo Carvalho de Melo
  2018-01-09  1:18       ` Jin, Yao
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-08 14:38 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Mon, Jan 08, 2018 at 11:31:49AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Fri, Dec 08, 2017 at 09:13:43PM +0800, Jin Yao escreveu:
> > 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
> 
> After applying this patch I'm not being able to get any of these
> examples to work:
> 
> [root@jouet home]# perf report --header | grep "time of"
> # time of first sample : 22947.909226
> # time of last sample : 22948.910704
> [root@jouet home]# 
> 
> Then, when I try the first example:
> 
> [root@jouet home]# perf report --stdio --time 1%-20%
> Invalid time string
> # To display the perf.data header info, please use --header/--header-only options.
> #
> [root@jouet home]#
> 
> What am I doing wrong?

Oh well, the way you worded this cset it looked like after applying it I
would be able to use percents, etc, which is not the case, I'll probably
need to apply the next patches to _then_ this work as advertised in this
cset comment.

Please try to make it clear in the commit messages these details, to
ease reviewing.

- Arnaldo

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

* Re: [PATCH v7 5/6] perf report: support time percent and multiple time ranges
  2017-12-08 13:13 ` [PATCH v7 5/6] perf report: support time percent and multiple time ranges Jin Yao
@ 2018-01-08 14:45   ` Arnaldo Carvalho de Melo
  2018-01-08 14:48     ` Arnaldo Carvalho de Melo
  2018-01-08 14:53   ` Arnaldo Carvalho de Melo
  2018-01-11  6:23   ` [tip:perf/core] perf report: Support " tip-bot for Jin Yao
  2 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-08 14:45 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Fri, Dec 08, 2017 at 09:13:45PM +0800, Jin Yao escreveu:
> 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.

So you're doing two things here, and the error message should be
improved, telling the user what is to be done to be able to use
something it is asking for.

I'm trying to split it here...

- Arnaldo
 
> 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%
> 
> Change log:
> -----------
> v6: Fix the merge issue with latest perf/core branch.
>     No functional changes.
> 
> v5: Add checking of first/last sample time to detect if it's recorded
>     in perf.data. If it's not recorded, returns error message to user.
> 
> v4: Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample
> 
> v3: Since the definitions of first_sample_time/last_sample_time
>     are moved from perf_session to perf_evlist so change the
>     related code.
> 
> Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
> ---
>  tools/perf/Documentation/perf-report.txt | 16 ++++++++++++++++
>  tools/perf/builtin-report.c              | 31 ++++++++++++++++++++++++++-----
>  2 files changed, 42 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
> index ddde2b5..ed36553 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 eb9ce63..946f146 100644
> --- a/tools/perf/builtin-report.c
> +++ b/tools/perf/builtin-report.c
> @@ -52,6 +52,8 @@
>  #include <sys/stat.h>
>  #include <unistd.h>
>  
> +#define PTIME_RANGE_MAX	10
> +
>  struct report {
>  	struct perf_tool	tool;
>  	struct perf_session	*session;
> @@ -69,7 +71,8 @@ struct report {
>  	const char		*cpu_list;
>  	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;
> @@ -186,8 +189,10 @@ static int process_sample_event(struct perf_tool *tool,
>  	};
>  	int ret = 0;
>  
> -	if (perf_time__skip_sample(&rep->ptime, sample->time))
> +	if (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",
> @@ -1077,9 +1082,25 @@ int cmd_report(int argc, const char **argv)
>  	if (symbol__init(&session->header.env) < 0)
>  		goto error;
>  
> -	if (perf_time__parse_str(&report.ptime, report.time_str) != 0) {
> -		pr_err("Invalid time string\n");
> -		return -EINVAL;
> +	if (perf_time__parse_str(report.ptime_range, report.time_str) != 0) {
> +		if (session->evlist->first_sample_time == 0 &&
> +		    session->evlist->last_sample_time == 0) {
> +			pr_err("No first/last sample time in perf data\n");
> +			return -EINVAL;
> +		}
> +
> +		report.range_num = perf_time__percent_parse_str(
> +					report.ptime_range, PTIME_RANGE_MAX,
> +					report.time_str,
> +					session->evlist->first_sample_time,
> +					session->evlist->last_sample_time);
> +
> +		if (report.range_num < 0) {
> +			pr_err("Invalid time string\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		report.range_num = 1;
>  	}
>  
>  	sort__setup_elide(stdout);
> -- 
> 2.7.4

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

* Re: [PATCH v7 5/6] perf report: support time percent and multiple time ranges
  2018-01-08 14:45   ` Arnaldo Carvalho de Melo
@ 2018-01-08 14:48     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-08 14:48 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Mon, Jan 08, 2018 at 11:45:06AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Fri, Dec 08, 2017 at 09:13:45PM +0800, Jin Yao escreveu:
> > 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.
> 
> So you're doing two things here, and the error message should be
> improved, telling the user what is to be done to be able to use
> something it is asking for.
> 
> I'm trying to split it here...

Nah, I'll leave it as is, but please try to add just one feature per
patch, this way the reviewer can make progress by picking patches he/she
agrees should be merged while leaving parts to be further developed.

Please consider sending a follow up patch improving the error message, I
mean this part:

+	if (perf_time__parse_str(report.ptime_range, report.time_str) != 0) {
+		if (session->evlist->first_sample_time == 0 &&
+		    session->evlist->last_sample_time == 0) {
+			pr_err("No first/last sample time in perf data\n");
+			return -EINVAL;
+		}

Add something like:

"HINT: use 'perf record --foobar' to record the first/last sample
timestamps in the perf.data file header or enable build-id processing."

> - Arnaldo
>  
> > 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%
> > 
> > Change log:
> > -----------
> > v6: Fix the merge issue with latest perf/core branch.
> >     No functional changes.
> > 
> > v5: Add checking of first/last sample time to detect if it's recorded
> >     in perf.data. If it's not recorded, returns error message to user.
> > 
> > v4: Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample
> > 
> > v3: Since the definitions of first_sample_time/last_sample_time
> >     are moved from perf_session to perf_evlist so change the
> >     related code.
> > 
> > Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
> > ---
> >  tools/perf/Documentation/perf-report.txt | 16 ++++++++++++++++
> >  tools/perf/builtin-report.c              | 31 ++++++++++++++++++++++++++-----
> >  2 files changed, 42 insertions(+), 5 deletions(-)
> > 
> > diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
> > index ddde2b5..ed36553 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 eb9ce63..946f146 100644
> > --- a/tools/perf/builtin-report.c
> > +++ b/tools/perf/builtin-report.c
> > @@ -52,6 +52,8 @@
> >  #include <sys/stat.h>
> >  #include <unistd.h>
> >  
> > +#define PTIME_RANGE_MAX	10
> > +
> >  struct report {
> >  	struct perf_tool	tool;
> >  	struct perf_session	*session;
> > @@ -69,7 +71,8 @@ struct report {
> >  	const char		*cpu_list;
> >  	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;
> > @@ -186,8 +189,10 @@ static int process_sample_event(struct perf_tool *tool,
> >  	};
> >  	int ret = 0;
> >  
> > -	if (perf_time__skip_sample(&rep->ptime, sample->time))
> > +	if (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",
> > @@ -1077,9 +1082,25 @@ int cmd_report(int argc, const char **argv)
> >  	if (symbol__init(&session->header.env) < 0)
> >  		goto error;
> >  
> > -	if (perf_time__parse_str(&report.ptime, report.time_str) != 0) {
> > -		pr_err("Invalid time string\n");
> > -		return -EINVAL;
> > +	if (perf_time__parse_str(report.ptime_range, report.time_str) != 0) {
> > +		if (session->evlist->first_sample_time == 0 &&
> > +		    session->evlist->last_sample_time == 0) {
> > +			pr_err("No first/last sample time in perf data\n");
> > +			return -EINVAL;
> > +		}
> > +
> > +		report.range_num = perf_time__percent_parse_str(
> > +					report.ptime_range, PTIME_RANGE_MAX,
> > +					report.time_str,
> > +					session->evlist->first_sample_time,
> > +					session->evlist->last_sample_time);
> > +
> > +		if (report.range_num < 0) {
> > +			pr_err("Invalid time string\n");
> > +			return -EINVAL;
> > +		}
> > +	} else {
> > +		report.range_num = 1;
> >  	}
> >  
> >  	sort__setup_elide(stdout);
> > -- 
> > 2.7.4

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

* Re: [PATCH v7 5/6] perf report: support time percent and multiple time ranges
  2017-12-08 13:13 ` [PATCH v7 5/6] perf report: support time percent and multiple time ranges Jin Yao
  2018-01-08 14:45   ` Arnaldo Carvalho de Melo
@ 2018-01-08 14:53   ` Arnaldo Carvalho de Melo
  2018-01-08 15:02     ` Arnaldo Carvalho de Melo
  2018-01-11  6:23   ` [tip:perf/core] perf report: Support " tip-bot for Jin Yao
  2 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-08 14:53 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Fri, Dec 08, 2017 at 09:13:45PM +0800, Jin Yao escreveu:
> 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%
> 
> Change log:
> -----------
> v6: Fix the merge issue with latest perf/core branch.
>     No functional changes.
> 
> v5: Add checking of first/last sample time to detect if it's recorded
>     in perf.data. If it's not recorded, returns error message to user.
> 
> v4: Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample
> 
> v3: Since the definitions of first_sample_time/last_sample_time
>     are moved from perf_session to perf_evlist so change the
>     related code.
> 
> Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
> ---
>  tools/perf/Documentation/perf-report.txt | 16 ++++++++++++++++
>  tools/perf/builtin-report.c              | 31 ++++++++++++++++++++++++++-----
>  2 files changed, 42 insertions(+), 5 deletions(-)
> 
> diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
> index ddde2b5..ed36553 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.

Also please run a spell checker, at least for documentation, it would
catch that "multipe" typo :-)

And we should avoid these magic numbers, why 10 is a good number, maybe
5? The best thing would be to have no such limitations. Please consider
this for some followup patch, i.e. to lift this limitation from the code
and docs.

> +
> +	For example:

You missed the ':' at the end of the example summaries, I'm adding them:

Select the second 10% time slice:

> +	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 eb9ce63..946f146 100644
> --- a/tools/perf/builtin-report.c
> +++ b/tools/perf/builtin-report.c
> @@ -52,6 +52,8 @@
>  #include <sys/stat.h>
>  #include <unistd.h>
>  
> +#define PTIME_RANGE_MAX	10
> +
>  struct report {
>  	struct perf_tool	tool;
>  	struct perf_session	*session;
> @@ -69,7 +71,8 @@ struct report {
>  	const char		*cpu_list;
>  	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;
> @@ -186,8 +189,10 @@ static int process_sample_event(struct perf_tool *tool,
>  	};
>  	int ret = 0;
>  
> -	if (perf_time__skip_sample(&rep->ptime, sample->time))
> +	if (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",
> @@ -1077,9 +1082,25 @@ int cmd_report(int argc, const char **argv)
>  	if (symbol__init(&session->header.env) < 0)
>  		goto error;
>  
> -	if (perf_time__parse_str(&report.ptime, report.time_str) != 0) {
> -		pr_err("Invalid time string\n");
> -		return -EINVAL;
> +	if (perf_time__parse_str(report.ptime_range, report.time_str) != 0) {
> +		if (session->evlist->first_sample_time == 0 &&
> +		    session->evlist->last_sample_time == 0) {
> +			pr_err("No first/last sample time in perf data\n");
> +			return -EINVAL;
> +		}
> +
> +		report.range_num = perf_time__percent_parse_str(
> +					report.ptime_range, PTIME_RANGE_MAX,
> +					report.time_str,
> +					session->evlist->first_sample_time,
> +					session->evlist->last_sample_time);
> +
> +		if (report.range_num < 0) {
> +			pr_err("Invalid time string\n");
> +			return -EINVAL;
> +		}
> +	} else {
> +		report.range_num = 1;
>  	}
>  
>  	sort__setup_elide(stdout);
> -- 
> 2.7.4

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

* Re: [PATCH v7 5/6] perf report: support time percent and multiple time ranges
  2018-01-08 14:53   ` Arnaldo Carvalho de Melo
@ 2018-01-08 15:02     ` Arnaldo Carvalho de Melo
  2018-01-08 15:04       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-08 15:02 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

Em Mon, Jan 08, 2018 at 11:53:36AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Fri, Dec 08, 2017 at 09:13:45PM +0800, Jin Yao escreveu:
> > 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%

So now it works, but we need to improve the error messages, i.e. if one
does:

   perf report --time 10%

should this be equivalent to:

   perf report --time 10%/1

?

Or at least say something like:

   "percent slices need an index to specify which one is wanted"

when you notice a % in the --time string, etc.

Consider these for follow up patches.

- Arnaldo

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

* Re: [PATCH v7 5/6] perf report: support time percent and multiple time ranges
  2018-01-08 15:02     ` Arnaldo Carvalho de Melo
@ 2018-01-08 15:04       ` Arnaldo Carvalho de Melo
  2018-01-09  2:02         ` Jin, Yao
  0 siblings, 1 reply; 29+ messages in thread
From: Arnaldo Carvalho de Melo @ 2018-01-08 15:04 UTC (permalink / raw)
  To: Jin Yao
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin

One more thing to consider:

When you use:

   perf report --time 10%/1

it will do what is asked but there is no indication of what percentage
ranges are in place, it would be nice to have this in the first line in
the TUI, right after this:

Samples: 128  of event 'cycles:ppp', Event count (approx.): 21386169 (10%/1)

- Arnaldo

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

* Re: [PATCH v7 3/6] perf util: Create function to parse time percent
  2018-01-08 14:38     ` Arnaldo Carvalho de Melo
@ 2018-01-09  1:18       ` Jin, Yao
  0 siblings, 0 replies; 29+ messages in thread
From: Jin, Yao @ 2018-01-09  1:18 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin



On 1/8/2018 10:38 PM, Arnaldo Carvalho de Melo wrote:
> Em Mon, Jan 08, 2018 at 11:31:49AM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Fri, Dec 08, 2017 at 09:13:43PM +0800, Jin Yao escreveu:
>>> 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
>>
>> After applying this patch I'm not being able to get any of these
>> examples to work:
>>
>> [root@jouet home]# perf report --header | grep "time of"
>> # time of first sample : 22947.909226
>> # time of last sample : 22948.910704
>> [root@jouet home]#
>>
>> Then, when I try the first example:
>>
>> [root@jouet home]# perf report --stdio --time 1%-20%
>> Invalid time string
>> # To display the perf.data header info, please use --header/--header-only options.
>> #
>> [root@jouet home]#
>>
>> What am I doing wrong?
> 
> Oh well, the way you worded this cset it looked like after applying it I
> would be able to use percents, etc, which is not the case, I'll probably
> need to apply the next patches to _then_ this work as advertised in this
> cset comment.
> 
> Please try to make it clear in the commit messages these details, to
> ease reviewing.
> 
> - Arnaldo
> 

Hi Arnaldo,

Sorry about that.

I will take care next time to try my best to make the patch description 
more clear.

Thanks
Jin Yao

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

* Re: [PATCH v7 5/6] perf report: support time percent and multiple time ranges
  2018-01-08 15:04       ` Arnaldo Carvalho de Melo
@ 2018-01-09  2:02         ` Jin, Yao
  0 siblings, 0 replies; 29+ messages in thread
From: Jin, Yao @ 2018-01-09  2:02 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: jolsa, peterz, mingo, alexander.shishkin, Linux-kernel, ak,
	kan.liang, yao.jin



On 1/8/2018 11:04 PM, Arnaldo Carvalho de Melo wrote:
> One more thing to consider:
> 
> When you use:
> 
>     perf report --time 10%/1
> 
> it will do what is asked but there is no indication of what percentage
> ranges are in place, it would be nice to have this in the first line in
> the TUI, right after this:
> 
> Samples: 128  of event 'cycles:ppp', Event count (approx.): 21386169 (10%/1)
> 
> - Arnaldo
> 

Hi Arnaldo,

Thanks for merging this feature and thanks so much for providing 
comments for how to improve this feature in next step.

Please let me summarize what the follow-up patch needs to do:

1. Improve the error message, something like:
"HINT: use 'perf record --foobar' to record the first/last sample 
timestamps in the perf.data file header or enable build-id processing."

2. Currently it uses magic number 10 to limit the number of time slices. 
But it's not good. The best thing would be to have no such limitations, 
i.e. to lift this limitation from the code and docs.

3. 'perf report --time 10%' should be equivalent to 'perf report --time 
10%/1'. Or at least say something like:

    "percent slices need an index to specify which one is wanted" when 
you notice a % in the --time string, etc.

4. Add an indication of what percentage ranges are being used. For example,

Samples: 128  of event 'cycles:ppp', Event count (approx.): 21386169 (10%/1)

I will develop a follow-up patchset to improve this feature.

Thanks
Jin Yao

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

* [tip:perf/core] perf header: Add infrastructure to record first and last sample time
  2017-12-08 13:13 ` [PATCH v7 1/6] perf header: Record first sample time and last sample time in perf file header Jin Yao
@ 2018-01-11  6:21   ` tip-bot for Jin Yao
  0 siblings, 0 replies; 29+ messages in thread
From: tip-bot for Jin Yao @ 2018-01-11  6:21 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: yao.jin, jolsa, kan.liang, mingo, peterz, alexander.shishkin,
	linux-kernel, tglx, ak, acme, hpa

Commit-ID:  6011518db3bd04c80cd3ce3e6aea1c399739adb4
Gitweb:     https://git.kernel.org/tip/6011518db3bd04c80cd3ce3e6aea1c399739adb4
Author:     Jin Yao <yao.jin@linux.intel.com>
AuthorDate: Fri, 8 Dec 2017 21:13:41 +0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Jan 2018 11:20:51 -0300

perf header: Add infrastructure to record first and last sample time

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.

This patch creates a new header feature type HEADER_SAMPLE_TIME and
related ops. Save the first sample time and the last sample time to the
feature section in perf file header. That will be done when, for
instance, processing build-ids, where we already have to process all
samples to create the build-id table, take advantage of that to further
amortize that processing by storing HEADER_SAMPLE_TIME to make 'perf
report/script' faster when using --time.

Committer testing:

After this patch is applied the header is written with zeroes, we need
the next patch, for "perf record" to actually write the timestamps:

  # perf report -D | grep PERF_RECORD_SAMPLE\(
  22501155244406 0x44f0 [0x28]: PERF_RECORD_SAMPLE(IP, 0x4001): 25016/25016: 0xffffffffa21be8c5 period: 1 addr: 0
  <SNIP>
  22501155793625 0x4a30 [0x28]: PERF_RECORD_SAMPLE(IP, 0x4001): 25016/25016: 0xffffffffa21ffd50 period: 2828043 addr: 0
  # perf report --header | grep "time of "
  # time of first sample : 0.000000
  # time of last sample : 0.000000
  #

Changelog:

v7: 1. Rebase to latest perf/core branch.

    2. Add following clarification in patch description according to
       Arnaldo's suggestion.

       "That will be done when, for instance, processing build-ids,
	where we already have to process all samples to create the
	build-id table, take advantage of that to further amortize
	that processing by storing HEADER_SAMPLE_TIME to make
	'perf report/script' faster when using --time."

v4: Use perf script time style for timestamp printing. Also add with
    the printing of sample duration.

v3: Remove the definitions of first_sample_time/last_sample_time from
    perf_session. Just define them in perf_evlist

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1512738826-2628-2-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf.data-file-format.txt |  4 ++
 tools/perf/util/evlist.h                           |  2 +
 tools/perf/util/header.c                           | 60 ++++++++++++++++++++++
 tools/perf/util/header.h                           |  1 +
 4 files changed, 67 insertions(+)

diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index 15e8b48..f7d85e8 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -261,6 +261,10 @@ struct {
 	struct perf_header_string map;
 }[number_of_cache_levels];
 
+	HEADER_SAMPLE_TIME = 21,
+
+Two uint64_t for the time of first sample and the time of last sample.
+
 	other bits are reserved and should ignored for now
 	HEADER_FEAT_BITS	= 256,
 
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 7516066..e7fbca6 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -50,6 +50,8 @@ struct perf_evlist {
 	struct perf_evsel *selected;
 	struct events_stats stats;
 	struct perf_env	*env;
+	u64		first_sample_time;
+	u64		last_sample_time;
 };
 
 struct perf_evsel_str_handler {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ca73aa7..a326e0d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -16,6 +16,7 @@
 #include <linux/stringify.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
+#include <linux/time64.h>
 
 #include "evlist.h"
 #include "evsel.h"
@@ -35,6 +36,7 @@
 #include <api/fs/fs.h>
 #include "asm/bug.h"
 #include "tool.h"
+#include "time-utils.h"
 
 #include "sane_ctype.h"
 
@@ -1180,6 +1182,20 @@ static int write_stat(struct feat_fd *ff __maybe_unused,
 	return 0;
 }
 
+static int write_sample_time(struct feat_fd *ff,
+			     struct perf_evlist *evlist)
+{
+	int ret;
+
+	ret = do_write(ff, &evlist->first_sample_time,
+		       sizeof(evlist->first_sample_time));
+	if (ret < 0)
+		return ret;
+
+	return do_write(ff, &evlist->last_sample_time,
+			sizeof(evlist->last_sample_time));
+}
+
 static void print_hostname(struct feat_fd *ff, FILE *fp)
 {
 	fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
@@ -1505,6 +1521,28 @@ static void print_group_desc(struct feat_fd *ff, FILE *fp)
 	}
 }
 
+static void print_sample_time(struct feat_fd *ff, FILE *fp)
+{
+	struct perf_session *session;
+	char time_buf[32];
+	double d;
+
+	session = container_of(ff->ph, struct perf_session, header);
+
+	timestamp__scnprintf_usec(session->evlist->first_sample_time,
+				  time_buf, sizeof(time_buf));
+	fprintf(fp, "# time of first sample : %s\n", time_buf);
+
+	timestamp__scnprintf_usec(session->evlist->last_sample_time,
+				  time_buf, sizeof(time_buf));
+	fprintf(fp, "# time of last sample : %s\n", time_buf);
+
+	d = (double)(session->evlist->last_sample_time -
+		session->evlist->first_sample_time) / NSEC_PER_MSEC;
+
+	fprintf(fp, "# sample duration : %10.3f ms\n", d);
+}
+
 static int __event_process_build_id(struct build_id_event *bev,
 				    char *filename,
 				    struct perf_session *session)
@@ -2146,6 +2184,27 @@ out_free_caches:
 	return -1;
 }
 
+static int process_sample_time(struct feat_fd *ff, void *data __maybe_unused)
+{
+	struct perf_session *session;
+	u64 first_sample_time, last_sample_time;
+	int ret;
+
+	session = container_of(ff->ph, struct perf_session, header);
+
+	ret = do_read_u64(ff, &first_sample_time);
+	if (ret)
+		return -1;
+
+	ret = do_read_u64(ff, &last_sample_time);
+	if (ret)
+		return -1;
+
+	session->evlist->first_sample_time = first_sample_time;
+	session->evlist->last_sample_time = last_sample_time;
+	return 0;
+}
+
 struct feature_ops {
 	int (*write)(struct feat_fd *ff, struct perf_evlist *evlist);
 	void (*print)(struct feat_fd *ff, FILE *fp);
@@ -2203,6 +2262,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
 	FEAT_OPN(AUXTRACE,	auxtrace,	false),
 	FEAT_OPN(STAT,		stat,		false),
 	FEAT_OPN(CACHE,		cache,		true),
+	FEAT_OPR(SAMPLE_TIME,	sample_time,	false),
 };
 
 struct header_print_data {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 317fb90..f28aaaa 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -35,6 +35,7 @@ enum {
 	HEADER_AUXTRACE,
 	HEADER_STAT,
 	HEADER_CACHE,
+	HEADER_SAMPLE_TIME,
 	HEADER_LAST_FEATURE,
 	HEADER_FEAT_BITS	= 256,
 };

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

* [tip:perf/core] perf record: Record the first and last sample time in the header
  2017-12-08 13:13 ` [PATCH v7 2/6] perf record: Get the first sample time " Jin Yao
  2018-01-04 19:09   ` Arnaldo Carvalho de Melo
@ 2018-01-11  6:22   ` tip-bot for Jin Yao
  1 sibling, 0 replies; 29+ messages in thread
From: tip-bot for Jin Yao @ 2018-01-11  6:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, hpa, mingo, kan.liang, yao.jin, tglx, peterz,
	jolsa, alexander.shishkin, ak, acme

Commit-ID:  68588baf8d01826673f2874f434123029e519052
Gitweb:     https://git.kernel.org/tip/68588baf8d01826673f2874f434123029e519052
Author:     Jin Yao <yao.jin@linux.intel.com>
AuthorDate: Fri, 8 Dec 2017 21:13:42 +0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Jan 2018 11:20:56 -0300

perf record: Record the first and last sample time in the header

In the default 'perf record' configuration, all samples are processed,
to create the HEADER_BUILD_ID table. So it's very easy to get the
first/last samples and save the time to perf file header via the
function write_sample_time().

Later, at post processing time, perf report/script will fetch the time
from perf file header.

Committer testing:

  # perf record -a sleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 2.099 MB perf.data (1101 samples) ]
  [root@jouet home]# perf report --header | grep "time of "
  # time of first sample : 22947.909226
  # time of last sample : 22948.910704
  #
  # perf report -D | grep PERF_RECORD_SAMPLE\(
  0 22947909226101 0x20bb68 [0x30]: PERF_RECORD_SAMPLE(IP, 0x4001): 0/0: 0xffffffffa21b1af3 period: 1 addr: 0
  0 22947909229928 0x20bb98 [0x30]: PERF_RECORD_SAMPLE(IP, 0x4001): 0/0: 0xffffffffa200d204 period: 1 addr: 0
  <SNIP>
  3 22948910397351 0x219360 [0x30]: PERF_RECORD_SAMPLE(IP, 0x4001): 28251/28251: 0xffffffffa22071d8 period: 169518 addr: 0
  0 22948910652380 0x20f120 [0x30]: PERF_RECORD_SAMPLE(IP, 0x4001): 0/0: 0xffffffffa2856816 period: 198807 addr: 0
  2 22948910704034 0x2172d0 [0x30]: PERF_RECORD_SAMPLE(IP, 0x4001): 0/0: 0xffffffffa2856816 period: 88111 addr: 0
  #

Changelog:

v7: Just update the patch description according to Arnaldo's suggestion.

v6: Currently '--buildid-all' is not enabled at default. So the walking
    on all samples is the default operation. There is no big overhead
    to calculate the timestamp boundary in process_sample_event handler
    once we already go through all samples. So the timestamp boundary
    calculation is enabled by default when '--buildid-all' is not enabled.

    While if '--buildid-all' is enabled, we creates a new option
    "--timestamp-boundary" for user to decide if it enables the
    timestamp boundary calculation.

v5: There is an issue that the sample walking can only work when
    '--buildid-all' is not enabled. So we need to let the walking
    be able to work even if '--buildid-all' is enabled and let the
    processing skips the dso hit marking for this case.

    At first, I want to provide a new option "--record-time-boundaries".
    While after consideration, I think a new option is not very
    necessary.

v3: Remove the definitions of first_sample_time and last_sample_time
    from struct record and directly save them in perf_evlist.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1512738826-2628-3-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-record.txt |  3 +++
 tools/perf/builtin-record.c              | 18 +++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 5a626ef..3eea6de 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -430,6 +430,9 @@ Configure all used events to run in user space.
 --timestamp-filename
 Append timestamp to output file name.
 
+--timestamp-boundary::
+Record timestamp boundary (time of first/last samples).
+
 --switch-output[=mode]::
 Generate multiple perf.data files, timestamp prefixed, switching to a new one
 based on 'mode' value:
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 50385d8..65681a1 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -78,6 +78,7 @@ struct record {
 	bool			no_buildid_cache_set;
 	bool			buildid_all;
 	bool			timestamp_filename;
+	bool			timestamp_boundary;
 	struct switch_output	switch_output;
 	unsigned long long	samples;
 };
@@ -409,8 +410,15 @@ static int process_sample_event(struct perf_tool *tool,
 {
 	struct record *rec = container_of(tool, struct record, tool);
 
-	rec->samples++;
+	if (rec->evlist->first_sample_time == 0)
+		rec->evlist->first_sample_time = sample->time;
+
+	rec->evlist->last_sample_time = sample->time;
 
+	if (rec->buildid_all)
+		return 0;
+
+	rec->samples++;
 	return build_id__mark_dso_hit(tool, event, sample, evsel, machine);
 }
 
@@ -435,9 +443,11 @@ static int process_buildids(struct record *rec)
 
 	/*
 	 * If --buildid-all is given, it marks all DSO regardless of hits,
-	 * so no need to process samples.
+	 * so no need to process samples. But if timestamp_boundary is enabled,
+	 * it still needs to walk on all samples to get the timestamps of
+	 * first/last samples.
 	 */
-	if (rec->buildid_all)
+	if (rec->buildid_all && !rec->timestamp_boundary)
 		rec->tool.sample = NULL;
 
 	return perf_session__process_events(session);
@@ -1621,6 +1631,8 @@ static struct option __record_options[] = {
 		    "Record build-id of all DSOs regardless of hits"),
 	OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
 		    "append timestamp to output filename"),
+	OPT_BOOLEAN(0, "timestamp-boundary", &record.timestamp_boundary,
+		    "Record timestamp boundary (time of first/last samples)"),
 	OPT_STRING_OPTARG_SET(0, "switch-output", &record.switch_output.str,
 			  &record.switch_output.set, "signal,size,time",
 			  "Switch output when receive SIGUSR2 or cross size,time threshold",

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

* [tip:perf/core] perf tools: Create function to parse time percent
  2017-12-08 13:13 ` [PATCH v7 3/6] perf util: Create function to parse time percent Jin Yao
  2018-01-08 14:31   ` Arnaldo Carvalho de Melo
@ 2018-01-11  6:22   ` tip-bot for Jin Yao
  1 sibling, 0 replies; 29+ messages in thread
From: tip-bot for Jin Yao @ 2018-01-11  6:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: kan.liang, alexander.shishkin, tglx, acme, ak, jolsa, yao.jin,
	linux-kernel, peterz, mingo, hpa

Commit-ID:  13a70f350665580708ab11f725d3578eaacbf2d0
Gitweb:     https://git.kernel.org/tip/13a70f350665580708ab11f725d3578eaacbf2d0
Author:     Jin Yao <yao.jin@linux.intel.com>
AuthorDate: Fri, 8 Dec 2017 21:13:43 +0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Jan 2018 11:39:09 -0300

perf tools: Create function to parse time percent

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

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%

Changelog:

v4: An issue is found. Following passes.
    perf script --time 10%/10x12321xsdfdasfdsafdsafdsa

    Now it uses strtol to replace atoi.

Committer notes:

This just puts in place the infrastructure, so the examples in this cset
comment will only work later, after more patches in this series are
applied.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1512738826-2628-4-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/time-utils.c | 205 ++++++++++++++++++++++++++++++++++++++++---
 tools/perf/util/time-utils.h |   3 +
 2 files changed, 196 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index 81927d0..61c46022 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -6,6 +6,7 @@
 #include <time.h>
 #include <errno.h>
 #include <inttypes.h>
+#include <math.h>
 
 #include "perf.h"
 #include "debug.h"
@@ -60,11 +61,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;
@@ -74,25 +74,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)
@@ -104,6 +114,177 @@ 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, *end_str;
+	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 = (int)strtol(p, &end_str, 10);
+	if (*end_str)
+		return -1;
+
+	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 15b475c..2308723 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -13,6 +13,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);

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

* [tip:perf/core] perf tools: Create function to perform multiple time range checking
  2017-12-08 13:13 ` [PATCH v7 4/6] perf util: Create function to perform multiple time range checking Jin Yao
@ 2018-01-11  6:22   ` tip-bot for Jin Yao
  0 siblings, 0 replies; 29+ messages in thread
From: tip-bot for Jin Yao @ 2018-01-11  6:22 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ak, mingo, alexander.shishkin, kan.liang, jolsa, yao.jin, acme,
	linux-kernel, tglx, peterz, hpa

Commit-ID:  9a9b8b4b2271e763c1600311a3d4ecc2ac359b55
Gitweb:     https://git.kernel.org/tip/9a9b8b4b2271e763c1600311a3d4ecc2ac359b55
Author:     Jin Yao <yao.jin@linux.intel.com>
AuthorDate: Fri, 8 Dec 2017 21:13:44 +0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Jan 2018 11:41:06 -0300

perf tools: Create function to perform multiple time range checking

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%].

Note that it includes the last element in [10%, 20%] but it doesn't
include the last element in [0, 10%). It's to avoid the overlap.

This patch implments a new function perf_time__ranges_skip_sample
for this checking.

Change log:

v4: Let perf_time__ranges_skip_sample be compatible with
    perf_time__skip_sample when only one time range.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1512738826-2628-5-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/time-utils.c | 28 ++++++++++++++++++++++++++++
 tools/perf/util/time-utils.h |  3 +++
 2 files changed, 31 insertions(+)

diff --git a/tools/perf/util/time-utils.c b/tools/perf/util/time-utils.c
index 61c46022..3f7f18f 100644
--- a/tools/perf/util/time-utils.c
+++ b/tools/perf/util/time-utils.c
@@ -300,6 +300,34 @@ 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;
+
+	if (num == 1)
+		return perf_time__skip_sample(&ptime_buf[0], timestamp);
+
+	/*
+	 * start/end of multiple time ranges must be valid.
+	 */
+	for (i = 0; i < num; i++) {
+		ptime = &ptime_buf[i];
+
+		if (timestamp >= ptime->start &&
+		    ((timestamp < ptime->end && i < num - 1) ||
+		     (timestamp <= ptime->end && i == num - 1))) {
+			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 2308723..34d5eba 100644
--- a/tools/perf/util/time-utils.h
+++ b/tools/perf/util/time-utils.h
@@ -18,6 +18,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);

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

* [tip:perf/core] perf report: Support time percent and multiple time ranges
  2017-12-08 13:13 ` [PATCH v7 5/6] perf report: support time percent and multiple time ranges Jin Yao
  2018-01-08 14:45   ` Arnaldo Carvalho de Melo
  2018-01-08 14:53   ` Arnaldo Carvalho de Melo
@ 2018-01-11  6:23   ` tip-bot for Jin Yao
  2 siblings, 0 replies; 29+ messages in thread
From: tip-bot for Jin Yao @ 2018-01-11  6:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, tglx, mingo, alexander.shishkin, yao.jin, linux-kernel, ak,
	jolsa, peterz, kan.liang, acme

Commit-ID:  5b969bc766807e5c2f184d1d6f97b8471de946f1
Gitweb:     https://git.kernel.org/tip/5b969bc766807e5c2f184d1d6f97b8471de946f1
Author:     Jin Yao <yao.jin@linux.intel.com>
AuthorDate: Fri, 8 Dec 2017 21:13:45 +0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Jan 2018 12:06:20 -0300

perf report: Support time percent and multiple time ranges

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%

Changelog:

v6: Fix the merge issue with latest perf/core branch.
    No functional changes.

v5: Add checking of first/last sample time to detect if it's recorded
    in perf.data. If it's not recorded, returns error message to user.

v4: Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample

v3: Since the definitions of first_sample_time/last_sample_time
    are moved from perf_session to perf_evlist so change the
    related code.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1512738826-2628-6-git-send-email-yao.jin@linux.intel.com
[ Add missing colons at end of examples in the man page ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-report.txt | 20 ++++++++++++++++++++
 tools/perf/builtin-report.c              | 31 ++++++++++++++++++++++++++-----
 2 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index ddde2b5..1e02c4e 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -402,6 +402,26 @@ 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 multiple 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 07827cd..770bf8a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -52,6 +52,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+#define PTIME_RANGE_MAX	10
+
 struct report {
 	struct perf_tool	tool;
 	struct perf_session	*session;
@@ -69,7 +71,8 @@ struct report {
 	const char		*cpu_list;
 	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;
@@ -202,8 +205,10 @@ static int process_sample_event(struct perf_tool *tool,
 	};
 	int ret = 0;
 
-	if (perf_time__skip_sample(&rep->ptime, sample->time))
+	if (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",
@@ -1093,9 +1098,25 @@ repeat:
 	if (symbol__init(&session->header.env) < 0)
 		goto error;
 
-	if (perf_time__parse_str(&report.ptime, report.time_str) != 0) {
-		pr_err("Invalid time string\n");
-		return -EINVAL;
+	if (perf_time__parse_str(report.ptime_range, report.time_str) != 0) {
+		if (session->evlist->first_sample_time == 0 &&
+		    session->evlist->last_sample_time == 0) {
+			pr_err("No first/last sample time in perf data\n");
+			return -EINVAL;
+		}
+
+		report.range_num = perf_time__percent_parse_str(
+					report.ptime_range, PTIME_RANGE_MAX,
+					report.time_str,
+					session->evlist->first_sample_time,
+					session->evlist->last_sample_time);
+
+		if (report.range_num < 0) {
+			pr_err("Invalid time string\n");
+			return -EINVAL;
+		}
+	} else {
+		report.range_num = 1;
 	}
 
 	sort__setup_elide(stdout);

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

* [tip:perf/core] perf script: Support time percent and multiple time ranges
  2017-12-08 13:13 ` [PATCH v7 6/6] perf script: support " Jin Yao
@ 2018-01-11  6:23   ` tip-bot for Jin Yao
  0 siblings, 0 replies; 29+ messages in thread
From: tip-bot for Jin Yao @ 2018-01-11  6:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, alexander.shishkin, jolsa, mingo, hpa, kan.liang, yao.jin,
	linux-kernel, ak, peterz, tglx

Commit-ID:  2ab046cd01e33a854798a3e245c9e3f32b950a7d
Gitweb:     https://git.kernel.org/tip/2ab046cd01e33a854798a3e245c9e3f32b950a7d
Author:     Jin Yao <yao.jin@linux.intel.com>
AuthorDate: Fri, 8 Dec 2017 21:13:46 +0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Mon, 8 Jan 2018 12:07:06 -0300

perf script: Support time percent and multiple time ranges

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%

Changelog:

v6: Fix the merge issue with latest perf/core branch.
    No functional changes.

v5: Add checking of first/last sample time to detect if it's recorded
    in perf.data. If it's not recorded, returns error message to user.

v4: Remove perf_time__skip_sample, only uses perf_time__ranges_skip_sample

v3: Since the definitions of first_sample_time/last_sample_time
    are moved from perf_session to perf_evlist so change the
    related code.

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1512738826-2628-7-git-send-email-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-script.txt | 16 +++++++++++++++
 tools/perf/builtin-script.c              | 34 ++++++++++++++++++++++++++------
 2 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 974ceb1..7b622a8 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -329,6 +329,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 77e47cf..330dcd9 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1436,6 +1436,8 @@ static int perf_sample__fprintf_synth(struct perf_sample *sample,
 	return 0;
 }
 
+#define PTIME_RANGE_MAX	10
+
 struct perf_script {
 	struct perf_tool	tool;
 	struct perf_session	*session;
@@ -1449,7 +1451,8 @@ struct perf_script {
 	struct thread_map	*threads;
 	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)
@@ -1734,8 +1737,10 @@ 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__ranges_skip_sample(scr->ptime_range, scr->range_num,
+					  sample->time)) {
 		return 0;
+	}
 
 	if (debug_mode) {
 		if (sample->time < last_timestamp) {
@@ -3360,10 +3365,27 @@ int cmd_script(int argc, const char **argv)
 		goto out_delete;
 
 	/* 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");
-		err = -EINVAL;
-		goto out_delete;
+	if (perf_time__parse_str(script.ptime_range, script.time_str) != 0) {
+		if (session->evlist->first_sample_time == 0 &&
+		    session->evlist->last_sample_time == 0) {
+			pr_err("No first/last sample time in perf data\n");
+			err = -EINVAL;
+			goto out_delete;
+		}
+
+		script.range_num = perf_time__percent_parse_str(
+					script.ptime_range, PTIME_RANGE_MAX,
+					script.time_str,
+					session->evlist->first_sample_time,
+					session->evlist->last_sample_time);
+
+		if (script.range_num < 0) {
+			pr_err("Invalid time string\n");
+			err = -EINVAL;
+			goto out_delete;
+		}
+	} else {
+		script.range_num = 1;
 	}
 
 	err = __cmd_script(&script);

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

end of thread, other threads:[~2018-01-11  6:26 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-08 13:13 [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Jin Yao
2017-12-08 13:13 ` [PATCH v7 1/6] perf header: Record first sample time and last sample time in perf file header Jin Yao
2018-01-11  6:21   ` [tip:perf/core] perf header: Add infrastructure to record first and last sample time tip-bot for Jin Yao
2017-12-08 13:13 ` [PATCH v7 2/6] perf record: Get the first sample time " Jin Yao
2018-01-04 19:09   ` Arnaldo Carvalho de Melo
2018-01-05  1:15     ` Jin, Yao
2018-01-05 12:53       ` Arnaldo Carvalho de Melo
2018-01-05 22:55         ` Jin, Yao
2018-01-11  6:22   ` [tip:perf/core] perf record: Record the first and last sample time in the header tip-bot for Jin Yao
2017-12-08 13:13 ` [PATCH v7 3/6] perf util: Create function to parse time percent Jin Yao
2018-01-08 14:31   ` Arnaldo Carvalho de Melo
2018-01-08 14:38     ` Arnaldo Carvalho de Melo
2018-01-09  1:18       ` Jin, Yao
2018-01-11  6:22   ` [tip:perf/core] perf tools: " tip-bot for Jin Yao
2017-12-08 13:13 ` [PATCH v7 4/6] perf util: Create function to perform multiple time range checking Jin Yao
2018-01-11  6:22   ` [tip:perf/core] perf tools: " tip-bot for Jin Yao
2017-12-08 13:13 ` [PATCH v7 5/6] perf report: support time percent and multiple time ranges Jin Yao
2018-01-08 14:45   ` Arnaldo Carvalho de Melo
2018-01-08 14:48     ` Arnaldo Carvalho de Melo
2018-01-08 14:53   ` Arnaldo Carvalho de Melo
2018-01-08 15:02     ` Arnaldo Carvalho de Melo
2018-01-08 15:04       ` Arnaldo Carvalho de Melo
2018-01-09  2:02         ` Jin, Yao
2018-01-11  6:23   ` [tip:perf/core] perf report: Support " tip-bot for Jin Yao
2017-12-08 13:13 ` [PATCH v7 6/6] perf script: support " Jin Yao
2018-01-11  6:23   ` [tip:perf/core] perf script: Support " tip-bot for Jin Yao
2017-12-13 14:28 ` [PATCH v7 0/6] perf report/script: Support percent and multiple range in --time option Arnaldo Carvalho de Melo
2017-12-14  0:48   ` Jin, Yao
2017-12-14 14:08 ` Jiri Olsa

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.