2015-08-31 18:37:20

by Liang, Kan

[permalink] [raw]
Subject: [PATCH V3 1/3] perf,tools: Separated functions to get core_id and socket_id

From: Kan Liang <[email protected]>

This patch moves the codes which read core_id and socket_id into
separated functions, and expose them.

Signed-off-by: Kan Liang <[email protected]>
---
tools/perf/util/cpumap.c | 51 +++++++++++++++++++++++++++++++-----------------
tools/perf/util/cpumap.h | 2 ++
2 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 3667e21..a05d76a 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -225,17 +225,12 @@ void cpu_map__put(struct cpu_map *map)
cpu_map__delete(map);
}

-int cpu_map__get_socket(struct cpu_map *map, int idx)
+int cpu_map__get_socket_id(int cpu)
{
FILE *fp;
const char *mnt;
char path[PATH_MAX];
- int cpu, ret;
-
- if (idx > map->nr)
- return -1;
-
- cpu = map->map[idx];
+ int socket_id, ret;

mnt = sysfs__mountpoint();
if (!mnt)
@@ -248,9 +243,22 @@ int cpu_map__get_socket(struct cpu_map *map, int idx)
fp = fopen(path, "r");
if (!fp)
return -1;
- ret = fscanf(fp, "%d", &cpu);
+ ret = fscanf(fp, "%d", &socket_id);
fclose(fp);
- return ret == 1 ? cpu : -1;
+
+ return ret == 1 ? socket_id : -1;
+}
+
+int cpu_map__get_socket(struct cpu_map *map, int idx)
+{
+ int cpu;
+
+ if (idx > map->nr)
+ return -1;
+
+ cpu = map->map[idx];
+
+ return cpu_map__get_socket_id(cpu);
}

static int cmp_ids(const void *a, const void *b)
@@ -289,17 +297,12 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
return 0;
}

-int cpu_map__get_core(struct cpu_map *map, int idx)
+int cpu_map__get_core_id(int cpu)
{
FILE *fp;
const char *mnt;
char path[PATH_MAX];
- int cpu, ret, s;
-
- if (idx > map->nr)
- return -1;
-
- cpu = map->map[idx];
+ int core_id, ret;

mnt = sysfs__mountpoint();
if (!mnt)
@@ -312,11 +315,23 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
fp = fopen(path, "r");
if (!fp)
return -1;
- ret = fscanf(fp, "%d", &cpu);
+ ret = fscanf(fp, "%d", &core_id);
fclose(fp);
- if (ret != 1)
+
+ return ret == 1 ? core_id : -1;
+}
+
+int cpu_map__get_core(struct cpu_map *map, int idx)
+{
+ int cpu, s;
+
+ if (idx > map->nr)
return -1;

+ cpu = map->map[idx];
+
+ cpu = cpu_map__get_core_id(cpu);
+
s = cpu_map__get_socket(map, idx);
if (s == -1)
return -1;
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 0af9cec..8982d53 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -18,7 +18,9 @@ struct cpu_map *cpu_map__new(const char *cpu_list);
struct cpu_map *cpu_map__dummy_new(void);
struct cpu_map *cpu_map__read(FILE *file);
size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
+int cpu_map__get_socket_id(int cpu);
int cpu_map__get_socket(struct cpu_map *map, int idx);
+int cpu_map__get_core_id(int cpu);
int cpu_map__get_core(struct cpu_map *map, int idx);
int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep);
--
1.8.3.1


2015-08-31 18:37:21

by Liang, Kan

[permalink] [raw]
Subject: [PATCH V3 2/3] perf,tools: store cpu socket_id and core_id in perf.date

From: Kan Liang <[email protected]>

This patch stores cpu socket_id and core_id in perf.date, and read them
to perf_env in header process.
Although the changes modify the CPU_TOPOLOGY feature, the old perf still
can correctly read new perf.data. Because the new codes are added at the
end of the cpu_topology section. The old perf can ignore the extra data.
For reading old perf.data, new perf will error out and leave message in
debug mode. So the user can upgrade the perf accordingly.

Signed-off-by: Kan Liang <[email protected]>
---

Changes since V1:
- Store core_id and socket_id in perf.date

Changes since V2:
- Use funcitons in cpumap.c to get core_id and socket_id
- Modify changelog

tools/perf/util/header.c | 72 ++++++++++++++++++++++++++++++++++++++++++++---
tools/perf/util/header.h | 6 ++++
tools/perf/util/session.c | 1 +
3 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 4181454..a1451f3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -441,10 +441,13 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
"/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"

struct cpu_topo {
+ u32 cpu_nr;
u32 core_sib;
u32 thread_sib;
char **core_siblings;
char **thread_siblings;
+ int *core_id;
+ int *phy_pkg_id;
};

static int build_cpu_topo(struct cpu_topo *tp, int cpu)
@@ -507,6 +510,9 @@ try_threads:
}
ret = 0;
done:
+ tp->core_id[cpu] = cpu_map__get_core_id(cpu);
+ tp->phy_pkg_id[cpu] = cpu_map__get_socket_id(cpu);
+
if(fp)
fclose(fp);
free(buf);
@@ -534,7 +540,7 @@ static struct cpu_topo *build_cpu_topology(void)
struct cpu_topo *tp;
void *addr;
u32 nr, i;
- size_t sz;
+ size_t sz, sz_id;
long ncpus;
int ret = -1;

@@ -545,17 +551,22 @@ static struct cpu_topo *build_cpu_topology(void)
nr = (u32)(ncpus & UINT_MAX);

sz = nr * sizeof(char *);
+ sz_id = nr * sizeof(int);

- addr = calloc(1, sizeof(*tp) + 2 * sz);
+ addr = calloc(1, sizeof(*tp) + 2 * sz + 2 * sz_id);
if (!addr)
return NULL;

tp = addr;
-
+ tp->cpu_nr = nr;
addr += sizeof(*tp);
tp->core_siblings = addr;
addr += sz;
tp->thread_siblings = addr;
+ addr += sz;
+ tp->core_id = addr;
+ addr += sz_id;
+ tp->phy_pkg_id = addr;

for (i = 0; i < nr; i++) {
ret = build_cpu_topo(tp, i);
@@ -598,6 +609,15 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
if (ret < 0)
break;
}
+
+ for (i = 0; i < tp->cpu_nr; i++) {
+ ret = do_write(fd, &tp->core_id[i], sizeof(int));
+ if (ret < 0)
+ return ret;
+ ret = do_write(fd, &tp->phy_pkg_id[i], sizeof(int));
+ if (ret < 0)
+ return ret;
+ }
done:
free_cpu_topo(tp);
return ret;
@@ -938,6 +958,7 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
{
int nr, i;
char *str;
+ int cpu_nr = ph->env.nr_cpus_online;

nr = ph->env.nr_sibling_cores;
str = ph->env.sibling_cores;
@@ -954,6 +975,10 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
fprintf(fp, "# sibling threads : %s\n", str);
str += strlen(str) + 1;
}
+
+ for (i = 0; i < cpu_nr; i++)
+ fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i,
+ ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id);
}

static void free_event_desc(struct perf_evsel *events)
@@ -1590,10 +1615,15 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
u32 nr, i;
char *str;
struct strbuf sb;
+ int cpu_nr = ph->env.nr_cpus_online;
+
+ ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
+ if (!ph->env.cpu)
+ return -1;

ret = readn(fd, &nr, sizeof(nr));
if (ret != sizeof(nr))
- return -1;
+ goto free_cpu;

if (ph->needs_swap)
nr = bswap_32(nr);
@@ -1631,10 +1661,44 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
free(str);
}
ph->env.sibling_threads = strbuf_detach(&sb, NULL);
+
+ for (i = 0; i < (u32)cpu_nr; i++) {
+ ret = readn(fd, &nr, sizeof(nr));
+ if (ret != sizeof(nr))
+ goto free_cpu;
+
+ if (ph->needs_swap)
+ nr = bswap_32(nr);
+
+ if (nr > (u32)cpu_nr) {
+ pr_debug("core_id number is too big."
+ "You may need to upgrade the perf tool.\n");
+ goto free_cpu;
+ }
+ ph->env.cpu[i].core_id = nr;
+
+ ret = readn(fd, &nr, sizeof(nr));
+ if (ret != sizeof(nr))
+ goto free_cpu;
+
+ if (ph->needs_swap)
+ nr = bswap_32(nr);
+
+ if (nr > (u32)cpu_nr) {
+ pr_debug("socket_id number is too big."
+ "You may need to upgrade the perf tool.\n");
+ goto free_cpu;
+ }
+
+ ph->env.cpu[i].socket_id = nr;
+ }
+
return 0;

error:
strbuf_release(&sb);
+free_cpu:
+ free(ph->env.cpu);
return -1;
}

diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 396e496..975d803 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -66,6 +66,11 @@ struct perf_header;
int perf_file_header__read(struct perf_file_header *header,
struct perf_header *ph, int fd);

+struct cpu_topology_map {
+ int socket_id;
+ int core_id;
+};
+
struct perf_env {
char *hostname;
char *os_release;
@@ -89,6 +94,7 @@ struct perf_env {
char *sibling_threads;
char *numa_nodes;
char *pmu_mappings;
+ struct cpu_topology_map *cpu;
};

struct perf_header {
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8a4537e..61669be 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -185,6 +185,7 @@ static void perf_session_env__exit(struct perf_env *env)
zfree(&env->sibling_threads);
zfree(&env->numa_nodes);
zfree(&env->pmu_mappings);
+ zfree(&env->cpu);
}

void perf_session__delete(struct perf_session *session)
--
1.8.3.1

2015-08-31 18:37:46

by Liang, Kan

[permalink] [raw]
Subject: [PATCH V3 3/3] perf,test: test cpu topology

From: Jiri Olsa <[email protected]>

This patch test cpu core_id and socket_id which are stored in perf_env.

Signed-off-by: Jiri Olsa <[email protected]>
Signed-off-by: Kan Liang <[email protected]>
---

Changes since jirka's original version
- Use pr_debug to replace fprintf
- Add date_size to avoid warning
- Introduce cpu_map, and compare core_id and socket_id
between cpu_map and perf_env

Changes since V2:
- unlink(path)

tools/perf/tests/Build | 1 +
tools/perf/tests/builtin-test.c | 4 ++
tools/perf/tests/tests.h | 1 +
tools/perf/tests/topology.c | 86 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 92 insertions(+)
create mode 100644 tools/perf/tests/topology.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index c1518bd..208bbdf 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -33,6 +33,7 @@ perf-y += parse-no-sample-id-all.o
perf-y += kmod-path.o
perf-y += thread-map.o
perf-y += llvm.o
+perf-y += topology.o

perf-$(CONFIG_X86) += perf-time-to-tsc.o

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 136cd93..6650f26 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -179,6 +179,10 @@ static struct test {
.func = test__llvm,
},
{
+ .desc = "Test topology in session",
+ .func = test_session_topology,
+ },
+ {
.func = NULL,
},
};
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index bf113a2..95654d7 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -63,6 +63,7 @@ int test__fdarray__add(void);
int test__kmod_path__parse(void);
int test__thread_map(void);
int test__llvm(void);
+int test_session_topology(void);

#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
new file mode 100644
index 0000000..c5345c9
--- /dev/null
+++ b/tools/perf/tests/topology.c
@@ -0,0 +1,86 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "tests.h"
+#include "util.h"
+#include "session.h"
+#include "evlist.h"
+#include "debug.h"
+
+#define TEMPL "/tmp/perf-test-XXXXXX"
+#define DATA_SIZE 10
+
+static int get_temp(char *path)
+{
+ int fd;
+
+ strcpy(path, TEMPL);
+
+ fd = mkstemp(path);
+ if (fd < 0) {
+ perror("mkstemp failed");
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
+int test_session_topology(void)
+{
+ struct perf_session *session;
+ char path[PATH_MAX];
+ struct cpu_map *map;
+ struct perf_data_file file = {
+ .path = path,
+ .mode = PERF_DATA_MODE_WRITE,
+ };
+ int i;
+
+ TEST_ASSERT_VAL("can't get templ file", !get_temp(path));
+
+ pr_debug("krava %s\n", path);
+
+ session = perf_session__new(&file, false, NULL);
+ TEST_ASSERT_VAL("can't get session", session);
+
+ session->evlist = perf_evlist__new_default();
+ TEST_ASSERT_VAL("can't get evlist", session->evlist);
+
+ perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
+ perf_header__set_feat(&session->header, HEADER_NRCPUS);
+
+ session->header.data_size += DATA_SIZE;
+
+ TEST_ASSERT_VAL("failed to write header",
+ !perf_session__write_header(session, session->evlist, file.fd, true));
+
+ perf_session__delete(session);
+
+ map = cpu_map__new(NULL);
+ TEST_ASSERT_VAL("failed to get system cpumap", !(map == NULL));
+
+ file.mode = PERF_DATA_MODE_READ;
+ session = perf_session__new(&file, false, NULL);
+ TEST_ASSERT_VAL("can't get session", session);
+
+ for (i = 0; i < session->header.env.nr_cpus_online; i++) {
+ pr_debug("CPU %d, core %d, socket %d\n", i,
+ session->header.env.cpu[i].core_id,
+ session->header.env.cpu[i].socket_id);
+ }
+
+ for (i = 0; i < map->nr; i++) {
+ TEST_ASSERT_VAL("Core ID doesn't match",
+ (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i) & 0xffff)));
+
+ TEST_ASSERT_VAL("Socket ID doesn't match",
+ (session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i)));
+ }
+
+ perf_session__delete(session);
+ cpu_map__put(map);
+ unlink(path);
+
+ return 0;
+}
--
1.8.3.1

2015-08-31 20:08:28

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH V3 2/3] perf,tools: store cpu socket_id and core_id in perf.date

Em Mon, Aug 31, 2015 at 07:21:21AM -0400, Kan Liang escreveu:
> From: Kan Liang <[email protected]>
>
> This patch stores cpu socket_id and core_id in perf.date, and read them
> to perf_env in header process.
> Although the changes modify the CPU_TOPOLOGY feature, the old perf still
> can correctly read new perf.data. Because the new codes are added at the
> end of the cpu_topology section. The old perf can ignore the extra data.

> For reading old perf.data, new perf will error out and leave message in
> debug mode. So the user can upgrade the perf accordingly.

So the "new perf" will just flat out refuse processing old perf.data files,
even when it doesn't need this? Lemme try... Doesn't look like that from my
testing...

So this is all about some specific perf.data file analysis, i.e. not applicable
to a plain "perf record ; perf report" canonical session?

I.e. I tried the "old perf" with "new perf.data" and "new perf" with "old perf
data" and all almost worked, see a bug below.

Or am I testing something in a bad way? Can you improve the patch
description?

Here are some of the tests I performed:

New tool, with this patch, new perf.data file:

[root@zoo linux]# perf report --header-only -I -i perf.new.data | more
# ========
# captured on: Mon Aug 31 17:03:15 2015
# hostname : zoo
# os release : 4.2.0
# perf version : 4.2.g906cef6
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM) i7-3667U CPU @ 2.00GHz
# cpuid : GenuineIntel,6,58,9
# total memory : 8080692 kB
# cmdline : /home/acme/bin/perf record -a
# event : name = cycles, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, disabled = 1, inherit = 1, mmap = 1, comm
= 1, freq = 1, task = 1, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1
# sibling cores : 0-3
# sibling threads : 0,2
# sibling threads : 1,3
# CPU 0: Core ID 0, Socket ID 0
# CPU 1: Core ID 1, Socket ID 0
# CPU 2: Core ID 0, Socket ID 0
# CPU 3: Core ID 1, Socket ID 0
# node0 meminfo : total = 8080692 kB, free = 382888 kB
# node0 cpu list : 0-3
# pmu mappings: intel_bts = 6, cpu = 4, software = 1, power = 7, uncore_imc = 8, tracepoint = 2, uncore_cbox_0 = 9, uncore_cbox_1 = 10, breakpoint = 5
# ========
#
[root@zoo linux]#

New tool, with this patch, old perf.data file, oops, there is a bug in this case:

[root@zoo linux]# perf report --header-only -I -i perf.old.data | more
*** Error in `perf': double free or corruption (!prev): 0x0000000002ba5bd0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x77d9e)[0x7f0e4e06ad9e]
/lib64/libc.so.6(cfree+0x5b5)[0x7f0e4e0769f5]
perf(perf_session__delete+0x14b)[0x4bd29b]
perf(cmd_report+0x118b)[0x42fcbb]
perf[0x479173]
perf(main+0x60a)[0x420aca]
/lib64/libc.so.6(__libc_start_main+0xf0)[0x7f0e4e012fe0]
perf[0x420be9]
======= Memory map: ========
00400000-00654000 r-xp 00000000 fd:02 4363800 /home/acme/bin/perf
00854000-00866000 r--p 00254000 fd:02 4363800 /home/acme/bin/perf
00866000-00882000 rw-p 00266000 fd:02 4363800 /home/acme/bin/perf
00882000-0190f000 rw-p 00000000 00:00 0
02b9f000-02bc0000 rw-p 00000000 00:00 0 [heap]
7f0e4cf3a000-7f0e4cf50000 r-xp 00000000 fd:00 534427 /usr/lib64/libgcc_s-4.9.2-20150212.so.1
7f0e4cf50000-7f0e4d14f000 ---p 00016000 fd:00 534427 /usr/lib64/libgcc_s-4.9.2-20150212.so.1
7f0e4d14f000-7f0e4d150000 r--p 00015000 fd:00 534427 /usr/lib64/libgcc_s-4.9.2-20150212.so.1
7f0e4d150000-7f0e4d151000 rw-p 00016000 fd:00 534427 /usr/lib64/libgcc_s-4.9.2-20150212.so.1
7f0e4d151000-7f0e4d1c9000 r-xp 00000000 fd:00 534480 /usr/lib64/libfreebl3.so
7f0e4d1c9000-7f0e4d3c8000 ---p 00078000 fd:00 534480 /usr/lib64/libfreebl3.so
7f0e4d3c8000-7f0e4d3ca000 r--p 00077000 fd:00 534480 /usr/lib64/libfreebl3.so
7f0e4d3ca000-7f0e4d3cb000 rw-p 00079000 fd:00 534480 /usr/lib64/libfreebl3.so
7f0e4d3cb000-7f0e4d3cf000 rw-p 00000000 00:00 0
7f0e4d3cf000-7f0e4d3de000 r-xp 00000000 fd:00 532385 /usr/lib64/libbz2.so.1.0.6
7f0e4d3de000-7f0e4d5dd000 ---p 0000f000 fd:00 532385 /usr/lib64/libbz2.so.1.0.6
7f0e4d5dd000-7f0e4d5de000 r--p 0000e000 fd:00 532385 /usr/lib64/libbz2.so.1.0.6
7f0e4d5de000-7f0e4d5df000 rw-p 0000f000 fd:00 532385 /usr/lib64/libbz2.so.1.0.6
7f0e4d5df000-7f0e4d5e9000 r-xp 00000000 fd:00 532908 /usr/lib64/libnuma.so.1
7f0e4d5e9000-7f0e4d7e8000 ---p 0000a000 fd:00 532908 /usr/lib64/libnuma.so.1
7f0e4d7e8000-7f0e4d7e9000 r--p 00009000 fd:00 532908 /usr/lib64/libnuma.so.1
7f0e4d7e9000-7f0e4d7ea000 rw-p 0000a000 fd:00 532908 /usr/lib64/libnuma.so.1
7f0e4d7ea000-7f0e4d80e000 r-xp 00000000 fd:00 532813 /usr/lib64/liblzma.so.5.0.99
7f0e4d80e000-7f0e4da0d000 ---p 00024000 fd:00 532813 /usr/lib64/liblzma.so.5.0.99
7f0e4da0d000-7f0e4da0e000 r--p 00023000 fd:00 532813 /usr/lib64/liblzma.so.5.0.99
7f0e4da0e000-7f0e4da0f000 rw-p 00024000 fd:00 532813 /usr/lib64/liblzma.so.5.0.99
7f0e4da0f000-7f0e4da24000 r-xp 00000000 fd:00 533312 /usr/lib64/libz.so.1.2.8
7f0e4da24000-7f0e4dc23000 ---p 00015000 fd:00 533312 /usr/lib64/libz.so.1.2.8
7f0e4dc23000-7f0e4dc24000 r--p 00014000 fd:00 533312 /usr/lib64/libz.so.1.2.8
7f0e4dc24000-7f0e4dc25000 rw-p 00015000 fd:00 533312 /usr/lib64/libz.so.1.2.8
7f0e4dc25000-7f0e4dda0000 r-xp 00000000 fd:00 533066 /usr/lib64/libpython2.7.so.1.0
7f0e4dda0000-7f0e4dfa0000 ---p 0017b000 fd:00 533066 /usr/lib64/libpython2.7.so.1.0
7f0e4dfa0000-7f0e4dfa1000 r--p 0017b000 fd:00 533066 /usr/lib64/libpython2.7.so.1.0
7f0e4dfa1000-7f0e4dfe3000 rw-p 0017c000 fd:00 533066 /usr/lib64/libpython2.7.so.1.0
7f0e4dfe3000-7f0e4dff3000 rw-p 00000000 00:00 0
7f0e4dff3000-7f0e4e1a6000 r-xp 00000000 fd:00 531160 /usr/lib64/libc-2.20.so
7f0e4e1a6000-7f0e4e3a6000 ---p 001b3000 fd:00 531160 /usr/lib64/libc-2.20.so
7f0e4e3a6000-7f0e4e3aa000 r--p 001b3000 fd:00 531160 /usr/lib64/libc-2.20.so
7f0e4e3aa000-7f0e4e3ac000 rw-p 001b7000 fd:00 531160 /usr/lib64/libc-2.20.so
7f0e4e3ac000-7f0e4e3b0000 rw-p 00000000 00:00 0
7f0e4e3b0000-7f0e4e3b2000 r-xp 00000000 fd:00 531915 /usr/lib64/libutil-2.20.so
7f0e4e3b2000-7f0e4e5b1000 ---p 00002000 fd:00 531915 /usr/lib64/libutil-2.20.so
7f0e4e5b1000-7f0e4e5b2000 r--p 00001000 fd:00 531915 /usr/lib64/libutil-2.20.so
7f0e4e5b2000-7f0e4e5b3000 rw-p 00002000 fd:00 531915 /usr/lib64/libutil-2.20.so
7f0e4e5b3000-7f0e4e5ba000 r-xp 00000000 fd:00 531243 /usr/lib64/libcrypt-2.20.so
7f0e4e5ba000-7f0e4e7b9000 ---p 00007000 fd:00 531243 /usr/lib64/libcrypt-2.20.so
7f0e4e7b9000-7f0e4e7ba000 r--p 00006000 fd:00 531243 /usr/lib64/libcrypt-2.20.so
7f0e4e7ba000-7f0e4e7bb000 rw-p 00007000 fd:00 531243 /usr/lib64/libcrypt-2.20.so
7f0e4e7bb000-7f0e4e7e9000 rw-p 00000000 00:00 0
7f0e4e7e9000-7f0e4e7ff000 r-xp 00000000 fd:00 531622 /usr/lib64/libnsl-2.20.so
7f0e4e7ff000-7f0e4e9fe000 ---p 00016000 fd:00 531622 /usr/lib64/libnsl-2.20.so
7f0e4e9fe000-7f0e4e9ff000 r--p 00015000 fd:00 531622 /usr/lib64/libnsl-2.20.so
7f0e4e9ff000-7f0e4ea00000 rw-p 00016000 fd:00 531622 /usr/lib64/libnsl-2.20.so
7f0e4ea00000-7f0e4ea02000 rw-p 00000000 00:00 0
7f0e4ea02000-7f0e4ea19000 r-xp 00000000 fd:00 531790 /usr/lib64/libresolv-2.20.so
7f0e4ea19000-7f0e4ec18000 ---p 00017000 fd:00 531790 /usr/lib64/libresolv-2.20.so
7f0e4ec18000-7f0e4ec19000 r--p 00016000 fd:00 531790 /usr/lib64/libresolv-2.20.so
7f0e4ec19000-7f0e4ec1a000 rw-p 00017000 fd:00 531790 /usr/lib64/libresolv-2.20.so
7f0e4ec1a000-7f0e4ec1c000 rw-p 00000000 00:00 0
7f0e4ec1c000-7f0e4edac000 r-xp 00000000 fd:00 531758 /usr/lib64/libperl.so.5.18.4
7f0e4edac000-7f0e4efab000 ---p 00190000 fd:00 531758 /usr/lib64/libperl.so.5.18.4
7f0e4efab000-7f0e4efb0000 r--p 0018f000 fd:00 531758 /usr/lib64/libperl.so.5.18.4
7f0e4efb0000-7f0e4efb7000 rw-p 00194000 fd:00 531758 /usr/lib64/libperl.so.5.18.4
7f0e4efb7000-7f0e4f0ae000 r-xp 00000000 fd:00 533064 /usr/lib64/libslang.so.2.2.4
7f0e4f0ae000-7f0e4f2ae000 ---p 000f7000 fd:00 533064 /usr/lib64/libslang.so.2.2.4
7f0e4f2ae000-7f0e4f2b2000 r--p 000f7000 fd:00 533064 /usr/lib64/libslang.so.2.2.4
7f0e4f2b2000-7f0e4f2cb000 rw-p 000fb000 fd:00 533064 /usr/lib64/libslang.so.2.2.4
7f0e4f2cb000-7f0e4f32f000 rw-p 00000000 00:00 0
7f0e4f32f000-7f0e4f34b000 r-xp 00000000 fd:00 525813 /usr/lib64/libaudit.so.1.0.0
7f0e4f34b000-7f0e4f54a000 ---p 0001c000 fd:00 525813 /usr/lib64/libaudit.so.1.0.0
7f0e4f54a000-7f0e4f54b000 r--p 0001b000 fd:00 525813 /usr/lib64/libaudit.so.1.0.0
7f0e4f54b000-7f0e4f54c000 rw-p 0001c000 fd:00 525813 /usr/lib64/libaudit.so.1.0.0
7f0e4f54c000-7f0e4f556000 rw-p 00000000 00:00 0
7f0e4f556000-7f0e4f59c000 r-xp 00000000 fd:00 529257 /usr/lib64/libdw-0.163.so
7f0e4f59c000-7f0e4f79c000 ---p 00046000 fd:00 529257 /usr/lib64/libdw-0.163.so
7f0e4f79c000-7f0e4f79e000 r--p 00046000 fd:00 529257 /usr/lib64/libdw-0.163.so
7f0e4f79e000-7f0e4f79f000 rw-p 00048000 fd:00 529257 /usr/lib64/libdw-0.163.so
7f0e4f79f000-7f0e4f7b4000 r-xp 00000000 fd:00 532271 /usr/lib64/libelf-0.163.so
7f0e4f7b4000-7f0e4f9b4000 ---p 00015000 fd:00 532271 /usr/lib64/libelf-0.163.so
7f0e4f9b4000-7f0e4f9b5000 r--p 00015000 fd:00 532271 /usr/lib64/libelf-0.163.so
7f0e4f9b5000-7f0e4f9b6000 rw-p 00016000 fd:00 532271 /usr/lib64/libelf-0.163.so
7f0e4f9b6000-7f0e4f9b9000 r-xp 00000000 fd:00 531270 /usr/lib64/libdl-2.20.so
7f0e4f9b9000-7f0e4fbb8000 ---p 00003000 fd:00 531270 /usr/lib64/libdl-2.20.so
7f0e4fbb8000-7f0e4fbb9000 r--p 00002000 fd:00 531270 /usr/lib64/libdl-2.20.so
7f0e4fbb9000-7f0e4fbba000 rw-p 00003000 fd:00 531270 /usr/lib64/libdl-2.20.so
7f0e4fbba000-7f0e4fcc1000 r-xp 00000000 fd:00 531293 /usr/lib64/libm-2.20.so
7f0e4fcc1000-7f0e4fec0000 ---p 00107000 fd:00 531293 /usr/lib64/libm-2.20.so
7f0e4fec0000-7f0e4fec1000 r--p 00106000 fd:00 531293 /usr/lib64/libm-2.20.so
7f0e4fec1000-7f0e4fec2000 rw-p 00107000 fd:00 531293 /usr/lib64/libm-2.20.so
7f0e4fec2000-7f0e4fec9000 r-xp 00000000 fd:00 531823 /usr/lib64/librt-2.20.so
7f0e4fec9000-7f0e500c8000 ---p 00007000 fd:00 531823 /usr/lib64/librt-2.20.so
7f0e500c8000-7f0e500c9000 r--p 00006000 fd:00 531823 /usr/lib64/librt-2.20.so
7f0e500c9000-7f0e500ca000 rw-p 00007000 fd:00 531823 /usr/lib64/librt-2.20.so
7f0e500ca000-7f0e500e1000 r-xp 00000000 fd:00 531692 /usr/lib64/libpthread-2.20.so
7f0e500e1000-7f0e502e0000 ---p 00017000 fd:00 531692 /usr/lib64/libpthread-2.20.so
7f0e502e0000-7f0e502e1000 r--p 00016000 fd:00 531692 /usr/lib64/libpthread-2.20.so
7f0e502e1000-7f0e502e2000 rw-p 00017000 fd:00 531692 /usr/lib64/libpthread-2.20.so
7f0e502e2000-7f0e502e6000 rw-p 00000000 00:00 0
7f0e502e6000-7f0e502f6000 r-xp 00000000 fd:00 531941 /usr/lib64/libunwind-x86_64.so.8.0.1
7f0e502f6000-7f0e504f5000 ---p 00010000 fd:00 531941 /usr/lib64/libunwind-x86_64.so.8.0.1
7f0e504f5000-7f0e504f6000 r--p 0000f000 fd:00 531941 /usr/lib64/libunwind-x86_64.so.8.0.1
7f0e504f6000-7f0e504f7000 rw-p 00010000 fd:00 531941 /usr/lib64/libunwind-x86_64.so.8.0.1
7f0e504f7000-7f0e50505000 rw-p 00000000 00:00 0
7f0e50505000-7f0e5050f000 r-xp 00000000 fd:00 531942 /usr/lib64/libunwind.so.8.0.1
7f0e5050f000-7f0e5070e000 ---p 0000a000 fd:00 531942 /usr/lib64/libunwind.so.8.0.1
7f0e5070e000-7f0e5070f000 r--p 00009000 fd:00 531942 /usr/lib64/libunwind.so.8.0.1
7f0e5070f000-7f0e50710000 rw-p 0000a000 fd:00 531942 /usr/lib64/libunwind.so.8.0.1
7f0e50710000-7f0e5071e000 rw-p 00000000 00:00 0
7f0e5071e000-7f0e5073f000 r-xp 00000000 fd:00 534148 /usr/lib64/ld-2.20.so
7f0e50917000-7f0e50923000 rw-p 00000000 00:00 0
7f0e5093c000-7f0e5093f000 rw-p 00000000 00:00 0
7f0e5093f000-7f0e50940000 r--p 00021000 fd:00 534148 /usr/lib64/ld-2.20.so
7f0e50940000-7f0e50941000 rw-p 00022000 fd:00 534148 /usr/lib64/ld-2.20.so
7f0e50941000-7f0e50942000 rw-p 00000000 00:00 0
7ffc70e47000-7ffc70e68000 rw-p 00000000 00:00 0 [stack]
7ffc70f5e000-7ffc70f60000 r--p 00000000 00:00 0 [vvar]
7ffc70f60000-7ffc70f62000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
# ========
# captured on: Mon Aug 31 16:55:30 2015
# hostname : zoo
# os release : 4.2.0
# perf version : 4.2.g906cef6
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM) i7-3667U CPU @ 2.00GHz
# cpuid : GenuineIntel,6,58,9
# total memory : 8080692 kB
# cmdline : /home/acme/bin/perf record -a
# event : name = cycles, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, disabled = 1, inherit = 1, mmap = 1, comm
= 1, freq = 1, task = 1, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1
# sibling cores : 0-3
# sibling threads : 0,2
# sibling threads : 1,3
# CPU 0: Core ID 32526, Socket ID 1312468248
# CPU 1: Core ID 0, Socket ID 45743648
# CPU 2: Core ID 0, Socket ID 0
# CPU 3: Core ID 0, Socket ID 0
# pmu mappings: not available
# ========
#
[root@zoo linux]#


Old perf tool, WITHOUT this patch, new file:

[root@zoo linux]# ~acme/bin/oldperf report --header-only -I -i perf.new.data | more
# ========
# captured on: Mon Aug 31 17:03:15 2015
# hostname : zoo
# os release : 4.2.0
# perf version : 4.2.g906cef6
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM) i7-3667U CPU @ 2.00GHz
# cpuid : GenuineIntel,6,58,9
# total memory : 8080692 kB
# cmdline : /home/acme/bin/perf record -a
# event : name = cycles, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, disabled = 1, inherit = 1, mmap = 1, comm
= 1, freq = 1, task = 1, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1
# sibling cores : 0-3
# sibling threads : 0,2
# sibling threads : 1,3
# node0 meminfo : total = 8080692 kB, free = 382888 kB
# node0 cpu list : 0-3
# pmu mappings: intel_bts = 6, cpu = 4, software = 1, power = 7, uncore_imc = 8, tracepoint = 2, uncore_cbox_0 = 9, uncore_cbox_1 = 10, breakpoint = 5
# ========
#
[root@zoo linux]#


Old perf tool, WITHOUT this patch, OLD file:

[root@zoo linux]# ~acme/bin/oldperf report --header-only -I -i perf.old.data | more
# ========
# captured on: Mon Aug 31 16:55:30 2015
# hostname : zoo
# os release : 4.2.0
# perf version : 4.2.g906cef6
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM) i7-3667U CPU @ 2.00GHz
# cpuid : GenuineIntel,6,58,9
# total memory : 8080692 kB
# cmdline : /home/acme/bin/perf record -a
# event : name = cycles, , size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, disabled = 1, inherit = 1, mmap = 1, comm
= 1, freq = 1, task = 1, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1
# sibling cores : 0-3
# sibling threads : 0,2
# sibling threads : 1,3
# node0 meminfo : total = 8080692 kB, free = 454952 kB
# node0 cpu list : 0-3
# pmu mappings: intel_bts = 6, cpu = 4, software = 1, power = 7, uncore_imc = 8, tracepoint = 2, uncore_cbox_0 = 9, uncore_cbox_1 = 10, breakpoint = 5
# ========
#
[root@zoo linux]#

Can you please take a look at these issues?

Regards,

- Arnaldo



> Signed-off-by: Kan Liang <[email protected]>
> ---
>
> Changes since V1:
> - Store core_id and socket_id in perf.date
>
> Changes since V2:
> - Use funcitons in cpumap.c to get core_id and socket_id
> - Modify changelog
>
> tools/perf/util/header.c | 72 ++++++++++++++++++++++++++++++++++++++++++++---
> tools/perf/util/header.h | 6 ++++
> tools/perf/util/session.c | 1 +
> 3 files changed, 75 insertions(+), 4 deletions(-)
>
> diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
> index 4181454..a1451f3 100644
> --- a/tools/perf/util/header.c
> +++ b/tools/perf/util/header.c
> @@ -441,10 +441,13 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
> "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
>
> struct cpu_topo {
> + u32 cpu_nr;
> u32 core_sib;
> u32 thread_sib;
> char **core_siblings;
> char **thread_siblings;
> + int *core_id;
> + int *phy_pkg_id;
> };
>
> static int build_cpu_topo(struct cpu_topo *tp, int cpu)
> @@ -507,6 +510,9 @@ try_threads:
> }
> ret = 0;
> done:
> + tp->core_id[cpu] = cpu_map__get_core_id(cpu);
> + tp->phy_pkg_id[cpu] = cpu_map__get_socket_id(cpu);
> +
> if(fp)
> fclose(fp);
> free(buf);
> @@ -534,7 +540,7 @@ static struct cpu_topo *build_cpu_topology(void)
> struct cpu_topo *tp;
> void *addr;
> u32 nr, i;
> - size_t sz;
> + size_t sz, sz_id;
> long ncpus;
> int ret = -1;
>
> @@ -545,17 +551,22 @@ static struct cpu_topo *build_cpu_topology(void)
> nr = (u32)(ncpus & UINT_MAX);
>
> sz = nr * sizeof(char *);
> + sz_id = nr * sizeof(int);
>
> - addr = calloc(1, sizeof(*tp) + 2 * sz);
> + addr = calloc(1, sizeof(*tp) + 2 * sz + 2 * sz_id);
> if (!addr)
> return NULL;
>
> tp = addr;
> -
> + tp->cpu_nr = nr;
> addr += sizeof(*tp);
> tp->core_siblings = addr;
> addr += sz;
> tp->thread_siblings = addr;
> + addr += sz;
> + tp->core_id = addr;
> + addr += sz_id;
> + tp->phy_pkg_id = addr;
>
> for (i = 0; i < nr; i++) {
> ret = build_cpu_topo(tp, i);
> @@ -598,6 +609,15 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,
> if (ret < 0)
> break;
> }
> +
> + for (i = 0; i < tp->cpu_nr; i++) {
> + ret = do_write(fd, &tp->core_id[i], sizeof(int));
> + if (ret < 0)
> + return ret;
> + ret = do_write(fd, &tp->phy_pkg_id[i], sizeof(int));
> + if (ret < 0)
> + return ret;
> + }
> done:
> free_cpu_topo(tp);
> return ret;
> @@ -938,6 +958,7 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
> {
> int nr, i;
> char *str;
> + int cpu_nr = ph->env.nr_cpus_online;
>
> nr = ph->env.nr_sibling_cores;
> str = ph->env.sibling_cores;
> @@ -954,6 +975,10 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
> fprintf(fp, "# sibling threads : %s\n", str);
> str += strlen(str) + 1;
> }
> +
> + for (i = 0; i < cpu_nr; i++)
> + fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i,
> + ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id);
> }
>
> static void free_event_desc(struct perf_evsel *events)
> @@ -1590,10 +1615,15 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
> u32 nr, i;
> char *str;
> struct strbuf sb;
> + int cpu_nr = ph->env.nr_cpus_online;
> +
> + ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
> + if (!ph->env.cpu)
> + return -1;
>
> ret = readn(fd, &nr, sizeof(nr));
> if (ret != sizeof(nr))
> - return -1;
> + goto free_cpu;
>
> if (ph->needs_swap)
> nr = bswap_32(nr);
> @@ -1631,10 +1661,44 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
> free(str);
> }
> ph->env.sibling_threads = strbuf_detach(&sb, NULL);
> +
> + for (i = 0; i < (u32)cpu_nr; i++) {
> + ret = readn(fd, &nr, sizeof(nr));
> + if (ret != sizeof(nr))
> + goto free_cpu;
> +
> + if (ph->needs_swap)
> + nr = bswap_32(nr);
> +
> + if (nr > (u32)cpu_nr) {
> + pr_debug("core_id number is too big."
> + "You may need to upgrade the perf tool.\n");
> + goto free_cpu;
> + }
> + ph->env.cpu[i].core_id = nr;
> +
> + ret = readn(fd, &nr, sizeof(nr));
> + if (ret != sizeof(nr))
> + goto free_cpu;
> +
> + if (ph->needs_swap)
> + nr = bswap_32(nr);
> +
> + if (nr > (u32)cpu_nr) {
> + pr_debug("socket_id number is too big."
> + "You may need to upgrade the perf tool.\n");
> + goto free_cpu;
> + }
> +
> + ph->env.cpu[i].socket_id = nr;
> + }
> +
> return 0;
>
> error:
> strbuf_release(&sb);
> +free_cpu:
> + free(ph->env.cpu);
> return -1;
> }
>
> diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
> index 396e496..975d803 100644
> --- a/tools/perf/util/header.h
> +++ b/tools/perf/util/header.h
> @@ -66,6 +66,11 @@ struct perf_header;
> int perf_file_header__read(struct perf_file_header *header,
> struct perf_header *ph, int fd);
>
> +struct cpu_topology_map {
> + int socket_id;
> + int core_id;
> +};
> +
> struct perf_env {
> char *hostname;
> char *os_release;
> @@ -89,6 +94,7 @@ struct perf_env {
> char *sibling_threads;
> char *numa_nodes;
> char *pmu_mappings;
> + struct cpu_topology_map *cpu;
> };
>
> struct perf_header {
> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
> index 8a4537e..61669be 100644
> --- a/tools/perf/util/session.c
> +++ b/tools/perf/util/session.c
> @@ -185,6 +185,7 @@ static void perf_session_env__exit(struct perf_env *env)
> zfree(&env->sibling_threads);
> zfree(&env->numa_nodes);
> zfree(&env->pmu_mappings);
> + zfree(&env->cpu);
> }
>
> void perf_session__delete(struct perf_session *session)
> --
> 1.8.3.1