[PATCH 6/8] perf data: Switch to multiple cpu stream files

2015-01-15 Thread Jiri Olsa
From: Sebastian Andrzej Siewior 

Currently we store the data into single data strea/file. The cpu
if data is stored within the event sample. The lttng puts the CPU
number that belongs to the event into the packet context instead
into the event.

This patch makes sure that the trace produce by perf does look the
same way. We now use one stream per-CPU. Having it all in one stream
increased the total size of the resulting file. The test went from
416KiB (with perf_cpu event member) to 24MiB due to the required
(and pointless) flush. With the per-cpu streams the total size went
up to 588KiB.

Cc: Arnaldo Carvalho de Melo 
Cc: David Ahern 
Cc: Frederic Weisbecker 
Cc: Jeremie Galarneau 
Cc: Jiri Olsa 
Cc: Namhyung Kim 
Cc: Paul Mackerras 
Cc: Peter Zijlstra 
Cc: Sebastian Andrzej Siewior 
Cc: Tom Zanussi 
Signed-off-by: Jiri Olsa 
Signed-off-by: Sebastian Andrzej Siewior 
---
 tools/perf/util/data-convert-bt.c | 205 +-
 1 file changed, 181 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/data-convert-bt.c 
b/tools/perf/util/data-convert-bt.c
index 6fa5c3ef336b..4bb769e081a8 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -38,12 +38,20 @@ struct evsel_priv {
struct bt_ctf_event_class *event_class;
 };
 
+#define MAX_CPUS   4096
+
+struct ctf_stream {
+   struct bt_ctf_stream *stream;
+   int cpu;
+};
+
 struct ctf_writer {
/* writer primitives */
-   struct bt_ctf_writer*writer;
-   struct bt_ctf_stream*stream;
-   struct bt_ctf_stream_class  *stream_class;
-   struct bt_ctf_clock *clock;
+   struct bt_ctf_writer *writer;
+   struct ctf_stream   **stream;
+   int   stream_cnt;
+   struct bt_ctf_stream_class   *stream_class;
+   struct bt_ctf_clock  *clock;
 
/* data types */
union {
@@ -346,12 +354,6 @@ static int add_generic_values(struct ctf_writer *cw,
return -1;
}
 
-   if (type & PERF_SAMPLE_CPU) {
-   ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
-   if (ret)
-   return -1;
-   }
-
if (type & PERF_SAMPLE_PERIOD) {
ret = value_set_u64(cw, event, "perf_period", sample->period);
if (ret)
@@ -381,6 +383,113 @@ static int add_generic_values(struct ctf_writer *cw,
return 0;
 }
 
+static int ctf_stream__flush(struct ctf_stream *cs)
+{
+   int err = 0;
+
+   if (cs) {
+   err = bt_ctf_stream_flush(cs->stream);
+   if (err)
+   pr_err("CTF stream %d flush failed\n", cs->cpu);
+
+   pr("Flush stream for cpu %d\n", cs->cpu);
+   }
+
+   return err;
+}
+
+static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs;
+   struct bt_ctf_field *pkt_ctx   = NULL;
+   struct bt_ctf_field *cpu_field = NULL;
+   struct bt_ctf_stream *stream   = NULL;
+   int ret;
+
+   cs = zalloc(sizeof(*cs));
+   if (!cs) {
+   pr_err("Failed to allocate ctf stream\n");
+   return NULL;
+   }
+
+   stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
+   if (!stream) {
+   pr_err("Failed to create CTF stream\n");
+   goto out;
+   }
+
+   pkt_ctx = bt_ctf_stream_get_packet_context(stream);
+   if (!pkt_ctx) {
+   pr_err("Failed to obtain packet context\n");
+   goto out;
+   }
+
+   cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
+   bt_ctf_field_put(pkt_ctx);
+   if (!cpu_field) {
+   pr_err("Failed to obtain cpu field\n");
+   goto out;
+   }
+
+   ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
+   if (ret) {
+   pr_err("Failed to update CPU number\n");
+   goto out;
+   }
+
+   bt_ctf_field_put(cpu_field);
+
+   cs->cpu= cpu;
+   cs->stream = stream;
+   return cs;
+
+out:
+   if (cpu_field)
+   bt_ctf_field_put(cpu_field);
+   if (stream)
+   bt_ctf_stream_put(stream);
+
+   free(cs);
+   return NULL;
+}
+
+static void ctf_stream__delete(struct ctf_stream *cs)
+{
+   if (cs) {
+   bt_ctf_stream_put(cs->stream);
+   free(cs);
+   }
+}
+
+static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs = cw->stream[cpu];
+
+   if (!cs) {
+   cs = ctf_stream__create(cw, cpu);
+   cw->stream[cpu] = cs;
+   }
+
+   return cs;
+}
+
+static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
+ struct perf_evsel *evsel)
+{
+   int cpu = 0;
+
+   if 

[PATCH 6/8] perf data: Switch to multiple cpu stream files

2015-01-15 Thread Jiri Olsa
From: Sebastian Andrzej Siewior bige...@linutronix.de

Currently we store the data into single data strea/file. The cpu
if data is stored within the event sample. The lttng puts the CPU
number that belongs to the event into the packet context instead
into the event.

This patch makes sure that the trace produce by perf does look the
same way. We now use one stream per-CPU. Having it all in one stream
increased the total size of the resulting file. The test went from
416KiB (with perf_cpu event member) to 24MiB due to the required
(and pointless) flush. With the per-cpu streams the total size went
up to 588KiB.

Cc: Arnaldo Carvalho de Melo a...@redhat.com
Cc: David Ahern dsah...@gmail.com
Cc: Frederic Weisbecker fweis...@gmail.com
Cc: Jeremie Galarneau jga...@efficios.com
Cc: Jiri Olsa jo...@kernel.org
Cc: Namhyung Kim namhy...@gmail.com
Cc: Paul Mackerras pau...@samba.org
Cc: Peter Zijlstra pet...@infradead.org
Cc: Sebastian Andrzej Siewior bige...@linutronix.de
Cc: Tom Zanussi tzanu...@gmail.com
Signed-off-by: Jiri Olsa jo...@kernel.org
Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de
---
 tools/perf/util/data-convert-bt.c | 205 +-
 1 file changed, 181 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/data-convert-bt.c 
b/tools/perf/util/data-convert-bt.c
index 6fa5c3ef336b..4bb769e081a8 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -38,12 +38,20 @@ struct evsel_priv {
struct bt_ctf_event_class *event_class;
 };
 
+#define MAX_CPUS   4096
+
+struct ctf_stream {
+   struct bt_ctf_stream *stream;
+   int cpu;
+};
+
 struct ctf_writer {
/* writer primitives */
-   struct bt_ctf_writer*writer;
-   struct bt_ctf_stream*stream;
-   struct bt_ctf_stream_class  *stream_class;
-   struct bt_ctf_clock *clock;
+   struct bt_ctf_writer *writer;
+   struct ctf_stream   **stream;
+   int   stream_cnt;
+   struct bt_ctf_stream_class   *stream_class;
+   struct bt_ctf_clock  *clock;
 
/* data types */
union {
@@ -346,12 +354,6 @@ static int add_generic_values(struct ctf_writer *cw,
return -1;
}
 
-   if (type  PERF_SAMPLE_CPU) {
-   ret = value_set_u32(cw, event, perf_cpu, sample-cpu);
-   if (ret)
-   return -1;
-   }
-
if (type  PERF_SAMPLE_PERIOD) {
ret = value_set_u64(cw, event, perf_period, sample-period);
if (ret)
@@ -381,6 +383,113 @@ static int add_generic_values(struct ctf_writer *cw,
return 0;
 }
 
+static int ctf_stream__flush(struct ctf_stream *cs)
+{
+   int err = 0;
+
+   if (cs) {
+   err = bt_ctf_stream_flush(cs-stream);
+   if (err)
+   pr_err(CTF stream %d flush failed\n, cs-cpu);
+
+   pr(Flush stream for cpu %d\n, cs-cpu);
+   }
+
+   return err;
+}
+
+static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs;
+   struct bt_ctf_field *pkt_ctx   = NULL;
+   struct bt_ctf_field *cpu_field = NULL;
+   struct bt_ctf_stream *stream   = NULL;
+   int ret;
+
+   cs = zalloc(sizeof(*cs));
+   if (!cs) {
+   pr_err(Failed to allocate ctf stream\n);
+   return NULL;
+   }
+
+   stream = bt_ctf_writer_create_stream(cw-writer, cw-stream_class);
+   if (!stream) {
+   pr_err(Failed to create CTF stream\n);
+   goto out;
+   }
+
+   pkt_ctx = bt_ctf_stream_get_packet_context(stream);
+   if (!pkt_ctx) {
+   pr_err(Failed to obtain packet context\n);
+   goto out;
+   }
+
+   cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, cpu_id);
+   bt_ctf_field_put(pkt_ctx);
+   if (!cpu_field) {
+   pr_err(Failed to obtain cpu field\n);
+   goto out;
+   }
+
+   ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
+   if (ret) {
+   pr_err(Failed to update CPU number\n);
+   goto out;
+   }
+
+   bt_ctf_field_put(cpu_field);
+
+   cs-cpu= cpu;
+   cs-stream = stream;
+   return cs;
+
+out:
+   if (cpu_field)
+   bt_ctf_field_put(cpu_field);
+   if (stream)
+   bt_ctf_stream_put(stream);
+
+   free(cs);
+   return NULL;
+}
+
+static void ctf_stream__delete(struct ctf_stream *cs)
+{
+   if (cs) {
+   bt_ctf_stream_put(cs-stream);
+   free(cs);
+   }
+}
+
+static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs = cw-stream[cpu];
+
+   if (!cs) {
+   cs = ctf_stream__create(cw, cpu);
+   cw-stream[cpu] = cs;
+  

[PATCH 6/8] perf data: Switch to multiple cpu stream files

2014-12-11 Thread Jiri Olsa
From: Sebastian Andrzej Siewior 

Currently we store the data into single data strea/file. The cpu
if data is stored within the event sample. The lttng puts the CPU
number that belongs to the event into the packet context instead
into the event.

This patch makes sure that the trace produce by perf does look the
same way. We now use one stream per-CPU. Having it all in one stream
increased the total size of the resulting file. The test went from
416KiB (with perf_cpu event member) to 24MiB due to the required
(and pointless) flush. With the per-cpu streams the total size went
up to 588KiB.

Cc: Arnaldo Carvalho de Melo 
Cc: David Ahern 
Cc: Frederic Weisbecker 
Cc: Jeremie Galarneau 
Cc: Jiri Olsa 
Cc: Namhyung Kim 
Cc: Paul Mackerras 
Cc: Peter Zijlstra 
Cc: Sebastian Andrzej Siewior 
Cc: Tom Zanussi 
Signed-off-by: Jiri Olsa 
Signed-off-by: Sebastian Andrzej Siewior 
---
 tools/perf/util/data-convert-bt.c | 205 +-
 1 file changed, 181 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/data-convert-bt.c 
b/tools/perf/util/data-convert-bt.c
index 6fa5c3ef336b..4bb769e081a8 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -38,12 +38,20 @@ struct evsel_priv {
struct bt_ctf_event_class *event_class;
 };
 
+#define MAX_CPUS   4096
+
+struct ctf_stream {
+   struct bt_ctf_stream *stream;
+   int cpu;
+};
+
 struct ctf_writer {
/* writer primitives */
-   struct bt_ctf_writer*writer;
-   struct bt_ctf_stream*stream;
-   struct bt_ctf_stream_class  *stream_class;
-   struct bt_ctf_clock *clock;
+   struct bt_ctf_writer *writer;
+   struct ctf_stream   **stream;
+   int   stream_cnt;
+   struct bt_ctf_stream_class   *stream_class;
+   struct bt_ctf_clock  *clock;
 
/* data types */
union {
@@ -346,12 +354,6 @@ static int add_generic_values(struct ctf_writer *cw,
return -1;
}
 
-   if (type & PERF_SAMPLE_CPU) {
-   ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
-   if (ret)
-   return -1;
-   }
-
if (type & PERF_SAMPLE_PERIOD) {
ret = value_set_u64(cw, event, "perf_period", sample->period);
if (ret)
@@ -381,6 +383,113 @@ static int add_generic_values(struct ctf_writer *cw,
return 0;
 }
 
+static int ctf_stream__flush(struct ctf_stream *cs)
+{
+   int err = 0;
+
+   if (cs) {
+   err = bt_ctf_stream_flush(cs->stream);
+   if (err)
+   pr_err("CTF stream %d flush failed\n", cs->cpu);
+
+   pr("Flush stream for cpu %d\n", cs->cpu);
+   }
+
+   return err;
+}
+
+static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs;
+   struct bt_ctf_field *pkt_ctx   = NULL;
+   struct bt_ctf_field *cpu_field = NULL;
+   struct bt_ctf_stream *stream   = NULL;
+   int ret;
+
+   cs = zalloc(sizeof(*cs));
+   if (!cs) {
+   pr_err("Failed to allocate ctf stream\n");
+   return NULL;
+   }
+
+   stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
+   if (!stream) {
+   pr_err("Failed to create CTF stream\n");
+   goto out;
+   }
+
+   pkt_ctx = bt_ctf_stream_get_packet_context(stream);
+   if (!pkt_ctx) {
+   pr_err("Failed to obtain packet context\n");
+   goto out;
+   }
+
+   cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
+   bt_ctf_field_put(pkt_ctx);
+   if (!cpu_field) {
+   pr_err("Failed to obtain cpu field\n");
+   goto out;
+   }
+
+   ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
+   if (ret) {
+   pr_err("Failed to update CPU number\n");
+   goto out;
+   }
+
+   bt_ctf_field_put(cpu_field);
+
+   cs->cpu= cpu;
+   cs->stream = stream;
+   return cs;
+
+out:
+   if (cpu_field)
+   bt_ctf_field_put(cpu_field);
+   if (stream)
+   bt_ctf_stream_put(stream);
+
+   free(cs);
+   return NULL;
+}
+
+static void ctf_stream__delete(struct ctf_stream *cs)
+{
+   if (cs) {
+   bt_ctf_stream_put(cs->stream);
+   free(cs);
+   }
+}
+
+static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs = cw->stream[cpu];
+
+   if (!cs) {
+   cs = ctf_stream__create(cw, cpu);
+   cw->stream[cpu] = cs;
+   }
+
+   return cs;
+}
+
+static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
+ struct perf_evsel *evsel)
+{
+   int cpu = 0;
+
+   if 

[PATCH 6/8] perf data: Switch to multiple cpu stream files

2014-12-11 Thread Jiri Olsa
From: Sebastian Andrzej Siewior bige...@linutronix.de

Currently we store the data into single data strea/file. The cpu
if data is stored within the event sample. The lttng puts the CPU
number that belongs to the event into the packet context instead
into the event.

This patch makes sure that the trace produce by perf does look the
same way. We now use one stream per-CPU. Having it all in one stream
increased the total size of the resulting file. The test went from
416KiB (with perf_cpu event member) to 24MiB due to the required
(and pointless) flush. With the per-cpu streams the total size went
up to 588KiB.

Cc: Arnaldo Carvalho de Melo a...@redhat.com
Cc: David Ahern dsah...@gmail.com
Cc: Frederic Weisbecker fweis...@gmail.com
Cc: Jeremie Galarneau jga...@efficios.com
Cc: Jiri Olsa jo...@kernel.org
Cc: Namhyung Kim namhy...@gmail.com
Cc: Paul Mackerras pau...@samba.org
Cc: Peter Zijlstra pet...@infradead.org
Cc: Sebastian Andrzej Siewior bige...@linutronix.de
Cc: Tom Zanussi tzanu...@gmail.com
Signed-off-by: Jiri Olsa jo...@kernel.org
Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de
---
 tools/perf/util/data-convert-bt.c | 205 +-
 1 file changed, 181 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/data-convert-bt.c 
b/tools/perf/util/data-convert-bt.c
index 6fa5c3ef336b..4bb769e081a8 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -38,12 +38,20 @@ struct evsel_priv {
struct bt_ctf_event_class *event_class;
 };
 
+#define MAX_CPUS   4096
+
+struct ctf_stream {
+   struct bt_ctf_stream *stream;
+   int cpu;
+};
+
 struct ctf_writer {
/* writer primitives */
-   struct bt_ctf_writer*writer;
-   struct bt_ctf_stream*stream;
-   struct bt_ctf_stream_class  *stream_class;
-   struct bt_ctf_clock *clock;
+   struct bt_ctf_writer *writer;
+   struct ctf_stream   **stream;
+   int   stream_cnt;
+   struct bt_ctf_stream_class   *stream_class;
+   struct bt_ctf_clock  *clock;
 
/* data types */
union {
@@ -346,12 +354,6 @@ static int add_generic_values(struct ctf_writer *cw,
return -1;
}
 
-   if (type  PERF_SAMPLE_CPU) {
-   ret = value_set_u32(cw, event, perf_cpu, sample-cpu);
-   if (ret)
-   return -1;
-   }
-
if (type  PERF_SAMPLE_PERIOD) {
ret = value_set_u64(cw, event, perf_period, sample-period);
if (ret)
@@ -381,6 +383,113 @@ static int add_generic_values(struct ctf_writer *cw,
return 0;
 }
 
+static int ctf_stream__flush(struct ctf_stream *cs)
+{
+   int err = 0;
+
+   if (cs) {
+   err = bt_ctf_stream_flush(cs-stream);
+   if (err)
+   pr_err(CTF stream %d flush failed\n, cs-cpu);
+
+   pr(Flush stream for cpu %d\n, cs-cpu);
+   }
+
+   return err;
+}
+
+static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs;
+   struct bt_ctf_field *pkt_ctx   = NULL;
+   struct bt_ctf_field *cpu_field = NULL;
+   struct bt_ctf_stream *stream   = NULL;
+   int ret;
+
+   cs = zalloc(sizeof(*cs));
+   if (!cs) {
+   pr_err(Failed to allocate ctf stream\n);
+   return NULL;
+   }
+
+   stream = bt_ctf_writer_create_stream(cw-writer, cw-stream_class);
+   if (!stream) {
+   pr_err(Failed to create CTF stream\n);
+   goto out;
+   }
+
+   pkt_ctx = bt_ctf_stream_get_packet_context(stream);
+   if (!pkt_ctx) {
+   pr_err(Failed to obtain packet context\n);
+   goto out;
+   }
+
+   cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, cpu_id);
+   bt_ctf_field_put(pkt_ctx);
+   if (!cpu_field) {
+   pr_err(Failed to obtain cpu field\n);
+   goto out;
+   }
+
+   ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
+   if (ret) {
+   pr_err(Failed to update CPU number\n);
+   goto out;
+   }
+
+   bt_ctf_field_put(cpu_field);
+
+   cs-cpu= cpu;
+   cs-stream = stream;
+   return cs;
+
+out:
+   if (cpu_field)
+   bt_ctf_field_put(cpu_field);
+   if (stream)
+   bt_ctf_stream_put(stream);
+
+   free(cs);
+   return NULL;
+}
+
+static void ctf_stream__delete(struct ctf_stream *cs)
+{
+   if (cs) {
+   bt_ctf_stream_put(cs-stream);
+   free(cs);
+   }
+}
+
+static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs = cw-stream[cpu];
+
+   if (!cs) {
+   cs = ctf_stream__create(cw, cpu);
+   cw-stream[cpu] = cs;
+  

Re: [PATCH 6/8] perf data: Switch to multiple cpu stream files

2014-12-09 Thread Jiri Olsa
On Mon, Dec 08, 2014 at 05:17:44PM +0900, Namhyung Kim wrote:
> On Thu, Dec 4, 2014 at 1:24 AM, Jiri Olsa  wrote:
> > +static int setup_streams(struct ctf_writer *cw, struct perf_session 
> > *session)
> > +{
> > +   struct ctf_stream **stream;
> > +   struct perf_header *ph = >header;
> > +   int ncpus;
> > +
> > +   /*
> > +* Try to get the number of cpus used in the data file,
> > +* if not present fallback to the MAX_CPUS.
> > +*/
> > +   if (!ph)
> 
> I think this check is meaningless since perf_header struct is embedded
> in perf_session so it shouldn't be NULL when refered from a session..

right, it's actually different in the git, I used:

if (!ph || !ph->env.nr_cpus_avail)
ncpus = MAX_CPUS;

I attached slightyl older version in email :-\

anyway, I'll send v2 shortly 

thanks,
jirka
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 6/8] perf data: Switch to multiple cpu stream files

2014-12-09 Thread Jiri Olsa
On Mon, Dec 08, 2014 at 05:17:44PM +0900, Namhyung Kim wrote:
 On Thu, Dec 4, 2014 at 1:24 AM, Jiri Olsa jo...@kernel.org wrote:
  +static int setup_streams(struct ctf_writer *cw, struct perf_session 
  *session)
  +{
  +   struct ctf_stream **stream;
  +   struct perf_header *ph = session-header;
  +   int ncpus;
  +
  +   /*
  +* Try to get the number of cpus used in the data file,
  +* if not present fallback to the MAX_CPUS.
  +*/
  +   if (!ph)
 
 I think this check is meaningless since perf_header struct is embedded
 in perf_session so it shouldn't be NULL when refered from a session..

right, it's actually different in the git, I used:

if (!ph || !ph-env.nr_cpus_avail)
ncpus = MAX_CPUS;

I attached slightyl older version in email :-\

anyway, I'll send v2 shortly 

thanks,
jirka
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 6/8] perf data: Switch to multiple cpu stream files

2014-12-08 Thread Namhyung Kim
On Thu, Dec 4, 2014 at 1:24 AM, Jiri Olsa  wrote:
> +static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
> +{
> +   struct ctf_stream **stream;
> +   struct perf_header *ph = >header;
> +   int ncpus;
> +
> +   /*
> +* Try to get the number of cpus used in the data file,
> +* if not present fallback to the MAX_CPUS.
> +*/
> +   if (!ph)

I think this check is meaningless since perf_header struct is embedded
in perf_session so it shouldn't be NULL when refered from a session..

Thanks,
Namhyung


> +   ncpus = MAX_CPUS;
> +   else
> +   ncpus = ph->env.nr_cpus_avail;
> +
> +   stream = zalloc(sizeof(*stream) * ncpus);
> +   if (!stream) {
> +   pr_err("Failed to allocate streams.\n");
> +   return -ENOMEM;
> +   }
> +
> +   cw->stream = stream;
> +   cw->stream_cnt = ncpus;
> +   return 0;
> +}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 6/8] perf data: Switch to multiple cpu stream files

2014-12-08 Thread Namhyung Kim
On Thu, Dec 4, 2014 at 1:24 AM, Jiri Olsa jo...@kernel.org wrote:
 +static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
 +{
 +   struct ctf_stream **stream;
 +   struct perf_header *ph = session-header;
 +   int ncpus;
 +
 +   /*
 +* Try to get the number of cpus used in the data file,
 +* if not present fallback to the MAX_CPUS.
 +*/
 +   if (!ph)

I think this check is meaningless since perf_header struct is embedded
in perf_session so it shouldn't be NULL when refered from a session..

Thanks,
Namhyung


 +   ncpus = MAX_CPUS;
 +   else
 +   ncpus = ph-env.nr_cpus_avail;
 +
 +   stream = zalloc(sizeof(*stream) * ncpus);
 +   if (!stream) {
 +   pr_err(Failed to allocate streams.\n);
 +   return -ENOMEM;
 +   }
 +
 +   cw-stream = stream;
 +   cw-stream_cnt = ncpus;
 +   return 0;
 +}
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 6/8] perf data: Switch to multiple cpu stream files

2014-12-03 Thread Jiri Olsa
From: Sebastian Andrzej Siewior 

Currently we store the data into single data strea/file. The cpu
if data is stored within the event sample. The lttng puts the CPU
number that belongs to the event into the packet context instead
into the event.

This patch makes sure that the trace produce by perf does look the
same way. We now use one stream per-CPU. Having it all in one stream
increased the total size of the resulting file. The test went from
416KiB (with perf_cpu event member) to 24MiB due to the required
(and pointless) flush. With the per-cpu streams the total size went
up to 588KiB.

Cc: Arnaldo Carvalho de Melo 
Cc: David Ahern 
Cc: Frederic Weisbecker 
Cc: Jeremie Galarneau 
Cc: Jiri Olsa 
Cc: Namhyung Kim 
Cc: Paul Mackerras 
Cc: Peter Zijlstra 
Cc: Sebastian Andrzej Siewior 
Cc: Tom Zanussi 
Signed-off-by: Jiri Olsa 
Signed-off-by: Sebastian Andrzej Siewior 
---
 tools/perf/util/data-convert-bt.c | 208 +-
 1 file changed, 184 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/data-convert-bt.c 
b/tools/perf/util/data-convert-bt.c
index cf1b16c89120..2bc70b8d128d 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -38,12 +38,20 @@ struct evsel_priv {
struct bt_ctf_event_class *event_class;
 };
 
+#define MAX_CPUS   4096
+
+struct ctf_stream {
+   struct bt_ctf_stream *stream;
+   int cpu;
+};
+
 struct ctf_writer {
/* writer primitives */
-   struct bt_ctf_writer*writer;
-   struct bt_ctf_stream*stream;
-   struct bt_ctf_stream_class  *stream_class;
-   struct bt_ctf_clock *clock;
+   struct bt_ctf_writer *writer;
+   struct ctf_stream   **stream;
+   int   stream_cnt;
+   struct bt_ctf_stream_class   *stream_class;
+   struct bt_ctf_clock  *clock;
 
/* data types */
union {
@@ -346,12 +354,6 @@ static int add_generic_values(struct ctf_writer *cw,
return -1;
}
 
-   if (type & PERF_SAMPLE_CPU) {
-   ret = value_set_u32(cw, event, "perf_cpu", sample->cpu);
-   if (ret)
-   return -1;
-   }
-
if (type & PERF_SAMPLE_PERIOD) {
ret = value_set_u64(cw, event, "perf_period", sample->period);
if (ret)
@@ -381,6 +383,113 @@ static int add_generic_values(struct ctf_writer *cw,
return 0;
 }
 
+static int ctf_stream__flush(struct ctf_stream *cs)
+{
+   int err = 0;
+
+   if (cs) {
+   err = bt_ctf_stream_flush(cs->stream);
+   if (err)
+   pr_err("CTF stream %d flush failed\n", cs->cpu);
+
+   pr("Flush stream for cpu %d\n", cs->cpu);
+   }
+
+   return err;
+}
+
+static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs;
+   struct bt_ctf_field *pkt_ctx   = NULL;
+   struct bt_ctf_field *cpu_field = NULL;
+   struct bt_ctf_stream *stream   = NULL;
+   int ret;
+
+   cs = zalloc(sizeof(*cs));
+   if (!cs) {
+   pr_err("Failed to allocate ctf stream\n");
+   return NULL;
+   }
+
+   stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
+   if (!stream) {
+   pr_err("Failed to create CTF stream\n");
+   goto out;
+   }
+
+   pkt_ctx = bt_ctf_stream_get_packet_context(stream);
+   if (!pkt_ctx) {
+   pr_err("Failed to obtain packet context\n");
+   goto out;
+   }
+
+   cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
+   bt_ctf_field_put(pkt_ctx);
+   if (!cpu_field) {
+   pr_err("Failed to obtain cpu field\n");
+   goto out;
+   }
+
+   ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
+   if (ret) {
+   pr_err("Failed to update CPU number\n");
+   goto out;
+   }
+
+   bt_ctf_field_put(cpu_field);
+
+   cs->cpu= cpu;
+   cs->stream = stream;
+   return cs;
+
+out:
+   if (cpu_field)
+   bt_ctf_field_put(cpu_field);
+   if (stream)
+   bt_ctf_stream_put(stream);
+
+   free(cs);
+   return NULL;
+}
+
+static void ctf_stream__delete(struct ctf_stream *cs)
+{
+   if (cs) {
+   bt_ctf_stream_put(cs->stream);
+   free(cs);
+   }
+}
+
+static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs = cw->stream[cpu];
+
+   if (!cs) {
+   cs = ctf_stream__create(cw, cpu);
+   cw->stream[cpu] = cs;
+   }
+
+   return cs;
+}
+
+static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
+ struct perf_evsel *evsel)
+{
+   int cpu = 0;
+
+   if 

[PATCH 6/8] perf data: Switch to multiple cpu stream files

2014-12-03 Thread Jiri Olsa
From: Sebastian Andrzej Siewior bige...@linutronix.de

Currently we store the data into single data strea/file. The cpu
if data is stored within the event sample. The lttng puts the CPU
number that belongs to the event into the packet context instead
into the event.

This patch makes sure that the trace produce by perf does look the
same way. We now use one stream per-CPU. Having it all in one stream
increased the total size of the resulting file. The test went from
416KiB (with perf_cpu event member) to 24MiB due to the required
(and pointless) flush. With the per-cpu streams the total size went
up to 588KiB.

Cc: Arnaldo Carvalho de Melo a...@redhat.com
Cc: David Ahern dsah...@gmail.com
Cc: Frederic Weisbecker fweis...@gmail.com
Cc: Jeremie Galarneau jga...@efficios.com
Cc: Jiri Olsa jo...@kernel.org
Cc: Namhyung Kim namhy...@gmail.com
Cc: Paul Mackerras pau...@samba.org
Cc: Peter Zijlstra pet...@infradead.org
Cc: Sebastian Andrzej Siewior bige...@linutronix.de
Cc: Tom Zanussi tzanu...@gmail.com
Signed-off-by: Jiri Olsa jo...@kernel.org
Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de
---
 tools/perf/util/data-convert-bt.c | 208 +-
 1 file changed, 184 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/data-convert-bt.c 
b/tools/perf/util/data-convert-bt.c
index cf1b16c89120..2bc70b8d128d 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -38,12 +38,20 @@ struct evsel_priv {
struct bt_ctf_event_class *event_class;
 };
 
+#define MAX_CPUS   4096
+
+struct ctf_stream {
+   struct bt_ctf_stream *stream;
+   int cpu;
+};
+
 struct ctf_writer {
/* writer primitives */
-   struct bt_ctf_writer*writer;
-   struct bt_ctf_stream*stream;
-   struct bt_ctf_stream_class  *stream_class;
-   struct bt_ctf_clock *clock;
+   struct bt_ctf_writer *writer;
+   struct ctf_stream   **stream;
+   int   stream_cnt;
+   struct bt_ctf_stream_class   *stream_class;
+   struct bt_ctf_clock  *clock;
 
/* data types */
union {
@@ -346,12 +354,6 @@ static int add_generic_values(struct ctf_writer *cw,
return -1;
}
 
-   if (type  PERF_SAMPLE_CPU) {
-   ret = value_set_u32(cw, event, perf_cpu, sample-cpu);
-   if (ret)
-   return -1;
-   }
-
if (type  PERF_SAMPLE_PERIOD) {
ret = value_set_u64(cw, event, perf_period, sample-period);
if (ret)
@@ -381,6 +383,113 @@ static int add_generic_values(struct ctf_writer *cw,
return 0;
 }
 
+static int ctf_stream__flush(struct ctf_stream *cs)
+{
+   int err = 0;
+
+   if (cs) {
+   err = bt_ctf_stream_flush(cs-stream);
+   if (err)
+   pr_err(CTF stream %d flush failed\n, cs-cpu);
+
+   pr(Flush stream for cpu %d\n, cs-cpu);
+   }
+
+   return err;
+}
+
+static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs;
+   struct bt_ctf_field *pkt_ctx   = NULL;
+   struct bt_ctf_field *cpu_field = NULL;
+   struct bt_ctf_stream *stream   = NULL;
+   int ret;
+
+   cs = zalloc(sizeof(*cs));
+   if (!cs) {
+   pr_err(Failed to allocate ctf stream\n);
+   return NULL;
+   }
+
+   stream = bt_ctf_writer_create_stream(cw-writer, cw-stream_class);
+   if (!stream) {
+   pr_err(Failed to create CTF stream\n);
+   goto out;
+   }
+
+   pkt_ctx = bt_ctf_stream_get_packet_context(stream);
+   if (!pkt_ctx) {
+   pr_err(Failed to obtain packet context\n);
+   goto out;
+   }
+
+   cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, cpu_id);
+   bt_ctf_field_put(pkt_ctx);
+   if (!cpu_field) {
+   pr_err(Failed to obtain cpu field\n);
+   goto out;
+   }
+
+   ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
+   if (ret) {
+   pr_err(Failed to update CPU number\n);
+   goto out;
+   }
+
+   bt_ctf_field_put(cpu_field);
+
+   cs-cpu= cpu;
+   cs-stream = stream;
+   return cs;
+
+out:
+   if (cpu_field)
+   bt_ctf_field_put(cpu_field);
+   if (stream)
+   bt_ctf_stream_put(stream);
+
+   free(cs);
+   return NULL;
+}
+
+static void ctf_stream__delete(struct ctf_stream *cs)
+{
+   if (cs) {
+   bt_ctf_stream_put(cs-stream);
+   free(cs);
+   }
+}
+
+static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
+{
+   struct ctf_stream *cs = cw-stream[cpu];
+
+   if (!cs) {
+   cs = ctf_stream__create(cw, cpu);
+   cw-stream[cpu] = cs;
+