2021-04-30 07:48:19

by Jin Yao

[permalink] [raw]
Subject: [PATCH v1 2/2] perf header: Support hybrid CPU_PMU_CAPS

On hybrid platform, it may have several cpu pmus, such as,
"cpu_core" and "cpu_atom". The CPU_PMU_CAPS feature in perf
header needs to be improved to support multiple cpu pmus.

The new layout in header is defined as:

<nr_caps>
<caps string>
<caps string>
<pmu name>
<nr of rest pmus>

It's considered to be compatible with old perf.data (the
perf.data generated by old perf tool).

With this patch, some examples,

New perf tool with new perf.data
(new perf.data is generated on hybrid platform):

root@otcpl-adl-s-2:~# perf report --header-only -I
...
# cpu_core pmu capabilities: branches=32, max_precise=3, pmu_name=alderlake_hybrid
# cpu_atom pmu capabilities: branches=32, max_precise=3, pmu_name=alderlake_hybrid

New perf tool with new perf.data
(new perf.data is generated on non-hybrid platform):

root@kbl-ppc:~# perf report --header-only -I
...
# cpu pmu capabilities: branches=32, max_precise=3, pmu_name=skylake

New perf tool with old perf.data
(old perf.data is generated by old perf tool on non-hybrid platform):

root@kbl-ppc:~# perf report --header-only -I
...
# cpu pmu capabilities: branches=32, max_precise=3, pmu_name=skylake

Note that: this patch is on tmp.perf/core.

Signed-off-by: Jin Yao <[email protected]>
---
tools/perf/util/env.c | 6 ++
tools/perf/util/env.h | 11 ++-
tools/perf/util/header.c | 175 ++++++++++++++++++++++++++++++++++-----
3 files changed, 168 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 9e05eca324a1..8ef24aad2152 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -208,6 +208,12 @@ void perf_env__exit(struct perf_env *env)
zfree(&env->hybrid_nodes[i].pmu_name);
}
zfree(&env->hybrid_nodes);
+
+ for (i = 0; i < env->nr_cpu_pmu_caps_nodes; i++) {
+ zfree(&env->cpu_pmu_caps_nodes[i].cpu_pmu_caps);
+ zfree(&env->cpu_pmu_caps_nodes[i].pmu_name);
+ }
+ zfree(&env->cpu_pmu_caps_nodes);
}

void perf_env__init(struct perf_env *env __maybe_unused)
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 9ca7633787e1..5552c98a6a76 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -42,6 +42,13 @@ struct hybrid_node {
struct perf_cpu_map *map;
};

+struct cpu_pmu_caps_node {
+ int nr_cpu_pmu_caps;
+ unsigned int max_branches;
+ char *cpu_pmu_caps;
+ char *pmu_name;
+};
+
struct perf_env {
char *hostname;
char *os_release;
@@ -63,15 +70,14 @@ struct perf_env {
int nr_memory_nodes;
int nr_pmu_mappings;
int nr_groups;
- int nr_cpu_pmu_caps;
int nr_hybrid_nodes;
+ int nr_cpu_pmu_caps_nodes;
char *cmdline;
const char **cmdline_argv;
char *sibling_cores;
char *sibling_dies;
char *sibling_threads;
char *pmu_mappings;
- char *cpu_pmu_caps;
struct cpu_topology_map *cpu;
struct cpu_cache_level *caches;
int caches_cnt;
@@ -84,6 +90,7 @@ struct perf_env {
struct memory_node *memory_nodes;
unsigned long long memory_bsize;
struct hybrid_node *hybrid_nodes;
+ struct cpu_pmu_caps_node *cpu_pmu_caps_nodes;
#ifdef HAVE_LIBBPF_SUPPORT
/*
* bpf_info_lock protects bpf rbtrees. This is needed because the
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index dff89c0be79c..6989c57b57e6 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -49,6 +49,7 @@
#include "cputopo.h"
#include "bpf-event.h"
#include "clockid.h"
+#include "pmu-hybrid.h"

#include <linux/ctype.h>
#include <internal/lib.h>
@@ -1459,18 +1460,22 @@ static int write_compressed(struct feat_fd *ff __maybe_unused,
return do_write(ff, &(ff->ph->env.comp_mmap_len), sizeof(ff->ph->env.comp_mmap_len));
}

-static int write_cpu_pmu_caps(struct feat_fd *ff,
- struct evlist *evlist __maybe_unused)
+static int write_per_cpu_pmu_caps(struct feat_fd *ff, struct perf_pmu *pmu,
+ int nr)
{
- struct perf_pmu *cpu_pmu = perf_pmu__find("cpu");
struct perf_pmu_caps *caps = NULL;
int nr_caps;
int ret;

- if (!cpu_pmu)
- return -ENOENT;
-
- nr_caps = perf_pmu__caps_parse(cpu_pmu);
+ /*
+ * The layout is:
+ * <nr_caps>
+ * <caps string>
+ * <caps string>
+ * <pmu name>
+ * <nr of rest pmus>
+ */
+ nr_caps = perf_pmu__caps_parse(pmu);
if (nr_caps < 0)
return nr_caps;

@@ -1478,7 +1483,7 @@ static int write_cpu_pmu_caps(struct feat_fd *ff,
if (ret < 0)
return ret;

- list_for_each_entry(caps, &cpu_pmu->caps, list) {
+ list_for_each_entry(caps, &pmu->caps, list) {
ret = do_write_string(ff, caps->name);
if (ret < 0)
return ret;
@@ -1488,9 +1493,49 @@ static int write_cpu_pmu_caps(struct feat_fd *ff,
return ret;
}

+ ret = do_write_string(ff, pmu->name);
+ if (ret < 0)
+ return ret;
+
+ ret = do_write(ff, &nr, sizeof(nr));
+ if (ret < 0)
+ return ret;
+
return ret;
}

+static int write_cpu_pmu_caps(struct feat_fd *ff,
+ struct evlist *evlist __maybe_unused)
+{
+ struct perf_pmu *pmu = perf_pmu__find("cpu");
+ u32 nr;
+ int ret;
+
+ if (pmu)
+ nr = 1;
+ else {
+ nr = perf_pmu__hybrid_pmu_num();
+ pmu = NULL;
+ }
+
+ if (nr == 0)
+ return -1;
+
+ if (pmu) {
+ ret = write_per_cpu_pmu_caps(ff, pmu, 0);
+ if (ret < 0)
+ return ret;
+ } else {
+ perf_pmu__for_each_hybrid_pmu(pmu) {
+ ret = write_per_cpu_pmu_caps(ff, pmu, --nr);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static void print_hostname(struct feat_fd *ff, FILE *fp)
{
fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
@@ -1963,18 +2008,28 @@ static void print_compressed(struct feat_fd *ff, FILE *fp)
ff->ph->env.comp_level, ff->ph->env.comp_ratio);
}

-static void print_cpu_pmu_caps(struct feat_fd *ff, FILE *fp)
+static void print_per_cpu_pmu_caps(FILE *fp, struct cpu_pmu_caps_node *n)
{
- const char *delimiter = "# cpu pmu capabilities: ";
- u32 nr_caps = ff->ph->env.nr_cpu_pmu_caps;
- char *str;
+ const char *delimiter;
+ u32 nr_caps = n->nr_cpu_pmu_caps;
+ char *str, buf[128];

if (!nr_caps) {
- fprintf(fp, "# cpu pmu capabilities: not available\n");
+ if (!n->pmu_name)
+ fprintf(fp, "# cpu pmu capabilities: not available\n");
+ else
+ fprintf(fp, "# %s pmu capabilities: not available\n", n->pmu_name);
return;
}

- str = ff->ph->env.cpu_pmu_caps;
+ if (!n->pmu_name)
+ scnprintf(buf, sizeof(buf), "# cpu pmu capabilities: ");
+ else
+ scnprintf(buf, sizeof(buf), "# %s pmu capabilities: ", n->pmu_name);
+
+ delimiter = buf;
+
+ str = n->cpu_pmu_caps;
while (nr_caps--) {
fprintf(fp, "%s%s", delimiter, str);
delimiter = ", ";
@@ -1984,6 +2039,17 @@ static void print_cpu_pmu_caps(struct feat_fd *ff, FILE *fp)
fprintf(fp, "\n");
}

+static void print_cpu_pmu_caps(struct feat_fd *ff, FILE *fp)
+{
+ struct cpu_pmu_caps_node *n;
+ int i;
+
+ for (i = 0; i < ff->ph->env.nr_cpu_pmu_caps_nodes; i++) {
+ n = &ff->ph->env.cpu_pmu_caps_nodes[i];
+ print_per_cpu_pmu_caps(fp, n);
+ }
+}
+
static void print_pmu_mappings(struct feat_fd *ff, FILE *fp)
{
const char *delimiter = "# pmu mappings: ";
@@ -3093,13 +3159,14 @@ static int process_compressed(struct feat_fd *ff,
return 0;
}

-static int process_cpu_pmu_caps(struct feat_fd *ff,
- void *data __maybe_unused)
+static int process_cpu_pmu_caps_node(struct feat_fd *ff,
+ struct cpu_pmu_caps_node *n, bool *end)
{
- char *name, *value;
+ char *name, *value, *pmu_name;
struct strbuf sb;
- u32 nr_caps;
+ u32 nr_caps, nr;

+ *end = false;
if (do_read_u32(ff, &nr_caps))
return -1;

@@ -3108,7 +3175,7 @@ static int process_cpu_pmu_caps(struct feat_fd *ff,
return 0;
}

- ff->ph->env.nr_cpu_pmu_caps = nr_caps;
+ n->nr_cpu_pmu_caps = nr_caps;

if (strbuf_init(&sb, 128) < 0)
return -1;
@@ -3129,13 +3196,33 @@ static int process_cpu_pmu_caps(struct feat_fd *ff,
if (strbuf_add(&sb, "", 1) < 0)
goto free_value;

- if (!strcmp(name, "branches"))
- ff->ph->env.max_branches = atoi(value);
+ if (!strcmp(name, "branches")) {
+ n->max_branches = atoi(value);
+ if (n->max_branches > ff->ph->env.max_branches)
+ ff->ph->env.max_branches = n->max_branches;
+ }

free(value);
free(name);
}
- ff->ph->env.cpu_pmu_caps = strbuf_detach(&sb, NULL);
+
+ /*
+ * Old perf.data may not have pmu_name,
+ */
+ pmu_name = do_read_string(ff);
+ if (!pmu_name || strncmp(pmu_name, "cpu_", 4)) {
+ *end = true;
+ goto out;
+ }
+
+ if (do_read_u32(ff, &nr))
+ return -1;
+
+ if (nr == 0)
+ *end = true;
+out:
+ n->cpu_pmu_caps = strbuf_detach(&sb, NULL);
+ n->pmu_name = pmu_name;
return 0;

free_value:
@@ -3147,6 +3234,50 @@ static int process_cpu_pmu_caps(struct feat_fd *ff,
return -1;
}

+static int process_cpu_pmu_caps(struct feat_fd *ff,
+ void *data __maybe_unused)
+{
+ struct cpu_pmu_caps_node *nodes = NULL, *tmp;
+ int ret, i, nr_alloc = 1, nr_used = 0;
+ bool end;
+
+ while (1) {
+ if (nr_used == nr_alloc || !nodes) {
+ nr_alloc *= 2;
+ tmp = realloc(nodes, sizeof(*nodes) * nr_alloc);
+ if (!tmp)
+ return -ENOMEM;
+ memset(tmp + nr_used, 0,
+ sizeof(*nodes) * (nr_alloc - nr_used));
+ nodes = tmp;
+ }
+
+ ret = process_cpu_pmu_caps_node(ff, &nodes[nr_used], &end);
+ if (ret) {
+ if (nr_used)
+ break;
+ goto err;
+ }
+
+ nr_used++;
+ if (end)
+ break;
+ }
+
+ ff->ph->env.nr_cpu_pmu_caps_nodes = (u32)nr_used;
+ ff->ph->env.cpu_pmu_caps_nodes = nodes;
+ return 0;
+
+err:
+ for (i = 0; i < nr_used; i++) {
+ free(nodes[i].cpu_pmu_caps);
+ free(nodes[i].pmu_name);
+ }
+
+ free(nodes);
+ return ret;
+}
+
#define FEAT_OPR(n, func, __full_only) \
[HEADER_##n] = { \
.name = __stringify(n), \
--
2.17.1


2021-05-04 15:10:00

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH v1 2/2] perf header: Support hybrid CPU_PMU_CAPS

On Fri, Apr 30, 2021 at 03:46:02PM +0800, Jin Yao wrote:
> On hybrid platform, it may have several cpu pmus, such as,
> "cpu_core" and "cpu_atom". The CPU_PMU_CAPS feature in perf
> header needs to be improved to support multiple cpu pmus.
>
> The new layout in header is defined as:
>
> <nr_caps>
> <caps string>
> <caps string>
> <pmu name>
> <nr of rest pmus>

not sure why is the 'nr of rest pmus' needed

the current format is:

u32 nr_cpu_pmu_caps;
{
char name[];
char value[];
} [nr_cpu_pmu_caps]


I guess we could extend it to:

u32 nr_cpu_pmu_caps;
{
char name[];
char value[];
} [nr_cpu_pmu_caps]
char pmu_name[]

u32 nr_cpu_pmu_caps;
{
char name[];
char value[];
} [nr_cpu_pmu_caps]
char pmu_name[]

...

and we could detect the old format by checking that there's no
pmu name.. but maybe I'm missing something, I did not check deeply,
please let me know

also would be great to move the format change and storing hybrid
pmus in separate patches

thanks,
jirka

2021-05-06 05:02:14

by Jin Yao

[permalink] [raw]
Subject: Re: [PATCH v1 2/2] perf header: Support hybrid CPU_PMU_CAPS

Hi Jiri,

On 5/4/2021 11:07 PM, Jiri Olsa wrote:
> On Fri, Apr 30, 2021 at 03:46:02PM +0800, Jin Yao wrote:
>> On hybrid platform, it may have several cpu pmus, such as,
>> "cpu_core" and "cpu_atom". The CPU_PMU_CAPS feature in perf
>> header needs to be improved to support multiple cpu pmus.
>>
>> The new layout in header is defined as:
>>
>> <nr_caps>
>> <caps string>
>> <caps string>
>> <pmu name>
>> <nr of rest pmus>
>
> not sure why is the 'nr of rest pmus' needed
>

The 'nr of rest pmus' indicates the remaining pmus which are waiting for process.

For example,

<nr_caps>
<caps string>
"cpu_core"
1
<nr_caps>
<caps string>
"cpu_atom"
0

When we see '0' in data file processing, we know all the pmu have been processed yet.

> the current format is:
>
> u32 nr_cpu_pmu_caps;
> {
> char name[];
> char value[];
> } [nr_cpu_pmu_caps]
>
>
> I guess we could extend it to:
>
> u32 nr_cpu_pmu_caps;
> {
> char name[];
> char value[];
> } [nr_cpu_pmu_caps]
> char pmu_name[]
>
> u32 nr_cpu_pmu_caps;
> {
> char name[];
> char value[];
> } [nr_cpu_pmu_caps]
> char pmu_name[]
>
> ...
>
> and we could detect the old format by checking that there's no
> pmu name.. but maybe I'm missing something, I did not check deeply,
> please let me know
>

Actually we do the same thing, but I just add an extra 'nr of rest pmus' after the pmu_name. The
purpose of 'nr of rest pmus' is when we see '0' at 'nr of rest pmus', we know that all pmus have
been processed.

Otherwise, we have to continue reading data file till we find something incorrect and then finally
drop the last read data.

So is this solution acceptable?

> also would be great to move the format change and storing hybrid
> pmus in separate patches
>

Maybe we have to put the storing and processing into one patch.

Say patch 1 contains the format change and storing hybrid pmus. And patch 2 contains the processing
for the new format. If the repo only contains the patch 1, I'm afraid that may introduce the
compatible issue.

Thanks
Jin Yao

> thanks,
> jirka
>

2021-05-06 13:26:19

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH v1 2/2] perf header: Support hybrid CPU_PMU_CAPS

On Thu, May 06, 2021 at 12:59:08PM +0800, Jin, Yao wrote:
> Hi Jiri,
>
> On 5/4/2021 11:07 PM, Jiri Olsa wrote:
> > On Fri, Apr 30, 2021 at 03:46:02PM +0800, Jin Yao wrote:
> > > On hybrid platform, it may have several cpu pmus, such as,
> > > "cpu_core" and "cpu_atom". The CPU_PMU_CAPS feature in perf
> > > header needs to be improved to support multiple cpu pmus.
> > >
> > > The new layout in header is defined as:
> > >
> > > <nr_caps>
> > > <caps string>
> > > <caps string>
> > > <pmu name>
> > > <nr of rest pmus>
> >
> > not sure why is the 'nr of rest pmus' needed
> >
>
> The 'nr of rest pmus' indicates the remaining pmus which are waiting for process.
>
> For example,
>
> <nr_caps>
> <caps string>
> "cpu_core"
> 1
> <nr_caps>
> <caps string>
> "cpu_atom"
> 0
>
> When we see '0' in data file processing, we know all the pmu have been processed yet.
>
> > the current format is:
> >
> > u32 nr_cpu_pmu_caps;
> > {
> > char name[];
> > char value[];
> > } [nr_cpu_pmu_caps]
> >
> >
> > I guess we could extend it to:
> >
> > u32 nr_cpu_pmu_caps;
> > {
> > char name[];
> > char value[];
> > } [nr_cpu_pmu_caps]
> > char pmu_name[]
> >
> > u32 nr_cpu_pmu_caps;
> > {
> > char name[];
> > char value[];
> > } [nr_cpu_pmu_caps]
> > char pmu_name[]
> >
> > ...
> >
> > and we could detect the old format by checking that there's no
> > pmu name.. but maybe I'm missing something, I did not check deeply,
> > please let me know
> >
>
> Actually we do the same thing, but I just add an extra 'nr of rest pmus'
> after the pmu_name. The purpose of 'nr of rest pmus' is when we see '0' at
> 'nr of rest pmus', we know that all pmus have been processed.
>
> Otherwise, we have to continue reading data file till we find something
> incorrect and then finally drop the last read data.

you have the size of the feature data right? I think we use
it in other cases to check if there are more data

>
> So is this solution acceptable?
>
> > also would be great to move the format change and storing hybrid
> > pmus in separate patches
> >
>
> Maybe we have to put the storing and processing into one patch.
>
> Say patch 1 contains the format change and storing hybrid pmus. And patch 2
> contains the processing for the new format. If the repo only contains the
> patch 1, I'm afraid that may introduce the compatible issue.

maybe you can have change of caps format in one patch
and storing/processing hybrid pmus in another?

jirka

2021-05-06 14:44:45

by Jin Yao

[permalink] [raw]
Subject: Re: [PATCH v1 2/2] perf header: Support hybrid CPU_PMU_CAPS

Hi Jiri,

On 5/6/2021 9:22 PM, Jiri Olsa wrote:
> On Thu, May 06, 2021 at 12:59:08PM +0800, Jin, Yao wrote:
>> Hi Jiri,
>>
>> On 5/4/2021 11:07 PM, Jiri Olsa wrote:
>>> On Fri, Apr 30, 2021 at 03:46:02PM +0800, Jin Yao wrote:
>>>> On hybrid platform, it may have several cpu pmus, such as,
>>>> "cpu_core" and "cpu_atom". The CPU_PMU_CAPS feature in perf
>>>> header needs to be improved to support multiple cpu pmus.
>>>>
>>>> The new layout in header is defined as:
>>>>
>>>> <nr_caps>
>>>> <caps string>
>>>> <caps string>
>>>> <pmu name>
>>>> <nr of rest pmus>
>>>
>>> not sure why is the 'nr of rest pmus' needed
>>>
>>
>> The 'nr of rest pmus' indicates the remaining pmus which are waiting for process.
>>
>> For example,
>>
>> <nr_caps>
>> <caps string>
>> "cpu_core"
>> 1
>> <nr_caps>
>> <caps string>
>> "cpu_atom"
>> 0
>>
>> When we see '0' in data file processing, we know all the pmu have been processed yet.
>>
>>> the current format is:
>>>
>>> u32 nr_cpu_pmu_caps;
>>> {
>>> char name[];
>>> char value[];
>>> } [nr_cpu_pmu_caps]
>>>
>>>
>>> I guess we could extend it to:
>>>
>>> u32 nr_cpu_pmu_caps;
>>> {
>>> char name[];
>>> char value[];
>>> } [nr_cpu_pmu_caps]
>>> char pmu_name[]
>>>
>>> u32 nr_cpu_pmu_caps;
>>> {
>>> char name[];
>>> char value[];
>>> } [nr_cpu_pmu_caps]
>>> char pmu_name[]
>>>
>>> ...
>>>
>>> and we could detect the old format by checking that there's no
>>> pmu name.. but maybe I'm missing something, I did not check deeply,
>>> please let me know
>>>
>>
>> Actually we do the same thing, but I just add an extra 'nr of rest pmus'
>> after the pmu_name. The purpose of 'nr of rest pmus' is when we see '0' at
>> 'nr of rest pmus', we know that all pmus have been processed.
>>
>> Otherwise, we have to continue reading data file till we find something
>> incorrect and then finally drop the last read data.
>
> you have the size of the feature data right? I think we use
> it in other cases to check if there are more data
>

The challenge for us is if we need to compatible with the old perf.data which was generated by old
perf tool.

For the old perf.data, the layout in header is:

nr of caps
caps string 1
caps string 2
...
caps string N

It doesn't carry with any other fields such as size of caps data.

To be compatible with old perf.data, so I have to extend the layout to:

nr of caps for pmu 1
caps string 1
caps string 2
...
caps string N
name of pmu 1
nr of rest pmus

nr of caps for pmu2
caps string 1
caps string 2
...
caps string N
name of pmu 2
nr of rest pmus

When the new perf tool detects the string such as "cpu_", it can know that it's the pmu name field
in new perf.data, otherwise it's the old perf.data.

If we add new field such as "size" to the layout, I'm afraid the new perf tool can not process the
old perf.data correctly.

If we don't need to support old perf.data, that makes things easy.

>>
>> So is this solution acceptable?
>>
>>> also would be great to move the format change and storing hybrid
>>> pmus in separate patches
>>>
>>
>> Maybe we have to put the storing and processing into one patch.
>>
>> Say patch 1 contains the format change and storing hybrid pmus. And patch 2
>> contains the processing for the new format. If the repo only contains the
>> patch 1, I'm afraid that may introduce the compatible issue.
>
> maybe you can have change of caps format in one patch
> and storing/processing hybrid pmus in another?
>

But there is no data structure defined in header.h for each feature.

It directly uses do_write/do_write_string in 'write()' ops to write the feature data.

So for the new layout, as I mentioned above, if we change the layout to

nr of caps for pmu 1
caps string 1
caps string 2
...
caps string N
"cpu"
0

We need to call do_write/do_write_string, actually it's the storing method. So I don't understand
well for having changes of caps format in one patch, I'm sorry about that. :(

Thanks
Jin Yao

> jirka
>

2021-05-10 13:16:37

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH v1 2/2] perf header: Support hybrid CPU_PMU_CAPS

On Thu, May 06, 2021 at 10:43:39PM +0800, Jin, Yao wrote:

SNIP

> > > 'nr of rest pmus', we know that all pmus have been processed.
> > >
> > > Otherwise, we have to continue reading data file till we find something
> > > incorrect and then finally drop the last read data.
> >
> > you have the size of the feature data right? I think we use
> > it in other cases to check if there are more data
> >
>
> The challenge for us is if we need to compatible with the old perf.data
> which was generated by old perf tool.
>
> For the old perf.data, the layout in header is:
>
> nr of caps
> caps string 1
> caps string 2
> ...
> caps string N
>
> It doesn't carry with any other fields such as size of caps data.
>
> To be compatible with old perf.data, so I have to extend the layout to:
>
> nr of caps for pmu 1
> caps string 1
> caps string 2
> ...
> caps string N
> name of pmu 1
> nr of rest pmus
>
> nr of caps for pmu2
> caps string 1
> caps string 2
> ...
> caps string N
> name of pmu 2
> nr of rest pmus
>
> When the new perf tool detects the string such as "cpu_", it can know that
> it's the pmu name field in new perf.data, otherwise it's the old perf.data.

what if the cap string starts with 'cpu_' ?

I think it might be better to create new feature that
stores caps for multiple pmus in generic way

>
> If we add new field such as "size" to the layout, I'm afraid the new perf
> tool can not process the old perf.data correctly.
>
> If we don't need to support old perf.data, that makes things easy.

we need to

jirka

2021-05-11 01:18:54

by Jin Yao

[permalink] [raw]
Subject: Re: [PATCH v1 2/2] perf header: Support hybrid CPU_PMU_CAPS

Hi Jiri,

On 5/10/2021 9:11 PM, Jiri Olsa wrote:
> On Thu, May 06, 2021 at 10:43:39PM +0800, Jin, Yao wrote:
>
> SNIP
>
>>>> 'nr of rest pmus', we know that all pmus have been processed.
>>>>
>>>> Otherwise, we have to continue reading data file till we find something
>>>> incorrect and then finally drop the last read data.
>>>
>>> you have the size of the feature data right? I think we use
>>> it in other cases to check if there are more data
>>>
>>
>> The challenge for us is if we need to compatible with the old perf.data
>> which was generated by old perf tool.
>>
>> For the old perf.data, the layout in header is:
>>
>> nr of caps
>> caps string 1
>> caps string 2
>> ...
>> caps string N
>>
>> It doesn't carry with any other fields such as size of caps data.
>>
>> To be compatible with old perf.data, so I have to extend the layout to:
>>
>> nr of caps for pmu 1
>> caps string 1
>> caps string 2
>> ...
>> caps string N
>> name of pmu 1
>> nr of rest pmus
>>
>> nr of caps for pmu2
>> caps string 1
>> caps string 2
>> ...
>> caps string N
>> name of pmu 2
>> nr of rest pmus
>>
>> When the new perf tool detects the string such as "cpu_", it can know that
>> it's the pmu name field in new perf.data, otherwise it's the old perf.data.
>
> what if the cap string starts with 'cpu_' ?
>

I just assume the cap string would not have 'cpu_' string. Yes, I agree, that's not a very good
solution.

> I think it might be better to create new feature that
> stores caps for multiple pmus in generic way
>

Yes, creating a new feature in header (such as "HYBRID_CPU_PMU_CAPS") is a better way.

>>
>> If we add new field such as "size" to the layout, I'm afraid the new perf
>> tool can not process the old perf.data correctly.
>>
>> If we don't need to support old perf.data, that makes things easy.
>
> we need to
>

Yes, we need to. I'm now preparing v3.

Thanks
Jin Yao

> jirka
>