All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 00/18] perf tools: Factor ordered samples queue
@ 2014-06-18 14:58 Jiri Olsa
  2014-06-18 14:58 ` [PATCH 01/18] perf tools: Always force PERF_RECORD_FINISHED_ROUND event Jiri Olsa
                   ` (18 more replies)
  0 siblings, 19 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra, Jiri Olsa

hi,
this patchset factors session's ordered samples queue,
and allows to limit the size of this queue.

v2 changes:
  - several small changes for review comments (Namhyung)


The report command queues events till any of following
conditions is reached:
  - PERF_RECORD_FINISHED_ROUND event is processed
  - end of the file is reached

Any of above conditions will force the queue to flush some
events while keeping all allocated memory for next events.

If PERF_RECORD_FINISHED_ROUND is missing the queue will
allocate memory for every single event in the perf.data.
This could lead to enormous memory consuption and speed
degradation of report command for huge perf.data files.

With the quue allocation limit of 100 MB, I've got around
15% speedup on reporting of ~10GB perf.data file.

current code:
 Performance counter stats for './perf.old report --stdio -i perf-test.data' (3 runs):

   621,685,704,665      cycles                    ( +-  0.52% )
   873,397,467,969      instructions              ( +-  0.00% )

     286.133268732 seconds time elapsed           ( +-  1.13% )

with patches:
 Performance counter stats for './perf report --stdio -i perf-test.data' (3 runs):

   603,933,987,185      cycles                    ( +-  0.45% )
   869,139,445,070      instructions              ( +-  0.00% )

     245.337510637 seconds time elapsed           ( +-  0.49% )


The speed up seems to be mainly in less cycles spent in servicing
page faults:

current code:
     4.44%     0.01%  perf.old  [kernel.kallsyms]   [k] page_fault                                   

with patches:
     1.45%     0.00%      perf  [kernel.kallsyms]   [k] page_fault                                   

current code (faults event):
         6,643,807      faults                    ( +-  0.36% )

with patches (faults event):
         2,214,756      faults                    ( +-  3.03% )


Also now we have one of our big memory spender under control
and the ordered events queue code is put in separated object
with clear interface ready to be used by another command
like script.

Also reachable in here:
  git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
  perf/core_ordered_events

thanks,
jirka


Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
Jiri Olsa (18):
      perf tools: Always force PERF_RECORD_FINISHED_ROUND event
      perf tools: Fix accounting of ordered samples queue
      perf tools: Rename ordered_samples to ordered_events
      perf tools: Rename ordered_events_queue members
      perf tools: Add ordered_events_(get|put) interface
      perf tools: Factor ordered_events_flush to be more generic
      perf tools: Limit ordered events queue size
      perf tools: Flush ordered events in case of allocation failure
      perf tools: Make perf_session_deliver_event global
      perf tools: Create ordered-events object
      perf tools: Use list_move in ordered_event_put function
      perf tools: Add ordered_events_queue_init function
      perf tools: Add ordered_events_queue_free function
      perf tools: Add perf_config_u64 function
      perf tools: Add report.queue-size config file option
      perf tools: Add debug prints for ordered events queue
      perf tools: Limit the ordered events queue by default to 100MB
      perf tools: Allow out of order messages in forced flush

 tools/perf/Makefile.perf         |   2 +
 tools/perf/builtin-annotate.c    |   2 +-
 tools/perf/builtin-diff.c        |   2 +-
 tools/perf/builtin-inject.c      |   2 +-
 tools/perf/builtin-kmem.c        |   2 +-
 tools/perf/builtin-kvm.c         |   8 +--
 tools/perf/builtin-lock.c        |   2 +-
 tools/perf/builtin-mem.c         |   2 +-
 tools/perf/builtin-record.c      |   7 +-
 tools/perf/builtin-report.c      |  19 ++++-
 tools/perf/builtin-sched.c       |   2 +-
 tools/perf/builtin-script.c      |   2 +-
 tools/perf/builtin-timechart.c   |   2 +-
 tools/perf/builtin-trace.c       |   2 +-
 tools/perf/util/cache.h          |   1 +
 tools/perf/util/config.c         |  24 +++++++
 tools/perf/util/ordered-events.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/ordered-events.h |  55 +++++++++++++++
 tools/perf/util/session.c        | 213 +++++++++----------------------------------------------
 tools/perf/util/session.h        |  40 +++++------
 tools/perf/util/tool.h           |   2 +-
 21 files changed, 444 insertions(+), 220 deletions(-)
 create mode 100644 tools/perf/util/ordered-events.c
 create mode 100644 tools/perf/util/ordered-events.h

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

* [PATCH 01/18] perf tools: Always force PERF_RECORD_FINISHED_ROUND event
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 02/18] perf tools: Fix accounting of ordered samples queue Jiri Olsa
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

The PERF_RECORD_FINISHED_ROUND governs queue flushing in
reporting, so it needs to be stored for any kind of event.

Forcing the PERF_RECORD_FINISHED_ROUND event to be stored any
time we finish the round and wrote at least one event.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-record.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 378b85b..4869050 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -238,6 +238,7 @@ static struct perf_event_header finished_round_event = {
 
 static int record__mmap_read_all(struct record *rec)
 {
+	u64 bytes_written = rec->bytes_written;
 	int i;
 	int rc = 0;
 
@@ -250,7 +251,11 @@ static int record__mmap_read_all(struct record *rec)
 		}
 	}
 
-	if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
+	/*
+	 * Mark the round finished in case we wrote
+	 * at least one event.
+	 */
+	if (bytes_written != rec->bytes_written)
 		rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
 
 out:
-- 
1.8.3.1


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

* [PATCH 02/18] perf tools: Fix accounting of ordered samples queue
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
  2014-06-18 14:58 ` [PATCH 01/18] perf tools: Always force PERF_RECORD_FINISHED_ROUND event Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 03/18] perf tools: Rename ordered_samples to ordered_events Jiri Olsa
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Properly account flushed samples within the ordered
samples queue.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 64a186e..aec3dcd 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -511,6 +511,7 @@ static int flush_sample_queue(struct perf_session *s,
 		os->last_flush = iter->timestamp;
 		list_del(&iter->list);
 		list_add(&iter->list, &os->sample_cache);
+		os->nr_samples--;
 
 		if (show_progress)
 			ui_progress__update(&prog, 1);
@@ -523,8 +524,6 @@ static int flush_sample_queue(struct perf_session *s,
 			list_entry(head->prev, struct sample_queue, list);
 	}
 
-	os->nr_samples = 0;
-
 	return 0;
 }
 
-- 
1.8.3.1


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

* [PATCH 03/18] perf tools: Rename ordered_samples to ordered_events
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
  2014-06-18 14:58 ` [PATCH 01/18] perf tools: Always force PERF_RECORD_FINISHED_ROUND event Jiri Olsa
  2014-06-18 14:58 ` [PATCH 02/18] perf tools: Fix accounting of ordered samples queue Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 04/18] perf tools: Rename ordered_events_queue members Jiri Olsa
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

The time ordering is generic for all kinds of events, so
using generic name 'ordered_events' for related struct.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-annotate.c  |  2 +-
 tools/perf/builtin-diff.c      |  2 +-
 tools/perf/builtin-inject.c    |  2 +-
 tools/perf/builtin-kmem.c      |  2 +-
 tools/perf/builtin-kvm.c       |  6 ++--
 tools/perf/builtin-lock.c      |  2 +-
 tools/perf/builtin-mem.c       |  2 +-
 tools/perf/builtin-report.c    |  2 +-
 tools/perf/builtin-sched.c     |  2 +-
 tools/perf/builtin-script.c    |  2 +-
 tools/perf/builtin-timechart.c |  2 +-
 tools/perf/builtin-trace.c     |  2 +-
 tools/perf/util/session.c      | 64 +++++++++++++++++++++---------------------
 tools/perf/util/session.h      | 24 ++++++++--------
 tools/perf/util/tool.h         |  2 +-
 15 files changed, 59 insertions(+), 59 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec429f..952b5ec 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -297,7 +297,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
 			.comm	= perf_event__process_comm,
 			.exit	= perf_event__process_exit,
 			.fork	= perf_event__process_fork,
-			.ordered_samples = true,
+			.ordered_events = true,
 			.ordering_requires_timestamps = true,
 		},
 	};
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 9a5a035..c10cc44 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -360,7 +360,7 @@ static struct perf_tool tool = {
 	.exit	= perf_event__process_exit,
 	.fork	= perf_event__process_fork,
 	.lost	= perf_event__process_lost,
-	.ordered_samples = true,
+	.ordered_events = true,
 	.ordering_requires_timestamps = true,
 };
 
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 16c7c11..94173dd 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -366,7 +366,7 @@ static int __cmd_inject(struct perf_inject *inject)
 	} else if (inject->sched_stat) {
 		struct perf_evsel *evsel;
 
-		inject->tool.ordered_samples = true;
+		inject->tool.ordered_events = true;
 
 		evlist__for_each(session->evlist, evsel) {
 			const char *name = perf_evsel__name(evsel);
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bef3376..b572111 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -256,7 +256,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
 static struct perf_tool perf_kmem = {
 	.sample		 = process_sample_event,
 	.comm		 = perf_event__process_comm,
-	.ordered_samples = true,
+	.ordered_events	 = true,
 };
 
 static double fragmentation(unsigned long n_req, unsigned long n_alloc)
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 0f1e5a2..b2f0ddb 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -955,7 +955,7 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
 
 	/* flush queue after each round in which we processed events */
 	if (ntotal) {
-		kvm->session->ordered_samples.next_flush = flush_time;
+		kvm->session->ordered_events.next_flush = flush_time;
 		err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
 		if (err) {
 			if (kvm->lost_events)
@@ -1228,7 +1228,7 @@ static int read_events(struct perf_kvm_stat *kvm)
 	struct perf_tool eops = {
 		.sample			= process_sample_event,
 		.comm			= perf_event__process_comm,
-		.ordered_samples	= true,
+		.ordered_events		= true,
 	};
 	struct perf_data_file file = {
 		.path = kvm->file_name,
@@ -1480,7 +1480,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
 	kvm->tool.exit   = perf_event__process_exit;
 	kvm->tool.fork   = perf_event__process_fork;
 	kvm->tool.lost   = process_lost_event;
-	kvm->tool.ordered_samples = true;
+	kvm->tool.ordered_events = true;
 	perf_tool__fill_defaults(&kvm->tool);
 
 	/* set defaults */
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6148afc..c8122d3 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -852,7 +852,7 @@ static int __cmd_report(bool display_info)
 	struct perf_tool eops = {
 		.sample		 = process_sample_event,
 		.comm		 = perf_event__process_comm,
-		.ordered_samples = true,
+		.ordered_events	 = true,
 	};
 	struct perf_data_file file = {
 		.path = input_name,
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 4a1a6c9..80e57c8 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -194,7 +194,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
 			.lost		= perf_event__process_lost,
 			.fork		= perf_event__process_fork,
 			.build_id	= perf_event__process_build_id,
-			.ordered_samples = true,
+			.ordered_events	= true,
 		},
 		.input_name		 = "perf.data",
 	};
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 21d830b..c72cc5a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -578,7 +578,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
 			.attr		 = perf_event__process_attr,
 			.tracing_data	 = perf_event__process_tracing_data,
 			.build_id	 = perf_event__process_build_id,
-			.ordered_samples = true,
+			.ordered_events	 = true,
 			.ordering_requires_timestamps = true,
 		},
 		.max_stack		 = PERF_MAX_STACK_DEPTH,
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index c38d06c..5cb39a3 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1660,7 +1660,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
 			.comm		 = perf_event__process_comm,
 			.lost		 = perf_event__process_lost,
 			.fork		 = perf_sched__process_fork_event,
-			.ordered_samples = true,
+			.ordered_events = true,
 		},
 		.cmp_pid	      = LIST_HEAD_INIT(sched.cmp_pid),
 		.sort_list	      = LIST_HEAD_INIT(sched.sort_list),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9e9c91f..ba4162e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1510,7 +1510,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 			.attr		 = process_attr,
 			.tracing_data	 = perf_event__process_tracing_data,
 			.build_id	 = perf_event__process_build_id,
-			.ordered_samples = true,
+			.ordered_events	 = true,
 			.ordering_requires_timestamps = true,
 		},
 	};
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 74db256..257d9d6 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1279,7 +1279,7 @@ int cmd_timechart(int argc, const char **argv,
 			.fork		 = process_fork_event,
 			.exit		 = process_exit_event,
 			.sample		 = process_sample_event,
-			.ordered_samples = true,
+			.ordered_events	 = true,
 		},
 		.proc_num = 15,
 	};
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index f954c26..c1d338e 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2068,7 +2068,7 @@ static int trace__replay(struct trace *trace)
 	trace->tool.tracing_data = perf_event__process_tracing_data;
 	trace->tool.build_id	  = perf_event__process_build_id;
 
-	trace->tool.ordered_samples = true;
+	trace->tool.ordered_events = true;
 	trace->tool.ordering_requires_timestamps = true;
 
 	/* add tid to output */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index aec3dcd..315d522 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -76,9 +76,9 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
 		goto out;
 
 	session->repipe = repipe;
-	INIT_LIST_HEAD(&session->ordered_samples.samples);
-	INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
-	INIT_LIST_HEAD(&session->ordered_samples.to_free);
+	INIT_LIST_HEAD(&session->ordered_events.samples);
+	INIT_LIST_HEAD(&session->ordered_events.sample_cache);
+	INIT_LIST_HEAD(&session->ordered_events.to_free);
 	machines__init(&session->machines);
 
 	if (file) {
@@ -105,9 +105,9 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
 	}
 
 	if (tool && tool->ordering_requires_timestamps &&
-	    tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) {
+	    tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
 		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
-		tool->ordered_samples = false;
+		tool->ordered_events = false;
 	}
 
 	return session;
@@ -240,7 +240,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
 	if (tool->build_id == NULL)
 		tool->build_id = process_finished_round_stub;
 	if (tool->finished_round == NULL) {
-		if (tool->ordered_samples)
+		if (tool->ordered_events)
 			tool->finished_round = process_finished_round;
 		else
 			tool->finished_round = process_finished_round_stub;
@@ -446,7 +446,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
-struct sample_queue {
+struct ordered_event {
 	u64			timestamp;
 	u64			file_offset;
 	union perf_event	*event;
@@ -455,12 +455,12 @@ struct sample_queue {
 
 static void perf_session_free_sample_buffers(struct perf_session *session)
 {
-	struct ordered_samples *os = &session->ordered_samples;
+	struct ordered_events_queue *os = &session->ordered_events;
 
 	while (!list_empty(&os->to_free)) {
-		struct sample_queue *sq;
+		struct ordered_event *sq;
 
-		sq = list_entry(os->to_free.next, struct sample_queue, list);
+		sq = list_entry(os->to_free.next, struct ordered_event, list);
 		list_del(&sq->list);
 		free(sq);
 	}
@@ -472,12 +472,12 @@ static int perf_session_deliver_event(struct perf_session *session,
 				      struct perf_tool *tool,
 				      u64 file_offset);
 
-static int flush_sample_queue(struct perf_session *s,
+static int ordered_events_flush(struct perf_session *s,
 		       struct perf_tool *tool)
 {
-	struct ordered_samples *os = &s->ordered_samples;
+	struct ordered_events_queue *os = &s->ordered_events;
 	struct list_head *head = &os->samples;
-	struct sample_queue *tmp, *iter;
+	struct ordered_event *tmp, *iter;
 	struct perf_sample sample;
 	u64 limit = os->next_flush;
 	u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
@@ -485,7 +485,7 @@ static int flush_sample_queue(struct perf_session *s,
 	struct ui_progress prog;
 	int ret;
 
-	if (!tool->ordered_samples || !limit)
+	if (!tool->ordered_events || !limit)
 		return 0;
 
 	if (show_progress)
@@ -521,7 +521,7 @@ static int flush_sample_queue(struct perf_session *s,
 		os->last_sample = NULL;
 	} else if (last_ts <= limit) {
 		os->last_sample =
-			list_entry(head->prev, struct sample_queue, list);
+			list_entry(head->prev, struct ordered_event, list);
 	}
 
 	return 0;
@@ -570,18 +570,18 @@ static int process_finished_round(struct perf_tool *tool,
 				  union perf_event *event __maybe_unused,
 				  struct perf_session *session)
 {
-	int ret = flush_sample_queue(session, tool);
+	int ret = ordered_events_flush(session, tool);
 	if (!ret)
-		session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
+		session->ordered_events.next_flush = session->ordered_events.max_timestamp;
 
 	return ret;
 }
 
 /* The queue is ordered by time */
-static void __queue_event(struct sample_queue *new, struct perf_session *s)
+static void __queue_event(struct ordered_event *new, struct perf_session *s)
 {
-	struct ordered_samples *os = &s->ordered_samples;
-	struct sample_queue *sample = os->last_sample;
+	struct ordered_events_queue *os = &s->ordered_events;
+	struct ordered_event *sample = os->last_sample;
 	u64 timestamp = new->timestamp;
 	struct list_head *p;
 
@@ -607,7 +607,7 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
 				os->max_timestamp = timestamp;
 				return;
 			}
-			sample = list_entry(p, struct sample_queue, list);
+			sample = list_entry(p, struct ordered_event, list);
 		}
 		list_add_tail(&new->list, &sample->list);
 	} else {
@@ -617,32 +617,32 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
 				list_add(&new->list, &os->samples);
 				return;
 			}
-			sample = list_entry(p, struct sample_queue, list);
+			sample = list_entry(p, struct ordered_event, list);
 		}
 		list_add(&new->list, &sample->list);
 	}
 }
 
-#define MAX_SAMPLE_BUFFER	(64 * 1024 / sizeof(struct sample_queue))
+#define MAX_SAMPLE_BUFFER	(64 * 1024 / sizeof(struct ordered_event))
 
 int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 				    struct perf_sample *sample, u64 file_offset)
 {
-	struct ordered_samples *os = &s->ordered_samples;
+	struct ordered_events_queue *os = &s->ordered_events;
 	struct list_head *sc = &os->sample_cache;
 	u64 timestamp = sample->time;
-	struct sample_queue *new;
+	struct ordered_event *new;
 
 	if (!timestamp || timestamp == ~0ULL)
 		return -ETIME;
 
-	if (timestamp < s->ordered_samples.last_flush) {
+	if (timestamp < s->ordered_events.last_flush) {
 		printf("Warning: Timestamp below last timeslice flush\n");
 		return -EINVAL;
 	}
 
 	if (!list_empty(sc)) {
-		new = list_entry(sc->next, struct sample_queue, list);
+		new = list_entry(sc->next, struct ordered_event, list);
 		list_del(&new->list);
 	} else if (os->sample_buffer) {
 		new = os->sample_buffer + os->sample_buffer_idx;
@@ -1062,7 +1062,7 @@ static int perf_session__process_event(struct perf_session *session,
 	if (ret)
 		return ret;
 
-	if (tool->ordered_samples) {
+	if (tool->ordered_events) {
 		ret = perf_session_queue_event(session, event, &sample,
 					       file_offset);
 		if (ret != -ETIME)
@@ -1221,8 +1221,8 @@ more:
 		goto more;
 done:
 	/* do the final flush for ordered samples */
-	session->ordered_samples.next_flush = ULLONG_MAX;
-	err = flush_sample_queue(session, tool);
+	session->ordered_events.next_flush = ULLONG_MAX;
+	err = ordered_events_flush(session, tool);
 out_err:
 	free(buf);
 	perf_session__warn_about_errors(session, tool);
@@ -1357,8 +1357,8 @@ more:
 
 out:
 	/* do the final flush for ordered samples */
-	session->ordered_samples.next_flush = ULLONG_MAX;
-	err = flush_sample_queue(session, tool);
+	session->ordered_events.next_flush = ULLONG_MAX;
+	err = ordered_events_flush(session, tool);
 out_err:
 	ui_progress__finish();
 	perf_session__warn_about_errors(session, tool);
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 3140f8a..91902ea 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -12,32 +12,32 @@
 #include <linux/rbtree.h>
 #include <linux/perf_event.h>
 
-struct sample_queue;
+struct ordered_event;
 struct ip_callchain;
 struct thread;
 
-struct ordered_samples {
+struct ordered_events_queue {
 	u64			last_flush;
 	u64			next_flush;
 	u64			max_timestamp;
 	struct list_head	samples;
 	struct list_head	sample_cache;
 	struct list_head	to_free;
-	struct sample_queue	*sample_buffer;
-	struct sample_queue	*last_sample;
+	struct ordered_event	*sample_buffer;
+	struct ordered_event	*last_sample;
 	int			sample_buffer_idx;
 	unsigned int		nr_samples;
 };
 
 struct perf_session {
-	struct perf_header	header;
-	struct machines		machines;
-	struct perf_evlist	*evlist;
-	struct trace_event	tevent;
-	struct events_stats	stats;
-	bool			repipe;
-	struct ordered_samples	ordered_samples;
-	struct perf_data_file	*file;
+	struct perf_header		header;
+	struct machines			machines;
+	struct perf_evlist		*evlist;
+	struct trace_event		tevent;
+	struct events_stats		stats;
+	bool				repipe;
+	struct ordered_events_queue	ordered_events;
+	struct perf_data_file		*file;
 };
 
 #define PRINT_IP_OPT_IP		(1<<0)
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 4385816..f116369 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -40,7 +40,7 @@ struct perf_tool {
 	event_op2	tracing_data;
 	event_op2	finished_round,
 			build_id;
-	bool		ordered_samples;
+	bool		ordered_events;
 	bool		ordering_requires_timestamps;
 };
 
-- 
1.8.3.1


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

* [PATCH 04/18] perf tools: Rename ordered_events_queue members
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (2 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 03/18] perf tools: Rename ordered_samples to ordered_events Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface Jiri Olsa
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Rename 'struct ordered_events_queue' members to better
fit the ordered events pattern.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 108 +++++++++++++++++++++++-----------------------
 tools/perf/util/session.h |  12 +++---
 2 files changed, 59 insertions(+), 61 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 315d522..fc4da58 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -76,8 +76,8 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
 		goto out;
 
 	session->repipe = repipe;
-	INIT_LIST_HEAD(&session->ordered_events.samples);
-	INIT_LIST_HEAD(&session->ordered_events.sample_cache);
+	INIT_LIST_HEAD(&session->ordered_events.events);
+	INIT_LIST_HEAD(&session->ordered_events.cache);
 	INIT_LIST_HEAD(&session->ordered_events.to_free);
 	machines__init(&session->machines);
 
@@ -455,12 +455,12 @@ struct ordered_event {
 
 static void perf_session_free_sample_buffers(struct perf_session *session)
 {
-	struct ordered_events_queue *os = &session->ordered_events;
+	struct ordered_events_queue *q = &session->ordered_events;
 
-	while (!list_empty(&os->to_free)) {
+	while (!list_empty(&q->to_free)) {
 		struct ordered_event *sq;
 
-		sq = list_entry(os->to_free.next, struct ordered_event, list);
+		sq = list_entry(q->to_free.next, struct ordered_event, list);
 		list_del(&sq->list);
 		free(sq);
 	}
@@ -475,12 +475,12 @@ static int perf_session_deliver_event(struct perf_session *session,
 static int ordered_events_flush(struct perf_session *s,
 		       struct perf_tool *tool)
 {
-	struct ordered_events_queue *os = &s->ordered_events;
-	struct list_head *head = &os->samples;
+	struct ordered_events_queue *q = &s->ordered_events;
+	struct list_head *head = &q->events;
 	struct ordered_event *tmp, *iter;
 	struct perf_sample sample;
-	u64 limit = os->next_flush;
-	u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
+	u64 limit = q->next_flush;
+	u64 last_ts = q->last ? q->last->timestamp : 0ULL;
 	bool show_progress = limit == ULLONG_MAX;
 	struct ui_progress prog;
 	int ret;
@@ -489,7 +489,7 @@ static int ordered_events_flush(struct perf_session *s,
 		return 0;
 
 	if (show_progress)
-		ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
+		ui_progress__init(&prog, q->nr_events, "Processing time ordered events...");
 
 	list_for_each_entry_safe(iter, tmp, head, list) {
 		if (session_done())
@@ -508,21 +508,19 @@ static int ordered_events_flush(struct perf_session *s,
 				return ret;
 		}
 
-		os->last_flush = iter->timestamp;
+		q->last_flush = iter->timestamp;
 		list_del(&iter->list);
-		list_add(&iter->list, &os->sample_cache);
-		os->nr_samples--;
+		list_add(&iter->list, &q->cache);
+		q->nr_events--;
 
 		if (show_progress)
 			ui_progress__update(&prog, 1);
 	}
 
-	if (list_empty(head)) {
-		os->last_sample = NULL;
-	} else if (last_ts <= limit) {
-		os->last_sample =
-			list_entry(head->prev, struct ordered_event, list);
-	}
+	if (list_empty(head))
+		q->last = NULL;
+	else if (last_ts <= limit)
+		q->last = list_entry(head->prev, struct ordered_event, list);
 
 	return 0;
 }
@@ -580,46 +578,46 @@ static int process_finished_round(struct perf_tool *tool,
 /* The queue is ordered by time */
 static void __queue_event(struct ordered_event *new, struct perf_session *s)
 {
-	struct ordered_events_queue *os = &s->ordered_events;
-	struct ordered_event *sample = os->last_sample;
+	struct ordered_events_queue *q = &s->ordered_events;
+	struct ordered_event *last = q->last;
 	u64 timestamp = new->timestamp;
 	struct list_head *p;
 
-	++os->nr_samples;
-	os->last_sample = new;
+	++q->nr_events;
+	q->last = new;
 
-	if (!sample) {
-		list_add(&new->list, &os->samples);
-		os->max_timestamp = timestamp;
+	if (!last) {
+		list_add(&new->list, &q->events);
+		q->max_timestamp = timestamp;
 		return;
 	}
 
 	/*
-	 * last_sample might point to some random place in the list as it's
-	 * the last queued event. We expect that the new event is close to
+	 * last event might point to some random place in the list as it's
+	 * the last queued event. We expect that the new event is clqe to
 	 * this.
 	 */
-	if (sample->timestamp <= timestamp) {
-		while (sample->timestamp <= timestamp) {
-			p = sample->list.next;
-			if (p == &os->samples) {
-				list_add_tail(&new->list, &os->samples);
-				os->max_timestamp = timestamp;
+	if (last->timestamp <= timestamp) {
+		while (last->timestamp <= timestamp) {
+			p = last->list.next;
+			if (p == &q->events) {
+				list_add_tail(&new->list, &q->events);
+				q->max_timestamp = timestamp;
 				return;
 			}
-			sample = list_entry(p, struct ordered_event, list);
+			last = list_entry(p, struct ordered_event, list);
 		}
-		list_add_tail(&new->list, &sample->list);
+		list_add_tail(&new->list, &last->list);
 	} else {
-		while (sample->timestamp > timestamp) {
-			p = sample->list.prev;
-			if (p == &os->samples) {
-				list_add(&new->list, &os->samples);
+		while (last->timestamp > timestamp) {
+			p = last->list.prev;
+			if (p == &q->events) {
+				list_add(&new->list, &q->events);
 				return;
 			}
-			sample = list_entry(p, struct ordered_event, list);
+			last = list_entry(p, struct ordered_event, list);
 		}
-		list_add(&new->list, &sample->list);
+		list_add(&new->list, &last->list);
 	}
 }
 
@@ -628,8 +626,8 @@ static void __queue_event(struct ordered_event *new, struct perf_session *s)
 int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 				    struct perf_sample *sample, u64 file_offset)
 {
-	struct ordered_events_queue *os = &s->ordered_events;
-	struct list_head *sc = &os->sample_cache;
+	struct ordered_events_queue *q = &s->ordered_events;
+	struct list_head *cache = &q->cache;
 	u64 timestamp = sample->time;
 	struct ordered_event *new;
 
@@ -641,20 +639,20 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 		return -EINVAL;
 	}
 
-	if (!list_empty(sc)) {
-		new = list_entry(sc->next, struct ordered_event, list);
+	if (!list_empty(cache)) {
+		new = list_entry(cache->next, struct ordered_event, list);
 		list_del(&new->list);
-	} else if (os->sample_buffer) {
-		new = os->sample_buffer + os->sample_buffer_idx;
-		if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
-			os->sample_buffer = NULL;
+	} else if (q->buffer) {
+		new = q->buffer + q->buffer_idx;
+		if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
+			q->buffer = NULL;
 	} else {
-		os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
-		if (!os->sample_buffer)
+		q->buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
+		if (!q->buffer)
 			return -ENOMEM;
-		list_add(&os->sample_buffer->list, &os->to_free);
-		os->sample_buffer_idx = 2;
-		new = os->sample_buffer + 1;
+		list_add(&q->buffer->list, &q->to_free);
+		q->buffer_idx = 2;
+		new = q->buffer + 1;
 	}
 
 	new->timestamp = timestamp;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 91902ea..76b897f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -20,13 +20,13 @@ struct ordered_events_queue {
 	u64			last_flush;
 	u64			next_flush;
 	u64			max_timestamp;
-	struct list_head	samples;
-	struct list_head	sample_cache;
+	struct list_head	events;
+	struct list_head	cache;
 	struct list_head	to_free;
-	struct ordered_event	*sample_buffer;
-	struct ordered_event	*last_sample;
-	int			sample_buffer_idx;
-	unsigned int		nr_samples;
+	struct ordered_event	*buffer;
+	struct ordered_event	*last;
+	int			buffer_idx;
+	unsigned int		nr_events;
 };
 
 struct perf_session {
-- 
1.8.3.1


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

* [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (3 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 04/18] perf tools: Rename ordered_events_queue members Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-27 23:06   ` David Ahern
  2014-06-18 14:58 ` [PATCH 06/18] perf tools: Factor ordered_events_flush to be more generic Jiri Olsa
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Adding new ordered events interface to get|put event buffer:
  ordered_events_get - allocate event buffer from the cache
  ordered_events_put - return event buffer to the cache

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 170 +++++++++++++++++++++++++++-------------------
 1 file changed, 99 insertions(+), 71 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index fc4da58..7ce26c4 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -466,6 +466,101 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
 	}
 }
 
+/* The queue is ordered by time */
+static void queue_event(struct ordered_events_queue *q, struct ordered_event *new)
+{
+	struct ordered_event *last = q->last;
+	u64 timestamp = new->timestamp;
+	struct list_head *p;
+
+	++q->nr_events;
+	q->last = new;
+
+	if (!last) {
+		list_add(&new->list, &q->events);
+		q->max_timestamp = timestamp;
+		return;
+	}
+
+	/*
+	 * last event might point to some random place in the list as it's
+	 * the last queued event. We expect that the new event is clqe to
+	 * this.
+	 */
+	if (last->timestamp <= timestamp) {
+		while (last->timestamp <= timestamp) {
+			p = last->list.next;
+			if (p == &q->events) {
+				list_add_tail(&new->list, &q->events);
+				q->max_timestamp = timestamp;
+				return;
+			}
+			last = list_entry(p, struct ordered_event, list);
+		}
+		list_add_tail(&new->list, &last->list);
+	} else {
+		while (last->timestamp > timestamp) {
+			p = last->list.prev;
+			if (p == &q->events) {
+				list_add(&new->list, &q->events);
+				return;
+			}
+			last = list_entry(p, struct ordered_event, list);
+		}
+		list_add(&new->list, &last->list);
+	}
+}
+
+#define MAX_SAMPLE_BUFFER	(64 * 1024 / sizeof(struct ordered_event))
+static struct ordered_event *alloc_event(struct ordered_events_queue *q)
+{
+	struct list_head *cache = &q->cache;
+	struct ordered_event *new;
+
+	if (!list_empty(cache)) {
+		new = list_entry(cache->next, struct ordered_event, list);
+		list_del(&new->list);
+	} else if (q->buffer) {
+		new = q->buffer + q->buffer_idx;
+		if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
+			q->buffer = NULL;
+	} else {
+		q->buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
+		if (!q->buffer)
+			return NULL;
+		list_add(&q->buffer->list, &q->to_free);
+
+		/* First entry is abused to maintain the to_free list. */
+		q->buffer_idx = 2;
+		new = q->buffer + 1;
+	}
+
+	return new;
+}
+
+static struct ordered_event*
+ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
+{
+	struct ordered_event *new;
+
+	new = alloc_event(q);
+	if (new) {
+		new->timestamp = timestamp;
+		queue_event(q, new);
+	}
+
+	return new;
+}
+
+static void
+ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
+{
+	list_del(&iter->list);
+	list_add(&iter->list, &q->cache);
+	q->nr_events--;
+}
+
+
 static int perf_session_deliver_event(struct perf_session *session,
 				      union perf_event *event,
 				      struct perf_sample *sample,
@@ -508,10 +603,8 @@ static int ordered_events_flush(struct perf_session *s,
 				return ret;
 		}
 
+		ordered_event_put(q, iter);
 		q->last_flush = iter->timestamp;
-		list_del(&iter->list);
-		list_add(&iter->list, &q->cache);
-		q->nr_events--;
 
 		if (show_progress)
 			ui_progress__update(&prog, 1);
@@ -575,59 +668,10 @@ static int process_finished_round(struct perf_tool *tool,
 	return ret;
 }
 
-/* The queue is ordered by time */
-static void __queue_event(struct ordered_event *new, struct perf_session *s)
-{
-	struct ordered_events_queue *q = &s->ordered_events;
-	struct ordered_event *last = q->last;
-	u64 timestamp = new->timestamp;
-	struct list_head *p;
-
-	++q->nr_events;
-	q->last = new;
-
-	if (!last) {
-		list_add(&new->list, &q->events);
-		q->max_timestamp = timestamp;
-		return;
-	}
-
-	/*
-	 * last event might point to some random place in the list as it's
-	 * the last queued event. We expect that the new event is clqe to
-	 * this.
-	 */
-	if (last->timestamp <= timestamp) {
-		while (last->timestamp <= timestamp) {
-			p = last->list.next;
-			if (p == &q->events) {
-				list_add_tail(&new->list, &q->events);
-				q->max_timestamp = timestamp;
-				return;
-			}
-			last = list_entry(p, struct ordered_event, list);
-		}
-		list_add_tail(&new->list, &last->list);
-	} else {
-		while (last->timestamp > timestamp) {
-			p = last->list.prev;
-			if (p == &q->events) {
-				list_add(&new->list, &q->events);
-				return;
-			}
-			last = list_entry(p, struct ordered_event, list);
-		}
-		list_add(&new->list, &last->list);
-	}
-}
-
-#define MAX_SAMPLE_BUFFER	(64 * 1024 / sizeof(struct ordered_event))
-
 int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 				    struct perf_sample *sample, u64 file_offset)
 {
 	struct ordered_events_queue *q = &s->ordered_events;
-	struct list_head *cache = &q->cache;
 	u64 timestamp = sample->time;
 	struct ordered_event *new;
 
@@ -639,28 +683,12 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 		return -EINVAL;
 	}
 
-	if (!list_empty(cache)) {
-		new = list_entry(cache->next, struct ordered_event, list);
-		list_del(&new->list);
-	} else if (q->buffer) {
-		new = q->buffer + q->buffer_idx;
-		if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
-			q->buffer = NULL;
-	} else {
-		q->buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
-		if (!q->buffer)
-			return -ENOMEM;
-		list_add(&q->buffer->list, &q->to_free);
-		q->buffer_idx = 2;
-		new = q->buffer + 1;
-	}
+	new = ordered_events_get(q, timestamp);
+	if (!new)
+		return -ENOMEM;
 
-	new->timestamp = timestamp;
 	new->file_offset = file_offset;
 	new->event = event;
-
-	__queue_event(new, s);
-
 	return 0;
 }
 
-- 
1.8.3.1


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

* [PATCH 06/18] perf tools: Factor ordered_events_flush to be more generic
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (4 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 07/18] perf tools: Limit ordered events queue size Jiri Olsa
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Centralizing the next_flush calculation under the
ordered_events_flush function.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 47 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 7ce26c4..f6991ac 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -453,6 +453,11 @@ struct ordered_event {
 	struct list_head	list;
 };
 
+enum oeq_flush {
+	OEQ_FLUSH__FINAL,
+	OEQ_FLUSH__ROUND,
+};
+
 static void perf_session_free_sample_buffers(struct perf_session *session)
 {
 	struct ordered_events_queue *q = &session->ordered_events;
@@ -567,8 +572,8 @@ static int perf_session_deliver_event(struct perf_session *session,
 				      struct perf_tool *tool,
 				      u64 file_offset);
 
-static int ordered_events_flush(struct perf_session *s,
-		       struct perf_tool *tool)
+static int __ordered_events_flush(struct perf_session *s,
+				  struct perf_tool *tool)
 {
 	struct ordered_events_queue *q = &s->ordered_events;
 	struct list_head *head = &q->events;
@@ -618,6 +623,32 @@ static int ordered_events_flush(struct perf_session *s,
 	return 0;
 }
 
+static int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
+				enum oeq_flush how)
+{
+	struct ordered_events_queue *q = &s->ordered_events;
+	int err;
+
+	switch (how) {
+	case OEQ_FLUSH__FINAL:
+		q->next_flush = ULLONG_MAX;
+		break;
+
+	case OEQ_FLUSH__ROUND:
+	default:
+		break;
+	};
+
+	err = __ordered_events_flush(s, tool);
+
+	if (!err) {
+		if (how == OEQ_FLUSH__ROUND)
+			q->next_flush = q->max_timestamp;
+	}
+
+	return err;
+}
+
 /*
  * When perf record finishes a pass on every buffers, it records this pseudo
  * event.
@@ -661,11 +692,7 @@ static int process_finished_round(struct perf_tool *tool,
 				  union perf_event *event __maybe_unused,
 				  struct perf_session *session)
 {
-	int ret = ordered_events_flush(session, tool);
-	if (!ret)
-		session->ordered_events.next_flush = session->ordered_events.max_timestamp;
-
-	return ret;
+	return ordered_events_flush(session, tool, OEQ_FLUSH__ROUND);
 }
 
 int perf_session_queue_event(struct perf_session *s, union perf_event *event,
@@ -1247,8 +1274,7 @@ more:
 		goto more;
 done:
 	/* do the final flush for ordered samples */
-	session->ordered_events.next_flush = ULLONG_MAX;
-	err = ordered_events_flush(session, tool);
+	err = ordered_events_flush(session, tool, OEQ_FLUSH__FINAL);
 out_err:
 	free(buf);
 	perf_session__warn_about_errors(session, tool);
@@ -1383,8 +1409,7 @@ more:
 
 out:
 	/* do the final flush for ordered samples */
-	session->ordered_events.next_flush = ULLONG_MAX;
-	err = ordered_events_flush(session, tool);
+	err = ordered_events_flush(session, tool, OEQ_FLUSH__FINAL);
 out_err:
 	ui_progress__finish();
 	perf_session__warn_about_errors(session, tool);
-- 
1.8.3.1


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

* [PATCH 07/18] perf tools: Limit ordered events queue size
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (5 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 06/18] perf tools: Factor ordered_events_flush to be more generic Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-27 23:11   ` David Ahern
  2014-06-18 14:58 ` [PATCH 08/18] perf tools: Flush ordered events in case of allocation failure Jiri Olsa
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Add limit to the ordered events queue allocation. This way
we will be able to control the size of the queue buffers.

There's no limit at the moment (it's set to (u64) -1). The config
code will come in following patches.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 12 +++++++++---
 tools/perf/util/session.h |  2 ++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f6991ac..5c00d9b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -79,6 +79,8 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
 	INIT_LIST_HEAD(&session->ordered_events.events);
 	INIT_LIST_HEAD(&session->ordered_events.cache);
 	INIT_LIST_HEAD(&session->ordered_events.to_free);
+	session->ordered_events.max_alloc_size = (u64) -1;
+	session->ordered_events.cur_alloc_size = 0;
 	machines__init(&session->machines);
 
 	if (file) {
@@ -520,7 +522,7 @@ static void queue_event(struct ordered_events_queue *q, struct ordered_event *ne
 static struct ordered_event *alloc_event(struct ordered_events_queue *q)
 {
 	struct list_head *cache = &q->cache;
-	struct ordered_event *new;
+	struct ordered_event *new = NULL;
 
 	if (!list_empty(cache)) {
 		new = list_entry(cache->next, struct ordered_event, list);
@@ -529,10 +531,14 @@ static struct ordered_event *alloc_event(struct ordered_events_queue *q)
 		new = q->buffer + q->buffer_idx;
 		if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
 			q->buffer = NULL;
-	} else {
-		q->buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
+	} else if (q->cur_alloc_size < q->max_alloc_size) {
+		size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
+
+		q->buffer = malloc(size);
 		if (!q->buffer)
 			return NULL;
+
+		q->cur_alloc_size += size;
 		list_add(&q->buffer->list, &q->to_free);
 
 		/* First entry is abused to maintain the to_free list. */
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 76b897f..9f64ac9 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -20,6 +20,8 @@ struct ordered_events_queue {
 	u64			last_flush;
 	u64			next_flush;
 	u64			max_timestamp;
+	u64			max_alloc_size;
+	u64			cur_alloc_size;
 	struct list_head	events;
 	struct list_head	cache;
 	struct list_head	to_free;
-- 
1.8.3.1


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

* [PATCH 08/18] perf tools: Flush ordered events in case of allocation failure
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (6 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 07/18] perf tools: Limit ordered events queue size Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-27 23:07   ` David Ahern
  2014-06-18 14:58 ` [PATCH 09/18] perf tools: Make perf_session_deliver_event global Jiri Olsa
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

In previous patches we added a limit for ordered events
queue allocation size. If we reach this size we need to
flush (part of) the queue to get some free buffers.

The current functionality is not affected, because the
limit is hard coded to (u64) -1. The configuration code
for size will come in following patches.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-kvm.c  |  2 +-
 tools/perf/util/session.c | 28 ++++++++++++++++++++++++++--
 tools/perf/util/session.h |  3 ++-
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index b2f0ddb..b4fd302 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -902,7 +902,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
 			return -1;
 		}
 
-		err = perf_session_queue_event(kvm->session, event, &sample, 0);
+		err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0);
 		/*
 		 * FIXME: Here we can't consume the event, as perf_session_queue_event will
 		 *        point to it, and it'll get possibly overwritten by the kernel.
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5c00d9b..a76cfcf 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -15,6 +15,7 @@
 #include "cpumap.h"
 #include "perf_regs.h"
 #include "vdso.h"
+#include "asm/bug.h"
 
 static int perf_session__open(struct perf_session *session)
 {
@@ -458,6 +459,7 @@ struct ordered_event {
 enum oeq_flush {
 	OEQ_FLUSH__FINAL,
 	OEQ_FLUSH__ROUND,
+	OEQ_FLUSH__HALF,
 };
 
 static void perf_session_free_sample_buffers(struct perf_session *session)
@@ -640,6 +642,22 @@ static int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 		q->next_flush = ULLONG_MAX;
 		break;
 
+	case OEQ_FLUSH__HALF:
+	{
+		struct ordered_event *first, *last;
+		struct list_head *head = &q->events;
+
+		first = list_entry(head->next, struct ordered_event, list);
+		last = q->last;
+
+		if (WARN_ONCE(!last || list_empty(head), "empty queue"))
+			return 0;
+
+		q->next_flush  = first->timestamp;
+		q->next_flush += (last->timestamp - first->timestamp) / 2;
+		break;
+	}
+
 	case OEQ_FLUSH__ROUND:
 	default:
 		break;
@@ -702,7 +720,8 @@ static int process_finished_round(struct perf_tool *tool,
 }
 
 int perf_session_queue_event(struct perf_session *s, union perf_event *event,
-				    struct perf_sample *sample, u64 file_offset)
+			     struct perf_tool *tool, struct perf_sample *sample,
+			     u64 file_offset)
 {
 	struct ordered_events_queue *q = &s->ordered_events;
 	u64 timestamp = sample->time;
@@ -717,6 +736,11 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 	}
 
 	new = ordered_events_get(q, timestamp);
+	if (!new) {
+		ordered_events_flush(s, tool, OEQ_FLUSH__HALF);
+		new = ordered_events_get(q, timestamp);
+	}
+
 	if (!new)
 		return -ENOMEM;
 
@@ -1122,7 +1146,7 @@ static int perf_session__process_event(struct perf_session *session,
 		return ret;
 
 	if (tool->ordered_events) {
-		ret = perf_session_queue_event(session, event, &sample,
+		ret = perf_session_queue_event(session, event, tool, &sample,
 					       file_offset);
 		if (ret != -ETIME)
 			return ret;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 9f64ac9..af38954 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -64,7 +64,8 @@ int perf_session__process_events(struct perf_session *session,
 				 struct perf_tool *tool);
 
 int perf_session_queue_event(struct perf_session *s, union perf_event *event,
-			     struct perf_sample *sample, u64 file_offset);
+			     struct perf_tool *tool, struct perf_sample *sample,
+			     u64 file_offset);
 
 void perf_tool__fill_defaults(struct perf_tool *tool);
 
-- 
1.8.3.1


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

* [PATCH 09/18] perf tools: Make perf_session_deliver_event global
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (7 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 08/18] perf tools: Flush ordered events in case of allocation failure Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 10/18] perf tools: Create ordered-events object Jiri Olsa
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Making perf_session_deliver_event global function, as it will
be called from another object in following patch.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/session.c | 17 +++++------------
 tools/perf/util/session.h |  6 ++++++
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index a76cfcf..cbbd2b4 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -573,13 +573,6 @@ ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
 	q->nr_events--;
 }
 
-
-static int perf_session_deliver_event(struct perf_session *session,
-				      union perf_event *event,
-				      struct perf_sample *sample,
-				      struct perf_tool *tool,
-				      u64 file_offset);
-
 static int __ordered_events_flush(struct perf_session *s,
 				  struct perf_tool *tool)
 {
@@ -1005,11 +998,11 @@ perf_session__deliver_sample(struct perf_session *session,
 					    &sample->read.one, machine);
 }
 
-static int perf_session_deliver_event(struct perf_session *session,
-				      union perf_event *event,
-				      struct perf_sample *sample,
-				      struct perf_tool *tool,
-				      u64 file_offset)
+int perf_session_deliver_event(struct perf_session *session,
+			       union perf_event *event,
+			       struct perf_sample *sample,
+			       struct perf_tool *tool,
+			       u64 file_offset)
 {
 	struct perf_evsel *evsel;
 	struct machine *machine;
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index af38954..58acad4 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -69,6 +69,12 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 
 void perf_tool__fill_defaults(struct perf_tool *tool);
 
+int perf_session_deliver_event(struct perf_session *session,
+			       union perf_event *event,
+			       struct perf_sample *sample,
+			       struct perf_tool *tool,
+			       u64 file_offset);
+
 int perf_session__resolve_callchain(struct perf_session *session,
 				    struct perf_evsel *evsel,
 				    struct thread *thread,
-- 
1.8.3.1


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

* [PATCH 10/18] perf tools: Create ordered-events object
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (8 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 09/18] perf tools: Make perf_session_deliver_event global Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 11/18] perf tools: Use list_move in ordered_event_put function Jiri Olsa
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Move ordered events code into separated object ordered-events.[ch].

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Makefile.perf         |   2 +
 tools/perf/util/ordered-events.c | 195 +++++++++++++++++++++++++++++++++++++
 tools/perf/util/ordered-events.h |  43 ++++++++
 tools/perf/util/session.c        | 205 ---------------------------------------
 tools/perf/util/session.h        |  17 +---
 5 files changed, 241 insertions(+), 221 deletions(-)
 create mode 100644 tools/perf/util/ordered-events.c
 create mode 100644 tools/perf/util/ordered-events.h

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 9670a16..1351cfe 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -263,6 +263,7 @@ LIB_H += util/xyarray.h
 LIB_H += util/header.h
 LIB_H += util/help.h
 LIB_H += util/session.h
+LIB_H += util/ordered-events.h
 LIB_H += util/strbuf.h
 LIB_H += util/strlist.h
 LIB_H += util/strfilter.h
@@ -345,6 +346,7 @@ LIB_OBJS += $(OUTPUT)util/machine.o
 LIB_OBJS += $(OUTPUT)util/map.o
 LIB_OBJS += $(OUTPUT)util/pstack.o
 LIB_OBJS += $(OUTPUT)util/session.o
+LIB_OBJS += $(OUTPUT)util/ordered-events.o
 LIB_OBJS += $(OUTPUT)util/comm.o
 LIB_OBJS += $(OUTPUT)util/thread.o
 LIB_OBJS += $(OUTPUT)util/thread_map.o
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
new file mode 100644
index 0000000..2e89bea
--- /dev/null
+++ b/tools/perf/util/ordered-events.c
@@ -0,0 +1,195 @@
+#include <linux/list.h>
+#include "ordered-events.h"
+#include "evlist.h"
+#include "session.h"
+#include "asm/bug.h"
+
+static void queue_event(struct ordered_events_queue *q, struct ordered_event *new)
+{
+	struct ordered_event *last = q->last;
+	u64 timestamp = new->timestamp;
+	struct list_head *p;
+
+	++q->nr_events;
+	q->last = new;
+
+	if (!last) {
+		list_add(&new->list, &q->events);
+		q->max_timestamp = timestamp;
+		return;
+	}
+
+	/*
+	 * last event might point to some random place in the list as it's
+	 * the last queued event. We expect that the new event is clqe to
+	 * this.
+	 */
+	if (last->timestamp <= timestamp) {
+		while (last->timestamp <= timestamp) {
+			p = last->list.next;
+			if (p == &q->events) {
+				list_add_tail(&new->list, &q->events);
+				q->max_timestamp = timestamp;
+				return;
+			}
+			last = list_entry(p, struct ordered_event, list);
+		}
+		list_add_tail(&new->list, &last->list);
+	} else {
+		while (last->timestamp > timestamp) {
+			p = last->list.prev;
+			if (p == &q->events) {
+				list_add(&new->list, &q->events);
+				return;
+			}
+			last = list_entry(p, struct ordered_event, list);
+		}
+		list_add(&new->list, &last->list);
+	}
+}
+
+#define MAX_SAMPLE_BUFFER	(64 * 1024 / sizeof(struct ordered_event))
+static struct ordered_event *alloc_event(struct ordered_events_queue *q)
+{
+	struct list_head *cache = &q->cache;
+	struct ordered_event *new = NULL;
+
+	if (!list_empty(cache)) {
+		new = list_entry(cache->next, struct ordered_event, list);
+		list_del(&new->list);
+	} else if (q->buffer) {
+		new = q->buffer + q->buffer_idx;
+		if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
+			q->buffer = NULL;
+	} else if (q->cur_alloc_size < q->max_alloc_size) {
+		size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
+
+		q->buffer = malloc(size);
+		if (!q->buffer)
+			return NULL;
+
+		q->cur_alloc_size += size;
+		list_add(&q->buffer->list, &q->to_free);
+
+		/* First entry is abused to maintain the to_free list. */
+		q->buffer_idx = 2;
+		new = q->buffer + 1;
+	}
+
+	return new;
+}
+
+struct ordered_event*
+ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
+{
+	struct ordered_event *new;
+
+	new = alloc_event(q);
+	if (new) {
+		new->timestamp = timestamp;
+		queue_event(q, new);
+	}
+
+	return new;
+}
+
+void
+ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
+{
+	list_del(&iter->list);
+	list_add(&iter->list, &q->cache);
+	q->nr_events--;
+}
+
+static int __ordered_events_flush(struct perf_session *s,
+				  struct perf_tool *tool)
+{
+	struct ordered_events_queue *q = &s->ordered_events;
+	struct list_head *head = &q->events;
+	struct ordered_event *tmp, *iter;
+	struct perf_sample sample;
+	u64 limit = q->next_flush;
+	u64 last_ts = q->last ? q->last->timestamp : 0ULL;
+	bool show_progress = limit == ULLONG_MAX;
+	struct ui_progress prog;
+	int ret;
+
+	if (!tool->ordered_events || !limit)
+		return 0;
+
+	if (show_progress)
+		ui_progress__init(&prog, q->nr_events, "Processing time ordered events...");
+
+	list_for_each_entry_safe(iter, tmp, head, list) {
+		if (session_done())
+			return 0;
+
+		if (iter->timestamp > limit)
+			break;
+
+		ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
+		if (ret)
+			pr_err("Can't parse sample, err = %d\n", ret);
+		else {
+			ret = perf_session_deliver_event(s, iter->event, &sample, tool,
+							 iter->file_offset);
+			if (ret)
+				return ret;
+		}
+
+		ordered_event_put(q, iter);
+		q->last_flush = iter->timestamp;
+
+		if (show_progress)
+			ui_progress__update(&prog, 1);
+	}
+
+	if (list_empty(head))
+		q->last = NULL;
+	else if (last_ts <= limit)
+		q->last = list_entry(head->prev, struct ordered_event, list);
+
+	return 0;
+}
+
+int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
+			 enum oeq_flush how)
+{
+	struct ordered_events_queue *q = &s->ordered_events;
+	int err;
+
+	switch (how) {
+	case OEQ_FLUSH__FINAL:
+		q->next_flush = ULLONG_MAX;
+		break;
+
+	case OEQ_FLUSH__HALF:
+	{
+		struct ordered_event *first, *last;
+		struct list_head *head = &q->events;
+
+		first = list_entry(head->next, struct ordered_event, list);
+		last = q->last;
+
+		if (WARN_ONCE(!last || list_empty(head), "empty queue"))
+			return 0;
+
+		q->next_flush  = first->timestamp;
+		q->next_flush += (last->timestamp - first->timestamp) / 2;
+		break;
+	}
+
+	case OEQ_FLUSH__ROUND:
+	default:
+		break;
+	};
+
+	err = __ordered_events_flush(s, tool);
+
+	if (!err) {
+		if (how == OEQ_FLUSH__ROUND)
+			q->next_flush = q->max_timestamp;
+	}
+
+	return err;
+}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
new file mode 100644
index 0000000..c0dc00e
--- /dev/null
+++ b/tools/perf/util/ordered-events.h
@@ -0,0 +1,43 @@
+#ifndef __ORDERED_EVENTS_H
+#define __ORDERED_EVENTS_H
+
+#include <linux/types.h>
+#include "tool.h"
+
+struct perf_session;
+
+struct ordered_event {
+	u64			timestamp;
+	u64			file_offset;
+	union perf_event	*event;
+	struct list_head	list;
+};
+
+enum oeq_flush {
+	OEQ_FLUSH__FINAL,
+	OEQ_FLUSH__ROUND,
+	OEQ_FLUSH__HALF,
+};
+
+struct ordered_events_queue {
+	u64			last_flush;
+	u64			next_flush;
+	u64			max_timestamp;
+	u64			max_alloc_size;
+	u64			cur_alloc_size;
+	struct list_head	events;
+	struct list_head	cache;
+	struct list_head	to_free;
+	struct ordered_event	*buffer;
+	struct ordered_event	*last;
+	int			buffer_idx;
+	unsigned int		nr_events;
+};
+
+struct ordered_event *ordered_events_get(struct ordered_events_queue *q,
+					 u64 timestamp);
+void ordered_event_put(struct ordered_events_queue *q,
+		       struct ordered_event *iter);
+int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
+			 enum oeq_flush how);
+#endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index cbbd2b4..2b97ada 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -15,7 +15,6 @@
 #include "cpumap.h"
 #include "perf_regs.h"
 #include "vdso.h"
-#include "asm/bug.h"
 
 static int perf_session__open(struct perf_session *session)
 {
@@ -449,19 +448,6 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
-struct ordered_event {
-	u64			timestamp;
-	u64			file_offset;
-	union perf_event	*event;
-	struct list_head	list;
-};
-
-enum oeq_flush {
-	OEQ_FLUSH__FINAL,
-	OEQ_FLUSH__ROUND,
-	OEQ_FLUSH__HALF,
-};
-
 static void perf_session_free_sample_buffers(struct perf_session *session)
 {
 	struct ordered_events_queue *q = &session->ordered_events;
@@ -475,197 +461,6 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
 	}
 }
 
-/* The queue is ordered by time */
-static void queue_event(struct ordered_events_queue *q, struct ordered_event *new)
-{
-	struct ordered_event *last = q->last;
-	u64 timestamp = new->timestamp;
-	struct list_head *p;
-
-	++q->nr_events;
-	q->last = new;
-
-	if (!last) {
-		list_add(&new->list, &q->events);
-		q->max_timestamp = timestamp;
-		return;
-	}
-
-	/*
-	 * last event might point to some random place in the list as it's
-	 * the last queued event. We expect that the new event is clqe to
-	 * this.
-	 */
-	if (last->timestamp <= timestamp) {
-		while (last->timestamp <= timestamp) {
-			p = last->list.next;
-			if (p == &q->events) {
-				list_add_tail(&new->list, &q->events);
-				q->max_timestamp = timestamp;
-				return;
-			}
-			last = list_entry(p, struct ordered_event, list);
-		}
-		list_add_tail(&new->list, &last->list);
-	} else {
-		while (last->timestamp > timestamp) {
-			p = last->list.prev;
-			if (p == &q->events) {
-				list_add(&new->list, &q->events);
-				return;
-			}
-			last = list_entry(p, struct ordered_event, list);
-		}
-		list_add(&new->list, &last->list);
-	}
-}
-
-#define MAX_SAMPLE_BUFFER	(64 * 1024 / sizeof(struct ordered_event))
-static struct ordered_event *alloc_event(struct ordered_events_queue *q)
-{
-	struct list_head *cache = &q->cache;
-	struct ordered_event *new = NULL;
-
-	if (!list_empty(cache)) {
-		new = list_entry(cache->next, struct ordered_event, list);
-		list_del(&new->list);
-	} else if (q->buffer) {
-		new = q->buffer + q->buffer_idx;
-		if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
-			q->buffer = NULL;
-	} else if (q->cur_alloc_size < q->max_alloc_size) {
-		size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
-
-		q->buffer = malloc(size);
-		if (!q->buffer)
-			return NULL;
-
-		q->cur_alloc_size += size;
-		list_add(&q->buffer->list, &q->to_free);
-
-		/* First entry is abused to maintain the to_free list. */
-		q->buffer_idx = 2;
-		new = q->buffer + 1;
-	}
-
-	return new;
-}
-
-static struct ordered_event*
-ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
-{
-	struct ordered_event *new;
-
-	new = alloc_event(q);
-	if (new) {
-		new->timestamp = timestamp;
-		queue_event(q, new);
-	}
-
-	return new;
-}
-
-static void
-ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
-{
-	list_del(&iter->list);
-	list_add(&iter->list, &q->cache);
-	q->nr_events--;
-}
-
-static int __ordered_events_flush(struct perf_session *s,
-				  struct perf_tool *tool)
-{
-	struct ordered_events_queue *q = &s->ordered_events;
-	struct list_head *head = &q->events;
-	struct ordered_event *tmp, *iter;
-	struct perf_sample sample;
-	u64 limit = q->next_flush;
-	u64 last_ts = q->last ? q->last->timestamp : 0ULL;
-	bool show_progress = limit == ULLONG_MAX;
-	struct ui_progress prog;
-	int ret;
-
-	if (!tool->ordered_events || !limit)
-		return 0;
-
-	if (show_progress)
-		ui_progress__init(&prog, q->nr_events, "Processing time ordered events...");
-
-	list_for_each_entry_safe(iter, tmp, head, list) {
-		if (session_done())
-			return 0;
-
-		if (iter->timestamp > limit)
-			break;
-
-		ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
-		if (ret)
-			pr_err("Can't parse sample, err = %d\n", ret);
-		else {
-			ret = perf_session_deliver_event(s, iter->event, &sample, tool,
-							 iter->file_offset);
-			if (ret)
-				return ret;
-		}
-
-		ordered_event_put(q, iter);
-		q->last_flush = iter->timestamp;
-
-		if (show_progress)
-			ui_progress__update(&prog, 1);
-	}
-
-	if (list_empty(head))
-		q->last = NULL;
-	else if (last_ts <= limit)
-		q->last = list_entry(head->prev, struct ordered_event, list);
-
-	return 0;
-}
-
-static int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
-				enum oeq_flush how)
-{
-	struct ordered_events_queue *q = &s->ordered_events;
-	int err;
-
-	switch (how) {
-	case OEQ_FLUSH__FINAL:
-		q->next_flush = ULLONG_MAX;
-		break;
-
-	case OEQ_FLUSH__HALF:
-	{
-		struct ordered_event *first, *last;
-		struct list_head *head = &q->events;
-
-		first = list_entry(head->next, struct ordered_event, list);
-		last = q->last;
-
-		if (WARN_ONCE(!last || list_empty(head), "empty queue"))
-			return 0;
-
-		q->next_flush  = first->timestamp;
-		q->next_flush += (last->timestamp - first->timestamp) / 2;
-		break;
-	}
-
-	case OEQ_FLUSH__ROUND:
-	default:
-		break;
-	};
-
-	err = __ordered_events_flush(s, tool);
-
-	if (!err) {
-		if (how == OEQ_FLUSH__ROUND)
-			q->next_flush = q->max_timestamp;
-	}
-
-	return err;
-}
-
 /*
  * When perf record finishes a pass on every buffers, it records this pseudo
  * event.
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 58acad4..f8dcbf9 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -9,28 +9,13 @@
 #include "symbol.h"
 #include "thread.h"
 #include "data.h"
+#include "ordered-events.h"
 #include <linux/rbtree.h>
 #include <linux/perf_event.h>
 
-struct ordered_event;
 struct ip_callchain;
 struct thread;
 
-struct ordered_events_queue {
-	u64			last_flush;
-	u64			next_flush;
-	u64			max_timestamp;
-	u64			max_alloc_size;
-	u64			cur_alloc_size;
-	struct list_head	events;
-	struct list_head	cache;
-	struct list_head	to_free;
-	struct ordered_event	*buffer;
-	struct ordered_event	*last;
-	int			buffer_idx;
-	unsigned int		nr_events;
-};
-
 struct perf_session {
 	struct perf_header		header;
 	struct machines			machines;
-- 
1.8.3.1


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

* [PATCH 11/18] perf tools: Use list_move in ordered_event_put function
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (9 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 10/18] perf tools: Create ordered-events object Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 12/18] perf tools: Add ordered_events_queue_init function Jiri Olsa
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

As Namhyung pointed out we can use list_move in ordered_event_put.

Suggested-by: Namhyung Kim <namhyung@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/ordered-events.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index 2e89bea..022be55 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -96,8 +96,7 @@ ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
 void
 ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
 {
-	list_del(&iter->list);
-	list_add(&iter->list, &q->cache);
+	list_move(&iter->list, &q->cache);
 	q->nr_events--;
 }
 
-- 
1.8.3.1


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

* [PATCH 12/18] perf tools: Add ordered_events_queue_init function
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (10 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 11/18] perf tools: Use list_move in ordered_event_put function Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 13/18] perf tools: Add ordered_events_queue_free function Jiri Olsa
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Adding ordered_events_queue_init function for struct
ordered_events_queue initialization.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/ordered-events.c | 9 +++++++++
 tools/perf/util/ordered-events.h | 1 +
 tools/perf/util/session.c        | 6 +-----
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index 022be55..42b1bbc 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -192,3 +192,12 @@ int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 
 	return err;
 }
+
+void ordered_events_queue_init(struct ordered_events_queue *q)
+{
+	INIT_LIST_HEAD(&q->events);
+	INIT_LIST_HEAD(&q->cache);
+	INIT_LIST_HEAD(&q->to_free);
+	q->max_alloc_size = (u64) -1;
+	q->cur_alloc_size = 0;
+}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index c0dc00e..0633b09 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -40,4 +40,5 @@ void ordered_event_put(struct ordered_events_queue *q,
 		       struct ordered_event *iter);
 int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 			 enum oeq_flush how);
+void ordered_events_queue_init(struct ordered_events_queue *q);
 #endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 2b97ada..59d13a7 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -76,11 +76,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
 		goto out;
 
 	session->repipe = repipe;
-	INIT_LIST_HEAD(&session->ordered_events.events);
-	INIT_LIST_HEAD(&session->ordered_events.cache);
-	INIT_LIST_HEAD(&session->ordered_events.to_free);
-	session->ordered_events.max_alloc_size = (u64) -1;
-	session->ordered_events.cur_alloc_size = 0;
+	ordered_events_queue_init(&session->ordered_events);
 	machines__init(&session->machines);
 
 	if (file) {
-- 
1.8.3.1


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

* [PATCH 13/18] perf tools: Add ordered_events_queue_free function
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (11 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 12/18] perf tools: Add ordered_events_queue_init function Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 14/18] perf tools: Add perf_config_u64 function Jiri Olsa
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Adding ordered_events_queue_free function to release all
the struct ordered_events_queue data. It's replacement
for former perf_session_free_sample_buffers function.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/ordered-events.c | 11 +++++++++++
 tools/perf/util/ordered-events.h |  1 +
 tools/perf/util/session.c        | 17 ++---------------
 3 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index 42b1bbc..946619c 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -201,3 +201,14 @@ void ordered_events_queue_init(struct ordered_events_queue *q)
 	q->max_alloc_size = (u64) -1;
 	q->cur_alloc_size = 0;
 }
+
+void ordered_events_queue_free(struct ordered_events_queue *q)
+{
+	while (!list_empty(&q->to_free)) {
+		struct ordered_event *event;
+
+		event = list_entry(q->to_free.next, struct ordered_event, list);
+		list_del(&event->list);
+		free(event);
+	}
+}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 0633b09..25ec273 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -41,4 +41,5 @@ void ordered_event_put(struct ordered_events_queue *q,
 int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 			 enum oeq_flush how);
 void ordered_events_queue_init(struct ordered_events_queue *q);
+void ordered_events_queue_free(struct ordered_events_queue *q);
 #endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 59d13a7..28fe6a1 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -444,19 +444,6 @@ static perf_event__swap_op perf_event__swap_ops[] = {
 	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
-static void perf_session_free_sample_buffers(struct perf_session *session)
-{
-	struct ordered_events_queue *q = &session->ordered_events;
-
-	while (!list_empty(&q->to_free)) {
-		struct ordered_event *sq;
-
-		sq = list_entry(q->to_free.next, struct ordered_event, list);
-		list_del(&sq->list);
-		free(sq);
-	}
-}
-
 /*
  * When perf record finishes a pass on every buffers, it records this pseudo
  * event.
@@ -1092,7 +1079,7 @@ done:
 out_err:
 	free(buf);
 	perf_session__warn_about_errors(session, tool);
-	perf_session_free_sample_buffers(session);
+	ordered_events_queue_free(&session->ordered_events);
 	return err;
 }
 
@@ -1227,7 +1214,7 @@ out:
 out_err:
 	ui_progress__finish();
 	perf_session__warn_about_errors(session, tool);
-	perf_session_free_sample_buffers(session);
+	ordered_events_queue_free(&session->ordered_events);
 	return err;
 }
 
-- 
1.8.3.1


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

* [PATCH 14/18] perf tools: Add perf_config_u64 function
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (12 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 13/18] perf tools: Add ordered_events_queue_free function Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-27 23:08   ` David Ahern
  2014-06-18 14:58 ` [PATCH 15/18] perf tools: Add report.queue-size config file option Jiri Olsa
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra, Jiri Olsa

From: Jiri Olsa <jolsa@redhat.com>

Adding perf_config_u64 function to be able to parse
'llong' values out of config file.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/cache.h  |  1 +
 tools/perf/util/config.c | 24 ++++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 7b176dd..5cf9e1b 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -22,6 +22,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int perf_default_config(const char *, const char *, void *);
 extern int perf_config(config_fn_t fn, void *);
 extern int perf_config_int(const char *, const char *);
+extern u64 perf_config_u64(const char *, const char *);
 extern int perf_config_bool(const char *, const char *);
 extern int config_error_nonbool(const char *);
 extern const char *perf_config_dirname(const char *, const char *);
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 24519e1..27ad81c 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -286,6 +286,21 @@ static int parse_unit_factor(const char *end, unsigned long *val)
 	return 0;
 }
 
+static int perf_parse_llong(const char *value, long long *ret)
+{
+	if (value && *value) {
+		char *end;
+		long long val = strtoll(value, &end, 0);
+		unsigned long factor = 1;
+
+		if (!parse_unit_factor(end, &factor))
+			return 0;
+		*ret = val * factor;
+		return 1;
+	}
+	return 0;
+}
+
 static int perf_parse_long(const char *value, long *ret)
 {
 	if (value && *value) {
@@ -307,6 +322,15 @@ static void die_bad_config(const char *name)
 	die("bad config value for '%s'", name);
 }
 
+u64 perf_config_u64(const char *name, const char *value)
+{
+	long long ret = 0;
+
+	if (!perf_parse_llong(value, &ret))
+		die_bad_config(name);
+	return (u64) ret;
+}
+
 int perf_config_int(const char *name, const char *value)
 {
 	long ret = 0;
-- 
1.8.3.1


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

* [PATCH 15/18] perf tools: Add report.queue-size config file option
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (13 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 14/18] perf tools: Add perf_config_u64 function Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 16/18] perf tools: Add debug prints for ordered events queue Jiri Olsa
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Adding report.queue-size config file option to setup
the maximum allocation size for session's struct
ordered_events_queue object.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-report.c      | 13 ++++++++++++-
 tools/perf/util/ordered-events.h |  6 ++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c72cc5a..09b9d0c 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -58,17 +58,19 @@ struct report {
 	const char		*symbol_filter_str;
 	float			min_percent;
 	u64			nr_entries;
+	u64			queue_size;
 	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
 
 static int report__config(const char *var, const char *value, void *cb)
 {
+	struct report *rep = cb;
+
 	if (!strcmp(var, "report.group")) {
 		symbol_conf.event_group = perf_config_bool(var, value);
 		return 0;
 	}
 	if (!strcmp(var, "report.percent-limit")) {
-		struct report *rep = cb;
 		rep->min_percent = strtof(value, NULL);
 		return 0;
 	}
@@ -76,6 +78,10 @@ static int report__config(const char *var, const char *value, void *cb)
 		symbol_conf.cumulate_callchain = perf_config_bool(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "report.queue-size")) {
+		rep->queue_size = perf_config_u64(var, value);
+		return 0;
+	}
 
 	return perf_default_config(var, value, cb);
 }
@@ -714,6 +720,11 @@ repeat:
 	if (session == NULL)
 		return -ENOMEM;
 
+	if (report.queue_size) {
+		ordered_events_queue_alloc_size(&session->ordered_events,
+						report.queue_size);
+	}
+
 	report.session = session;
 
 	has_br_stack = perf_header__has_feat(&session->header,
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 25ec273..04cb295 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -42,4 +42,10 @@ int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 			 enum oeq_flush how);
 void ordered_events_queue_init(struct ordered_events_queue *q);
 void ordered_events_queue_free(struct ordered_events_queue *q);
+
+static inline void
+ordered_events_queue_alloc_size(struct ordered_events_queue *q, u64 size)
+{
+	q->max_alloc_size = size;
+}
 #endif /* __ORDERED_EVENTS_H */
-- 
1.8.3.1


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

* [PATCH 16/18] perf tools: Add debug prints for ordered events queue
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (14 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 15/18] perf tools: Add report.queue-size config file option Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-28  2:52   ` David Ahern
  2014-06-18 14:58 ` [PATCH 17/18] perf tools: Limit the ordered events queue by default to 100MB Jiri Olsa
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Adding some prints for ordered events queue, to help
debug issues.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-report.c      |  4 +++
 tools/perf/util/ordered-events.c | 54 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/ordered-events.h |  2 ++
 3 files changed, 60 insertions(+)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 09b9d0c..130ab5c 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -82,6 +82,10 @@ static int report__config(const char *var, const char *value, void *cb)
 		rep->queue_size = perf_config_u64(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "report.queue-debug")) {
+		debug_sample_queue = perf_config_int(var, value);
+		return 0;
+	}
 
 	return perf_default_config(var, value, cb);
 }
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index 946619c..662ee0c 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -4,6 +4,37 @@
 #include "session.h"
 #include "asm/bug.h"
 
+int debug_sample_queue;
+
+static int pr_level(int level, const char *fmt, ...)
+{
+	int ret = 0;
+
+	if (unlikely(debug_sample_queue >= level)) {
+		va_list args;
+
+		va_start(args, fmt);
+		ret = vfprintf(stderr, fmt, args);
+		va_end(args);
+	}
+
+	return ret;
+}
+
+#define pr_N(n, fmt, ...) \
+	pr_level(n, fmt, ##__VA_ARGS__)
+#define pr(fmt, ...)  pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
+
+static int pr_time(const char *str, u64 time)
+{
+	u64 secs, usecs, nsecs = time;
+
+	secs = nsecs / NSECS_PER_SEC;
+	nsecs -= secs * NSECS_PER_SEC;
+	usecs = nsecs / NSECS_PER_USEC;
+	return fprintf(stderr, "\t[%13lu.%06lu] %s\n", secs, usecs, str);
+}
+
 static void queue_event(struct ordered_events_queue *q, struct ordered_event *new)
 {
 	struct ordered_event *last = q->last;
@@ -68,6 +99,9 @@ static struct ordered_event *alloc_event(struct ordered_events_queue *q)
 		if (!q->buffer)
 			return NULL;
 
+		pr("alloc size %" PRIu64 "B, max %" PRIu64 "B\n",
+		   q->cur_alloc_size, q->max_alloc_size);
+
 		q->cur_alloc_size += size;
 		list_add(&q->buffer->list, &q->to_free);
 
@@ -183,6 +217,19 @@ int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 		break;
 	};
 
+	if (unlikely(debug_sample_queue)) {
+		static const char * const str[] = {
+			"FINAL",
+			"ROUND",
+			"HALF ",
+		};
+
+		fprintf(stderr, "ordered_events_flush %s, nr_events %u\n",
+			str[how], q->nr_events);
+		pr_time("next_flush",    q->next_flush);
+		pr_time("max_timestamp", q->max_timestamp);
+	}
+
 	err = __ordered_events_flush(s, tool);
 
 	if (!err) {
@@ -190,6 +237,13 @@ int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 			q->next_flush = q->max_timestamp;
 	}
 
+	if (unlikely(debug_sample_queue)) {
+		fprintf(stderr, "ordered_events_flush nr_events %u\n",
+			q->nr_events);
+		pr_time("next_flush", q->next_flush);
+		pr_time("last_flush", q->last_flush);
+	}
+
 	return err;
 }
 
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 04cb295..8a717de 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -48,4 +48,6 @@ ordered_events_queue_alloc_size(struct ordered_events_queue *q, u64 size)
 {
 	q->max_alloc_size = size;
 }
+
+extern int debug_sample_queue;
 #endif /* __ORDERED_EVENTS_H */
-- 
1.8.3.1


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

* [PATCH 17/18] perf tools: Limit the ordered events queue by default to 100MB
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (15 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 16/18] perf tools: Add debug prints for ordered events queue Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 14:58 ` [PATCH 18/18] perf tools: Allow out of order messages in forced flush Jiri Olsa
  2014-06-18 19:44 ` [PATCHv2 00/18] perf tools: Factor ordered samples queue David Ahern
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

It's still configurable by report.queue-size config option,
but looks like 100MB limit is more sane than no limit at all.

There's some speedup for report on huge data files:

With the limit of 100 MB, I've got around 15% speedup on reporting
of ~10GB perf.data file.

  current code:
   621,685,704,665      cycles                    ( +-  0.52% )
   873,397,467,969      instructions              ( +-  0.00% )

     286.133268732 seconds time elapsed           ( +-  1.13% )

  with patches:
   603,933,987,185      cycles                    ( +-  0.45% )
   869,139,445,070      instructions              ( +-  0.00% )

     245.337510637 seconds time elapsed           ( +-  0.49% )

The speed up seems to be mainly in less cycles spent in servicing
page faults.

  current code:
     4.44%     0.01%  perf.old  [kernel.kallsyms]   [k] page_fault

  with patches:
     1.45%     0.00%      perf  [kernel.kallsyms]   [k] page_fault

  current code (faults event):
         6,643,807      faults                    ( +-  0.36% )

  with patches (faults event):
         2,214,756      faults                    ( +-  3.03% )

Also there's lower memory consuption.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/ordered-events.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index 662ee0c..aa98b6a 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -252,7 +252,8 @@ void ordered_events_queue_init(struct ordered_events_queue *q)
 	INIT_LIST_HEAD(&q->events);
 	INIT_LIST_HEAD(&q->cache);
 	INIT_LIST_HEAD(&q->to_free);
-	q->max_alloc_size = (u64) -1;
+	/* 100MB limitation by default */
+	q->max_alloc_size = 100 * 1024 * 1024;
 	q->cur_alloc_size = 0;
 }
 
-- 
1.8.3.1


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

* [PATCH 18/18] perf tools: Allow out of order messages in forced flush
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (16 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 17/18] perf tools: Limit the ordered events queue by default to 100MB Jiri Olsa
@ 2014-06-18 14:58 ` Jiri Olsa
  2014-06-18 19:44 ` [PATCHv2 00/18] perf tools: Factor ordered samples queue David Ahern
  18 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-18 14:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

In forced flush (OEQ_FLUSH__HALF) we break the rules of the
flush timestamp via PERF_RECORD_FINISHED_ROUND event, so
we could get out of order event.

Do not force error in this case and also changing the
output warning to use WARN_ONCE.

Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jean Pihet <jean.pihet@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/ordered-events.c | 4 ++++
 tools/perf/util/ordered-events.h | 2 ++
 tools/perf/util/session.c        | 8 ++++++--
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index aa98b6a..bfaf065 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -213,12 +213,14 @@ int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 	}
 
 	case OEQ_FLUSH__ROUND:
+	case OEQ_FLUSH__NONE:
 	default:
 		break;
 	};
 
 	if (unlikely(debug_sample_queue)) {
 		static const char * const str[] = {
+			"NONE",
 			"FINAL",
 			"ROUND",
 			"HALF ",
@@ -235,6 +237,8 @@ int ordered_events_flush(struct perf_session *s, struct perf_tool *tool,
 	if (!err) {
 		if (how == OEQ_FLUSH__ROUND)
 			q->next_flush = q->max_timestamp;
+
+		q->last_flush_type = how;
 	}
 
 	if (unlikely(debug_sample_queue)) {
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 8a717de..7e92688 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -14,6 +14,7 @@ struct ordered_event {
 };
 
 enum oeq_flush {
+	OEQ_FLUSH__NONE,
 	OEQ_FLUSH__FINAL,
 	OEQ_FLUSH__ROUND,
 	OEQ_FLUSH__HALF,
@@ -32,6 +33,7 @@ struct ordered_events_queue {
 	struct ordered_event	*last;
 	int			buffer_idx;
 	unsigned int		nr_events;
+	enum oeq_flush		last_flush_type;
 };
 
 struct ordered_event *ordered_events_get(struct ordered_events_queue *q,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 28fe6a1..337a783 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -15,6 +15,7 @@
 #include "cpumap.h"
 #include "perf_regs.h"
 #include "vdso.h"
+#include "asm/bug.h"
 
 static int perf_session__open(struct perf_session *session)
 {
@@ -502,8 +503,11 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
 		return -ETIME;
 
 	if (timestamp < s->ordered_events.last_flush) {
-		printf("Warning: Timestamp below last timeslice flush\n");
-		return -EINVAL;
+		WARN_ONCE(1, "Timestamp below last timeslice flush\n");
+
+		/* We could get out of order messages after forced flush. */
+		if (q->last_flush_type != OEQ_FLUSH__HALF)
+			return -EINVAL;
 	}
 
 	new = ordered_events_get(q, timestamp);
-- 
1.8.3.1


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

* Re: [PATCHv2 00/18] perf tools: Factor ordered samples queue
  2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
                   ` (17 preceding siblings ...)
  2014-06-18 14:58 ` [PATCH 18/18] perf tools: Allow out of order messages in forced flush Jiri Olsa
@ 2014-06-18 19:44 ` David Ahern
  2014-06-19 10:34   ` Jiri Olsa
  18 siblings, 1 reply; 37+ messages in thread
From: David Ahern @ 2014-06-18 19:44 UTC (permalink / raw)
  To: Jiri Olsa, linux-kernel
  Cc: Arnaldo Carvalho de Melo, Corey Ashford, Frederic Weisbecker,
	Ingo Molnar, Jean Pihet, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> hi,
> this patchset factors session's ordered samples queue,
> and allows to limit the size of this queue.
>
> v2 changes:
>    - several small changes for review comments (Namhyung)
>
>
> The report command queues events till any of following
> conditions is reached:
>    - PERF_RECORD_FINISHED_ROUND event is processed
>    - end of the file is reached
>
> Any of above conditions will force the queue to flush some
> events while keeping all allocated memory for next events.
>
> If PERF_RECORD_FINISHED_ROUND is missing the queue will
> allocate memory for every single event in the perf.data.
> This could lead to enormous memory consuption and speed
> degradation of report command for huge perf.data files.
>
> With the quue allocation limit of 100 MB, I've got around
> 15% speedup on reporting of ~10GB perf.data file.
>
> current code:
>   Performance counter stats for './perf.old report --stdio -i perf-test.data' (3 runs):
>
>     621,685,704,665      cycles                    ( +-  0.52% )
>     873,397,467,969      instructions              ( +-  0.00% )
>
>       286.133268732 seconds time elapsed           ( +-  1.13% )
>
> with patches:
>   Performance counter stats for './perf report --stdio -i perf-test.data' (3 runs):
>
>     603,933,987,185      cycles                    ( +-  0.45% )
>     869,139,445,070      instructions              ( +-  0.00% )
>
>       245.337510637 seconds time elapsed           ( +-  0.49% )
>
>
> The speed up seems to be mainly in less cycles spent in servicing
> page faults:
>
> current code:
>       4.44%     0.01%  perf.old  [kernel.kallsyms]   [k] page_fault
>
> with patches:
>       1.45%     0.00%      perf  [kernel.kallsyms]   [k] page_fault
>
> current code (faults event):
>           6,643,807      faults                    ( +-  0.36% )
>
> with patches (faults event):
>           2,214,756      faults                    ( +-  3.03% )
>
>
> Also now we have one of our big memory spender under control
> and the ordered events queue code is put in separated object
> with clear interface ready to be used by another command
> like script.
>
> Also reachable in here:
>    git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
>    perf/core_ordered_events
>

I've skimmed through the patches. What happens if you are in the middle 
of a round and the max queue size is reached?

I need to find some time for a detailed review, and to run through some 
stress case scenarios. e.g., a couple that come to mind
perf sched record -- perf bench sched pipe
perf kvm record while booting a nested VM which causes a lot of VMEXITs

David


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

* Re: [PATCHv2 00/18] perf tools: Factor ordered samples queue
  2014-06-18 19:44 ` [PATCHv2 00/18] perf tools: Factor ordered samples queue David Ahern
@ 2014-06-19 10:34   ` Jiri Olsa
  2014-06-19 17:54     ` David Ahern
  0 siblings, 1 reply; 37+ messages in thread
From: Jiri Olsa @ 2014-06-19 10:34 UTC (permalink / raw)
  To: David Ahern
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On Wed, Jun 18, 2014 at 01:44:46PM -0600, David Ahern wrote:

SNIP

> >
> >Also now we have one of our big memory spender under control
> >and the ordered events queue code is put in separated object
> >with clear interface ready to be used by another command
> >like script.
> >
> >Also reachable in here:
> >   git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
> >   perf/core_ordered_events
> >
> 
> I've skimmed through the patches. What happens if you are in the middle of a
> round and the max queue size is reached?

half of the queue (time half) is flushed to make some free space

> I need to find some time for a detailed review, and to run through some
> stress case scenarios. e.g., a couple that come to mind
> perf sched record -- perf bench sched pipe
> perf kvm record while booting a nested VM which causes a lot of VMEXITs

will try.. at least the first one ;-)

thanks for looking on this,
jirka

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

* Re: [PATCHv2 00/18] perf tools: Factor ordered samples queue
  2014-06-19 10:34   ` Jiri Olsa
@ 2014-06-19 17:54     ` David Ahern
  2014-06-20  7:15       ` Jiri Olsa
  0 siblings, 1 reply; 37+ messages in thread
From: David Ahern @ 2014-06-19 17:54 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On 6/19/14, 4:34 AM, Jiri Olsa wrote:
>> I've skimmed through the patches. What happens if you are in the middle of a
>> round and the max queue size is reached?
>
> half of the queue (time half) is flushed to make some free space

right, I believe there will be scenarios where that will cause failures 
with out of order timestamps.

David

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

* Re: [PATCHv2 00/18] perf tools: Factor ordered samples queue
  2014-06-19 17:54     ` David Ahern
@ 2014-06-20  7:15       ` Jiri Olsa
  0 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-20  7:15 UTC (permalink / raw)
  To: David Ahern
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On Thu, Jun 19, 2014 at 11:54:40AM -0600, David Ahern wrote:
> On 6/19/14, 4:34 AM, Jiri Olsa wrote:
> >>I've skimmed through the patches. What happens if you are in the middle of a
> >>round and the max queue size is reached?
> >
> >half of the queue (time half) is flushed to make some free space
> 
> right, I believe there will be scenarios where that will cause failures with
> out of order timestamps.

yep, but I did not hit any so far.. thats why I added
patch 18 - not to drop out of seq. event if it's found
after this flush

jirka

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

* Re: [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface
  2014-06-18 14:58 ` [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface Jiri Olsa
@ 2014-06-27 23:06   ` David Ahern
  2014-06-29 16:39     ` Jiri Olsa
  0 siblings, 1 reply; 37+ messages in thread
From: David Ahern @ 2014-06-27 23:06 UTC (permalink / raw)
  To: Jiri Olsa, linux-kernel
  Cc: Arnaldo Carvalho de Melo, Corey Ashford, Frederic Weisbecker,
	Ingo Molnar, Jean Pihet, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

On 6/18/14, 8:58 AM, Jiri Olsa wrote:
>
> +static struct ordered_event*
> +ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
> +{
> +	struct ordered_event *new;
> +
> +	new = alloc_event(q);
> +	if (new) {
> +		new->timestamp = timestamp;
> +		queue_event(q, new);
> +	}
> +
> +	return new;
> +}

The _get name does not really correlate with what is happening -- ie., 
allocate a new event and add it to the queue. There is no reference 
taken either.

> +
> +static void
> +ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
> +{
> +	list_del(&iter->list);
> +	list_add(&iter->list, &q->cache);
> +	q->nr_events--;
> +}

Similarly here with the _put. In this case the function is moving the 
event from one list to another. And how about something else for the 
name besides iter -- oe, or oevent?

David


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

* Re: [PATCH 08/18] perf tools: Flush ordered events in case of allocation failure
  2014-06-18 14:58 ` [PATCH 08/18] perf tools: Flush ordered events in case of allocation failure Jiri Olsa
@ 2014-06-27 23:07   ` David Ahern
  2014-06-29 16:41     ` Jiri Olsa
  0 siblings, 1 reply; 37+ messages in thread
From: David Ahern @ 2014-06-27 23:07 UTC (permalink / raw)
  To: Jiri Olsa, linux-kernel
  Cc: Arnaldo Carvalho de Melo, Corey Ashford, Frederic Weisbecker,
	Ingo Molnar, Jean Pihet, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> +	case OEQ_FLUSH__HALF:
> +	{
> +		struct ordered_event *first, *last;
> +		struct list_head *head = &q->events;
> +
> +		first = list_entry(head->next, struct ordered_event, list);
> +		last = q->last;
> +
> +		if (WARN_ONCE(!last || list_empty(head), "empty queue"))
> +			return 0;

Maybe a comment that the WARN_ONCE can only happen if perf can't 
allocate an ordered event the first time through?

> +
> +		q->next_flush  = first->timestamp;
> +		q->next_flush += (last->timestamp - first->timestamp) / 2;
> +		break;
> +	}
> +


David

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

* Re: [PATCH 14/18] perf tools: Add perf_config_u64 function
  2014-06-18 14:58 ` [PATCH 14/18] perf tools: Add perf_config_u64 function Jiri Olsa
@ 2014-06-27 23:08   ` David Ahern
  2014-06-29 16:44     ` Jiri Olsa
  0 siblings, 1 reply; 37+ messages in thread
From: David Ahern @ 2014-06-27 23:08 UTC (permalink / raw)
  To: Jiri Olsa, linux-kernel
  Cc: Jiri Olsa, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On 6/18/14, 8:58 AM, Jiri Olsa wrote:

> @@ -307,6 +322,15 @@ static void die_bad_config(const char *name)
>   	die("bad config value for '%s'", name);
>   }
>
> +u64 perf_config_u64(const char *name, const char *value)
> +{
> +	long long ret = 0;
> +
> +	if (!perf_parse_llong(value, &ret))
> +		die_bad_config(name);
> +	return (u64) ret;


Thought we were not using the die functions any longer?

David

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

* Re: [PATCH 07/18] perf tools: Limit ordered events queue size
  2014-06-18 14:58 ` [PATCH 07/18] perf tools: Limit ordered events queue size Jiri Olsa
@ 2014-06-27 23:11   ` David Ahern
  2014-06-30 17:58     ` Jiri Olsa
  0 siblings, 1 reply; 37+ messages in thread
From: David Ahern @ 2014-06-27 23:11 UTC (permalink / raw)
  To: Jiri Olsa, linux-kernel
  Cc: Arnaldo Carvalho de Melo, Corey Ashford, Frederic Weisbecker,
	Ingo Molnar, Jean Pihet, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> @@ -520,7 +522,7 @@ static void queue_event(struct ordered_events_queue *q, struct ordered_event *ne
>   static struct ordered_event *alloc_event(struct ordered_events_queue *q)
>   {
>   	struct list_head *cache = &q->cache;
> -	struct ordered_event *new;
> +	struct ordered_event *new = NULL;
>
>   	if (!list_empty(cache)) {
>   		new = list_entry(cache->next, struct ordered_event, list);
> @@ -529,10 +531,14 @@ static struct ordered_event *alloc_event(struct ordered_events_queue *q)
>   		new = q->buffer + q->buffer_idx;
>   		if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
>   			q->buffer = NULL;
> -	} else {
> -		q->buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
> +	} else if (q->cur_alloc_size < q->max_alloc_size) {
> +		size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
> +
> +		q->buffer = malloc(size);
>   		if (!q->buffer)
>   			return NULL;
> +
> +		q->cur_alloc_size += size;
>   		list_add(&q->buffer->list, &q->to_free);
>

When is cur_alloc_size decremented?

$ git checkout remotes/jolsa/perf/core_ordered_events

$ egrep -r cur_alloc_size tools/perf/
tools/perf//util/ordered-events.c:	} else if (q->cur_alloc_size < 
q->max_alloc_size) {
tools/perf//util/ordered-events.c:		   q->cur_alloc_size, 
q->max_alloc_size);
tools/perf//util/ordered-events.c:		q->cur_alloc_size += size;
tools/perf//util/ordered-events.c:	q->cur_alloc_size = 0;
tools/perf//util/ordered-events.h:	u64			cur_alloc_size;

Does not appear to ever be decremented.

David


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

* Re: [PATCH 16/18] perf tools: Add debug prints for ordered events queue
  2014-06-18 14:58 ` [PATCH 16/18] perf tools: Add debug prints for ordered events queue Jiri Olsa
@ 2014-06-28  2:52   ` David Ahern
  2014-06-29 16:46     ` Jiri Olsa
  0 siblings, 1 reply; 37+ messages in thread
From: David Ahern @ 2014-06-28  2:52 UTC (permalink / raw)
  To: Jiri Olsa, linux-kernel
  Cc: Arnaldo Carvalho de Melo, Corey Ashford, Frederic Weisbecker,
	Ingo Molnar, Jean Pihet, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra

On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> Adding some prints for ordered events queue, to help
> debug issues.

went to enable this and it is really odd to have to edit a config file 
to enable debugging. How about hooking it into verbose option? Maybe 
like multiple levels of -v or -v <val> or -v queue.

David

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

* Re: [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface
  2014-06-27 23:06   ` David Ahern
@ 2014-06-29 16:39     ` Jiri Olsa
  2014-06-29 16:50       ` David Ahern
  2014-06-30 15:03       ` Arnaldo Carvalho de Melo
  0 siblings, 2 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-29 16:39 UTC (permalink / raw)
  To: David Ahern
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On Fri, Jun 27, 2014 at 05:06:36PM -0600, David Ahern wrote:
> On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> >
> >+static struct ordered_event*
> >+ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
> >+{
> >+	struct ordered_event *new;
> >+
> >+	new = alloc_event(q);
> >+	if (new) {
> >+		new->timestamp = timestamp;
> >+		queue_event(q, new);
> >+	}
> >+
> >+	return new;
> >+}
> 
> The _get name does not really correlate with what is happening -- ie.,
> allocate a new event and add it to the queue. There is no reference taken
> either.

ook.. so how about ordered_events_alloc ordered_events_free

> 
> >+
> >+static void
> >+ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
> >+{
> >+	list_del(&iter->list);
> >+	list_add(&iter->list, &q->cache);
> >+	q->nr_events--;
> >+}
> 
> Similarly here with the _put. In this case the function is moving the event
> from one list to another. And how about something else for the name besides
> iter -- oe, or oevent?

how about 'event' ?

jirka

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

* Re: [PATCH 08/18] perf tools: Flush ordered events in case of allocation failure
  2014-06-27 23:07   ` David Ahern
@ 2014-06-29 16:41     ` Jiri Olsa
  0 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-29 16:41 UTC (permalink / raw)
  To: David Ahern
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On Fri, Jun 27, 2014 at 05:07:52PM -0600, David Ahern wrote:
> On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> >+	case OEQ_FLUSH__HALF:
> >+	{
> >+		struct ordered_event *first, *last;
> >+		struct list_head *head = &q->events;
> >+
> >+		first = list_entry(head->next, struct ordered_event, list);
> >+		last = q->last;
> >+
> >+		if (WARN_ONCE(!last || list_empty(head), "empty queue"))
> >+			return 0;
> 
> Maybe a comment that the WARN_ONCE can only happen if perf can't allocate an
> ordered event the first time through?

ok, will do..

thanks,
jirka

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

* Re: [PATCH 14/18] perf tools: Add perf_config_u64 function
  2014-06-27 23:08   ` David Ahern
@ 2014-06-29 16:44     ` Jiri Olsa
  0 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-29 16:44 UTC (permalink / raw)
  To: David Ahern
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On Fri, Jun 27, 2014 at 05:08:03PM -0600, David Ahern wrote:
> On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> 
> >@@ -307,6 +322,15 @@ static void die_bad_config(const char *name)
> >  	die("bad config value for '%s'", name);
> >  }
> >
> >+u64 perf_config_u64(const char *name, const char *value)
> >+{
> >+	long long ret = 0;
> >+
> >+	if (!perf_parse_llong(value, &ret))
> >+		die_bad_config(name);
> >+	return (u64) ret;
> 
> 
> Thought we were not using the die functions any longer?

seem like patchset removing that for config object
will prepare separate change

jirka

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

* Re: [PATCH 16/18] perf tools: Add debug prints for ordered events queue
  2014-06-28  2:52   ` David Ahern
@ 2014-06-29 16:46     ` Jiri Olsa
  2014-06-29 16:52       ` David Ahern
  0 siblings, 1 reply; 37+ messages in thread
From: Jiri Olsa @ 2014-06-29 16:46 UTC (permalink / raw)
  To: David Ahern
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On Fri, Jun 27, 2014 at 08:52:26PM -0600, David Ahern wrote:
> On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> >Adding some prints for ordered events queue, to help
> >debug issues.
> 
> went to enable this and it is really odd to have to edit a config file to
> enable debugging. How about hooking it into verbose option? Maybe like
> multiple levels of -v or -v <val> or -v queue.

seems like verbose option factoring.. in future ;-) I can live
without this patch though.. it was mainly for testing my changes

thanks,
jirka

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

* Re: [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface
  2014-06-29 16:39     ` Jiri Olsa
@ 2014-06-29 16:50       ` David Ahern
  2014-06-30 15:02         ` Arnaldo Carvalho de Melo
  2014-06-30 15:03       ` Arnaldo Carvalho de Melo
  1 sibling, 1 reply; 37+ messages in thread
From: David Ahern @ 2014-06-29 16:50 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On 6/29/14, 10:39 AM, Jiri Olsa wrote:
> On Fri, Jun 27, 2014 at 05:06:36PM -0600, David Ahern wrote:
>> On 6/18/14, 8:58 AM, Jiri Olsa wrote:
>>>
>>> +static struct ordered_event*
>>> +ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
>>> +{
>>> +	struct ordered_event *new;
>>> +
>>> +	new = alloc_event(q);
>>> +	if (new) {
>>> +		new->timestamp = timestamp;
>>> +		queue_event(q, new);
>>> +	}
>>> +
>>> +	return new;
>>> +}
>>
>> The _get name does not really correlate with what is happening -- ie.,
>> allocate a new event and add it to the queue. There is no reference taken
>> either.
>
> ook.. so how about ordered_events_alloc ordered_events_free
>
>>
>>> +
>>> +static void
>>> +ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
>>> +{
>>> +	list_del(&iter->list);
>>> +	list_add(&iter->list, &q->cache);
>>> +	q->nr_events--;
>>> +}
>>
>> Similarly here with the _put. In this case the function is moving the event
>> from one list to another. And how about something else for the name besides
>> iter -- oe, or oevent?
>
> how about 'event' ?

Already a heavily used keyword in perf, that's why I was thinking oe or 
oevent -- besides it is a struct ordered_event not an event.

The bigger thing to me with this patch is the _get/_put names.

David


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

* Re: [PATCH 16/18] perf tools: Add debug prints for ordered events queue
  2014-06-29 16:46     ` Jiri Olsa
@ 2014-06-29 16:52       ` David Ahern
  0 siblings, 0 replies; 37+ messages in thread
From: David Ahern @ 2014-06-29 16:52 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On 6/29/14, 10:46 AM, Jiri Olsa wrote:
> On Fri, Jun 27, 2014 at 08:52:26PM -0600, David Ahern wrote:
>> On 6/18/14, 8:58 AM, Jiri Olsa wrote:
>>> Adding some prints for ordered events queue, to help
>>> debug issues.
>>
>> went to enable this and it is really odd to have to edit a config file to
>> enable debugging. How about hooking it into verbose option? Maybe like
>> multiple levels of -v or -v <val> or -v queue.
>
> seems like verbose option factoring.. in future ;-) I can live
> without this patch though.. it was mainly for testing my changes

It was quite useful to see how various data sets were stressing the 
ordered samples queue. For example 'perf record -g' and a kernel build 
stressed it more than the record on the 'perf bench'.

David


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

* Re: [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface
  2014-06-29 16:50       ` David Ahern
@ 2014-06-30 15:02         ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-06-30 15:02 UTC (permalink / raw)
  To: David Ahern
  Cc: Jiri Olsa, Jiri Olsa, linux-kernel, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Em Sun, Jun 29, 2014 at 10:50:24AM -0600, David Ahern escreveu:
> On 6/29/14, 10:39 AM, Jiri Olsa wrote:
> >On Fri, Jun 27, 2014 at 05:06:36PM -0600, David Ahern wrote:
> >>On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> >>>+static struct ordered_event*
> >>>+ordered_events_get(struct ordered_events_queue *q, u64 timestamp)
> >>>+{
> >>>+	struct ordered_event *new;
> >>>+
> >>>+	new = alloc_event(q);
> >>>+	if (new) {
> >>>+		new->timestamp = timestamp;
> >>>+		queue_event(q, new);
> >>>+	}
> >>>+
> >>>+	return new;
> >>>+}

> >>The _get name does not really correlate with what is happening -- ie.,
> >>allocate a new event and add it to the queue. There is no reference taken
> >>either.

> >ook.. so how about ordered_events_alloc ordered_events_free

ordered_events__new() and ordered_events__delete(), to be consistent
with general naming for constructors and destructors in tools/perf/ :-)

I would also not use "new" as the name of the new instance, as above,
but would rather use 'oe', shortcut for ordered event, or even oevent,
as elsewhere suggested in this thread.

> >>>+static void
> >>>+ordered_event_put(struct ordered_events_queue *q, struct ordered_event *iter)
> >>>+{
> >>>+	list_del(&iter->list);
> >>>+	list_add(&iter->list, &q->cache);
> >>>+	q->nr_events--;
> >>>+}
> >>
> >>Similarly here with the _put. In this case the function is moving the event
> >>from one list to another. And how about something else for the name besides
> >>iter -- oe, or oevent?
> >
> >how about 'event' ?
> 
> Already a heavily used keyword in perf, that's why I was thinking oe or
> oevent -- besides it is a struct ordered_event not an event.

Agreed on all counts.
 
> The bigger thing to me with this patch is the _get/_put names.

Agreed, those are for reference counting.

- Arnaldo

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

* Re: [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface
  2014-06-29 16:39     ` Jiri Olsa
  2014-06-29 16:50       ` David Ahern
@ 2014-06-30 15:03       ` Arnaldo Carvalho de Melo
  1 sibling, 0 replies; 37+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-06-30 15:03 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: David Ahern, Jiri Olsa, linux-kernel, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

Em Sun, Jun 29, 2014 at 06:39:33PM +0200, Jiri Olsa escreveu:
> On Fri, Jun 27, 2014 at 05:06:36PM -0600, David Ahern wrote:
> > On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> > >+static struct ordered_event*
> > >+ordered_events_get(struct ordered_events_queue *q, u64 timestamp)

Also I don't think that it matters that much to have explicit in the
name above the data structure used to reorder events, i.e. I suggest
renaming "struct ordered_events_queue" to just "struct ordered_events".

- Arnaldo

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

* Re: [PATCH 07/18] perf tools: Limit ordered events queue size
  2014-06-27 23:11   ` David Ahern
@ 2014-06-30 17:58     ` Jiri Olsa
  0 siblings, 0 replies; 37+ messages in thread
From: Jiri Olsa @ 2014-06-30 17:58 UTC (permalink / raw)
  To: David Ahern
  Cc: Jiri Olsa, linux-kernel, Arnaldo Carvalho de Melo, Corey Ashford,
	Frederic Weisbecker, Ingo Molnar, Jean Pihet, Namhyung Kim,
	Paul Mackerras, Peter Zijlstra

On Fri, Jun 27, 2014 at 05:11:15PM -0600, David Ahern wrote:
> On 6/18/14, 8:58 AM, Jiri Olsa wrote:
> >@@ -520,7 +522,7 @@ static void queue_event(struct ordered_events_queue *q, struct ordered_event *ne
> >  static struct ordered_event *alloc_event(struct ordered_events_queue *q)
> >  {
> >  	struct list_head *cache = &q->cache;
> >-	struct ordered_event *new;
> >+	struct ordered_event *new = NULL;
> >
> >  	if (!list_empty(cache)) {
> >  		new = list_entry(cache->next, struct ordered_event, list);
> >@@ -529,10 +531,14 @@ static struct ordered_event *alloc_event(struct ordered_events_queue *q)
> >  		new = q->buffer + q->buffer_idx;
> >  		if (++q->buffer_idx == MAX_SAMPLE_BUFFER)
> >  			q->buffer = NULL;
> >-	} else {
> >-		q->buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
> >+	} else if (q->cur_alloc_size < q->max_alloc_size) {
> >+		size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
> >+
> >+		q->buffer = malloc(size);
> >  		if (!q->buffer)
> >  			return NULL;
> >+
> >+		q->cur_alloc_size += size;
> >  		list_add(&q->buffer->list, &q->to_free);
> >
> 
> When is cur_alloc_size decremented?

never, it get's incremented untiul we reach the limit,
then it stays and the cache is used for new events..
and it's all released at the end

jirka

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

end of thread, other threads:[~2014-06-30 17:58 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-18 14:58 [PATCHv2 00/18] perf tools: Factor ordered samples queue Jiri Olsa
2014-06-18 14:58 ` [PATCH 01/18] perf tools: Always force PERF_RECORD_FINISHED_ROUND event Jiri Olsa
2014-06-18 14:58 ` [PATCH 02/18] perf tools: Fix accounting of ordered samples queue Jiri Olsa
2014-06-18 14:58 ` [PATCH 03/18] perf tools: Rename ordered_samples to ordered_events Jiri Olsa
2014-06-18 14:58 ` [PATCH 04/18] perf tools: Rename ordered_events_queue members Jiri Olsa
2014-06-18 14:58 ` [PATCH 05/18] perf tools: Add ordered_events_(get|put) interface Jiri Olsa
2014-06-27 23:06   ` David Ahern
2014-06-29 16:39     ` Jiri Olsa
2014-06-29 16:50       ` David Ahern
2014-06-30 15:02         ` Arnaldo Carvalho de Melo
2014-06-30 15:03       ` Arnaldo Carvalho de Melo
2014-06-18 14:58 ` [PATCH 06/18] perf tools: Factor ordered_events_flush to be more generic Jiri Olsa
2014-06-18 14:58 ` [PATCH 07/18] perf tools: Limit ordered events queue size Jiri Olsa
2014-06-27 23:11   ` David Ahern
2014-06-30 17:58     ` Jiri Olsa
2014-06-18 14:58 ` [PATCH 08/18] perf tools: Flush ordered events in case of allocation failure Jiri Olsa
2014-06-27 23:07   ` David Ahern
2014-06-29 16:41     ` Jiri Olsa
2014-06-18 14:58 ` [PATCH 09/18] perf tools: Make perf_session_deliver_event global Jiri Olsa
2014-06-18 14:58 ` [PATCH 10/18] perf tools: Create ordered-events object Jiri Olsa
2014-06-18 14:58 ` [PATCH 11/18] perf tools: Use list_move in ordered_event_put function Jiri Olsa
2014-06-18 14:58 ` [PATCH 12/18] perf tools: Add ordered_events_queue_init function Jiri Olsa
2014-06-18 14:58 ` [PATCH 13/18] perf tools: Add ordered_events_queue_free function Jiri Olsa
2014-06-18 14:58 ` [PATCH 14/18] perf tools: Add perf_config_u64 function Jiri Olsa
2014-06-27 23:08   ` David Ahern
2014-06-29 16:44     ` Jiri Olsa
2014-06-18 14:58 ` [PATCH 15/18] perf tools: Add report.queue-size config file option Jiri Olsa
2014-06-18 14:58 ` [PATCH 16/18] perf tools: Add debug prints for ordered events queue Jiri Olsa
2014-06-28  2:52   ` David Ahern
2014-06-29 16:46     ` Jiri Olsa
2014-06-29 16:52       ` David Ahern
2014-06-18 14:58 ` [PATCH 17/18] perf tools: Limit the ordered events queue by default to 100MB Jiri Olsa
2014-06-18 14:58 ` [PATCH 18/18] perf tools: Allow out of order messages in forced flush Jiri Olsa
2014-06-18 19:44 ` [PATCHv2 00/18] perf tools: Factor ordered samples queue David Ahern
2014-06-19 10:34   ` Jiri Olsa
2014-06-19 17:54     ` David Ahern
2014-06-20  7:15       ` 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.