All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: linux-trace-devel@vger.kernel.org
Cc: "Steven Rostedt (Google)" <rostedt@goodmis.org>
Subject: [PATCH 3/3] libtracecmd: Just save timestamps and not the records in iterators
Date: Thu, 11 Jan 2024 17:15:38 -0500	[thread overview]
Message-ID: <20240111222201.154686-4-rostedt@goodmis.org> (raw)
In-Reply-To: <20240111222201.154686-1-rostedt@goodmis.org>

From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

The iterators cache the records via a tracecmd_peek_data() to find the next
CPU record to use. The problem is that the callback() may do a
tracecmd_read_data() (the function graph plugin does) and this may
invalidate the cached record. It would require refreshing every record of
every cached CPU after every callback, which can be expensive.

Since only the timestamps of the records are needed, simply cache the
timestamp of the record to find which is the next CPU record to use. After
finding the CPU that has the earliest timestamp, do a tracecmd_peek_data()
test again to make sure the timestamp still matches the record. If it does,
then simply use that record, if not, refresh the timestamp for that CPU and
try again.

Fixes: 2cb6cc2f4 ("tracecmd library: Add tracecmd_iterate_events()")
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 lib/trace-cmd/trace-input.c | 60 ++++++++++++++++++++++++-------------
 1 file changed, 40 insertions(+), 20 deletions(-)

diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c
index bc937b0491d7..dbcbf3613686 100644
--- a/lib/trace-cmd/trace-input.c
+++ b/lib/trace-cmd/trace-input.c
@@ -2807,9 +2807,9 @@ int tracecmd_iterate_events(struct tracecmd_input *handle,
 					    int, void *),
 			    void *callback_data)
 {
-	struct tep_record **records;
 	struct tep_record *record;
-	unsigned long long last_timestamp = 0;
+	unsigned long long *timestamps;
+	unsigned long long ts, last_timestamp = 0;
 	int next_cpu;
 	int cpu;
 	int ret = 0;
@@ -2819,42 +2819,53 @@ int tracecmd_iterate_events(struct tracecmd_input *handle,
 		return -1;
 	}
 
-	records = calloc(handle->cpus, sizeof(*records));
-	if (!records)
+	timestamps = calloc(handle->cpus, sizeof(*timestamps));
+	if (!timestamps)
 		return -1;
 
 	for (cpu = 0; cpu < handle->cpus; cpu++) {
 		if (cpus && !CPU_ISSET_S(cpu, cpu_size, cpus))
 			continue;
 
-		records[cpu] = tracecmd_peek_data(handle, cpu);
+		record = tracecmd_peek_data(handle, cpu);
+		timestamps[cpu] = record ? record->ts : -1ULL;
 	}
 
 	do {
 		next_cpu = -1;
 		for (cpu = 0; cpu < handle->cpus; cpu++) {
-			record = records[cpu];
-			if (!record)
+			ts = timestamps[cpu];
+			if (ts == -1ULL)
 				continue;
 
-			if (next_cpu < 0 || record->ts < last_timestamp) {
+			if (next_cpu < 0 || ts < last_timestamp) {
 				next_cpu = cpu;
-				last_timestamp = record->ts;
+				last_timestamp = ts;
 			}
 		}
 		if (next_cpu >= 0) {
+			record = tracecmd_peek_data(handle, next_cpu);
+
+			/* Make sure the record is still what we expect it to be */
+			if (!record || record->ts != last_timestamp) {
+				timestamps[next_cpu] = record ? record->ts : -1ULL;
+				continue;
+			}
+
 			/* Need to call read_data to increment to the next record */
 			record = tracecmd_read_data(handle, next_cpu);
 
 			ret = call_callbacks(handle, record, next_cpu,
 					     callback, callback_data);
 
-			records[next_cpu] = tracecmd_peek_data(handle, next_cpu);
 			tracecmd_free_record(record);
+
+			record = tracecmd_peek_data(handle, next_cpu);
+			timestamps[next_cpu] = record ? record->ts : -1ULL;
 		}
 	} while (next_cpu >= 0 && ret == 0);
 
-	free(records);
+	free(timestamps);
 
 	return ret;
 }
@@ -3036,7 +3047,7 @@ int tracecmd_iterate_events_reverse(struct tracecmd_input *handle,
 }
 
 struct record_handle {
-	struct tep_record		*record;
+	unsigned long long		ts;
 	struct tracecmd_input		*handle;
 };
 
@@ -3063,7 +3074,7 @@ int tracecmd_iterate_events_multi(struct tracecmd_input **handles,
 	struct tracecmd_input *handle;
 	struct record_handle *records;
 	struct tep_record *record;
-	unsigned long long last_timestamp = 0;
+	unsigned long long ts, last_timestamp = 0;
 	int next_cpu;
 	int cpus = 0;
 	int all_cpus = 0;
@@ -3084,7 +3095,8 @@ int tracecmd_iterate_events_multi(struct tracecmd_input **handles,
 		handle = handles[i];
 		handle->start_cpu = all_cpus;
 		for (cpu = 0; cpu < handle->cpus; cpu++) {
-			records[all_cpus + cpu].record = tracecmd_peek_data(handle, cpu);
+			record = tracecmd_peek_data(handle, cpu);
+			records[all_cpus + cpu].ts = record ? record->ts : -1ULL;
 			records[all_cpus + cpu].handle = handle;
 		}
 		all_cpus += cpu;
@@ -3093,19 +3105,28 @@ int tracecmd_iterate_events_multi(struct tracecmd_input **handles,
 	do {
 		next_cpu = -1;
 		for (cpu = 0; cpu < all_cpus; cpu++) {
-			record = records[cpu].record;
-			if (!record)
+			ts = records[cpu].ts;
+			if (ts == -1ULL)
 				continue;
 
-			if (next_cpu < 0 || record->ts < last_timestamp) {
+			if (next_cpu < 0 || ts < last_timestamp) {
 				next_cpu = cpu;
-				last_timestamp = record->ts;
+				last_timestamp = ts;
 			}
 		}
 		if (next_cpu >= 0) {
-			record = records[next_cpu].record;
 			handle = records[next_cpu].handle;
 			cpu = next_cpu - handle->start_cpu;
+
+			/* Refresh record as callback could have changed */
+			record = tracecmd_peek_data(handle, cpu);
+
+			/* If the record updated, try again */
+			if (!record || record->ts != last_timestamp) {
+				records[next_cpu].ts = record ? record->ts : -1ULL;
+				continue;
+			}
+
 			/* Need to call read_data to increment to the next record */
 			record = tracecmd_read_data(handle, cpu);
 
@@ -3113,7 +3134,6 @@ int tracecmd_iterate_events_multi(struct tracecmd_input **handles,
 					     callback, callback_data);
 
 			tracecmd_free_record(record);
-			records[next_cpu].record = tracecmd_peek_data(handle, cpu);
 		}
 
 	} while (next_cpu >= 0 && ret == 0);
-- 
2.43.0


      parent reply	other threads:[~2024-01-11 22:20 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-11 22:15 [PATCH 0/3] libtracecmd: Fix iterators Steven Rostedt
2024-01-11 22:15 ` [PATCH 1/3] libtracecmd: Use cpu_data[cpu]->cpus and not ->max_cpu Steven Rostedt
2024-01-11 22:15 ` [PATCH 2/3] libtracecmd: Do not free records at end of iterator Steven Rostedt
2024-01-11 22:15 ` Steven Rostedt [this message]

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=20240111222201.154686-4-rostedt@goodmis.org \
    --to=rostedt@goodmis.org \
    --cc=linux-trace-devel@vger.kernel.org \
    /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 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.