linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jin Yao <yao.jin@linux.intel.com>
To: acme@kernel.org, jolsa@kernel.org, peterz@infradead.org,
	mingo@redhat.com, alexander.shishkin@linux.intel.com
Cc: Linux-kernel@vger.kernel.org, ak@linux.intel.com,
	kan.liang@intel.com, yao.jin@intel.com,
	Jin Yao <yao.jin@linux.intel.com>
Subject: [PATCH v1 1/6] perf record: Record the first sample time and last sample time to perf file header
Date: Wed, 20 Sep 2017 23:12:32 +0800	[thread overview]
Message-ID: <1505920357-25561-2-git-send-email-yao.jin@linux.intel.com> (raw)
In-Reply-To: <1505920357-25561-1-git-send-email-yao.jin@linux.intel.com>

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

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

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

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

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

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

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

  reply	other threads:[~2017-09-20  7:16 UTC|newest]

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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1505920357-25561-2-git-send-email-yao.jin@linux.intel.com \
    --to=yao.jin@linux.intel.com \
    --cc=Linux-kernel@vger.kernel.org \
    --cc=acme@kernel.org \
    --cc=ak@linux.intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@intel.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=yao.jin@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).