perf_env/CPU socket reorg/fixes
Arnaldo Carvalho de Melo
maintainercover perf_env/CPU socket reorg/fixes
Hi,
Please take a look at these changes to fix the problems reported by
Wang Nan wrt accesses to the cpu_topology_map information.
The fixes are present on these following two csets:
perf event: Use machine->env to find the cpu -> socket mapping perf report: Do not blindly use env->cpu[al.cpu].socket_id
The rest are fixes made while working on this, infrastructure to enable
the fixes, reverts for things that ended up not being necessary and some cleanups.
It is available at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git perf/env
Please let me know if I can have your Acked-by, Tested-by or
Reviewed-by.
- Arnaldo
Arnaldo Carvalho de Melo (13):
perf env: Move perf_env out of header.h and session.c into separate object perf env: Rename some leftovers from rename to perf_env
perf env: Adopt perf_header__set_cmdline
perf env: Introduce read_cpu_topology_map() method
perf sort: Set flag stating if the "socket" key is being used perf top: Cache the cpu topology info when "-s socket" is used perf hists browser: Fixup the "cpu" column width calculation perf machine: Add pointer to sample's environment
perf event: Use machine->env to find the cpu -> socket mapping perf report: Do not blindly use env->cpu[al.cpu].socket_id Revert "perf evsel: Add a backpointer to the evlist a evsel is in" perf evsel: Remove forward declaration of 'struct perf_evlist' Revert "perf evlist: Add backpointer for perf_env to evlist"
Arnaldo Carvalho de Melo
maintainerPATCH 1/13 perf env: Move perf_env out of header.h and session.c into separate object
From: Arnaldo Carvalho de Melo <[email protected]>
Since it can be used separately from 'perf_session' and 'perf_header', move it to separate include file and object, next csets will try to move a perf_env__init() routine.
--- tools/perf/util/Build | 1 + tools/perf/util/env.c | 19 +++++++++++++++++++ tools/perf/util/env.h | 37 +++++++++++++++++++++++++++++++++++++ tools/perf/util/header.h | 33 +-------------------------------- tools/perf/util/session.c | 20 +------------------- 5 files changed, 59 insertions(+), 51 deletions(-) create mode 100644 tools/perf/util/env.c create mode 100644 tools/perf/util/env.h
tools/perf/util/Build +1 -0
@@ -5,6 +5,7 @@ libperf-y += build-id.o libperf-y += config.o libperf-y += ctype.o libperf-y += db-export.o +libperf-y += env.o libperf-y += environment.o libperf-y += event.o libperf-y += evlist.o
tools/perf/util/env.c new file +19 -0
@@ -0,0 +1,19 @@ +#include "env.h" +#include "util.h" + +void perf_env__exit (struct perf_env *env) +{ +zfree (&env->hostname); +zfree (&env->os_release); +zfree (&env->version); +zfree (&env->arch); +zfree (&env->cpu_desc); +zfree (&env->cpuid); +zfree (&env->cmdline); +zfree (&env->cmdline_argv); +zfree (&env->sibling_cores); +zfree (&env->sibling_threads); +zfree (&env->numa_nodes); +zfree (&env->pmu_mappings); +zfree (&env->cpu); +}
tools/perf/util/env.h new file +37 -0
@@ -0,0 +1,37 @@ +#ifndef __PERF_ENV_H +#define __PERF_ENV_H + +struct cpu_topology_map { +int socket_id; +int core_id; +}; + +struct perf_env { +char *hostname; +char *os_release; +char *version; +char *arch; +int nr_cpus_online; +int nr_cpus_avail; +char *cpu_desc; +char *cpuid; +unsigned long long total_mem; + +int nr_cmdline; +int nr_sibling_cores; +int nr_sibling_threads; +int nr_numa_nodes; +int nr_pmu_mappings; +int nr_groups; +char *cmdline; +const char **cmdline_argv; +char *sibling_cores; +char *sibling_threads; +char *numa_nodes; +char *pmu_mappings; +struct cpu_topology_map *cpu; +}; + +void perf_env__exit (struct perf_env *env); + +#endif /* __PERF_ENV_H */
tools/perf/util/header.h +1 -32
@@ -7,7 +7,7 @@#include <linux/bitmap.h> #include <linux/types.h> #include "event.h" - +#include "env.h" enum {HEADER_RESERVED =0 ,/* always cleared */
@@ -66,37 +66,6 @@ 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; -char *version; -char *arch; -int nr_cpus_online; -int nr_cpus_avail; -char *cpu_desc; -char *cpuid; -unsigned long long total_mem; - -int nr_cmdline; -int nr_sibling_cores; -int nr_sibling_threads; -int nr_numa_nodes; -int nr_pmu_mappings; -int nr_groups; -char *cmdline; -const char **cmdline_argv; -char *sibling_cores; -char *sibling_threads; -char *numa_nodes; -char *pmu_mappings; -struct cpu_topology_map *cpu; -}; -struct perf_header {enum perf_header_version version;bool needs_swap;
tools/perf/util/session.c +1 -19
@@ -170,31 +170,13 @@ static void perf_session__delete_threads(struct perf_session *session)machine__delete_threads (&session->machines.host); } -static void perf_session_env__exit (struct perf_env *env) -{ -zfree (&env->hostname); -zfree (&env->os_release); -zfree (&env->version); -zfree (&env->arch); -zfree (&env->cpu_desc); -zfree (&env->cpuid); - -zfree (&env->cmdline); -zfree (&env->cmdline_argv); -zfree (&env->sibling_cores); -zfree (&env->sibling_threads); -zfree (&env->numa_nodes); -zfree (&env->pmu_mappings); -zfree (&env->cpu); -} -void perf_session__delete (struct perf_session *session) {auxtrace__free (session);auxtrace_index__free (&session->auxtrace_index);perf_session__destroy_kernel_maps (session);perf_session__delete_threads (session); -perf_session_env__exit (&session->header.env); +perf_env__exit (&session->header.env);machines__exit (&session->machines);if (session->file)perf_data_file__close (session->file);
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 2/13 perf env: Rename some leftovers from rename to perf_env
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
In ce80d3bef9ff ("perf tools: Rename perf_session_env to perf_env") we forgot to rename a few functions to the "perf_env" prefix, do it now.
--- tools/perf/arch/common.c | 10 ++++------ tools/perf/arch/common.h | 4 ++-- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/ui/browsers/hists.c | 2 +- 5 files changed, 9 insertions(+), 11 deletions(-)
tools/perf/arch/common.c +4 -6
@@ -128,9 +128,8 @@ static const char *normalize_arch(char *arch)return arch; } -static int perf_session_env__lookup_binutils_path (struct perf_env *env, -const char *name, -const char **path) +static int perf_env__lookup_binutils_path (struct perf_env *env, +const char *name,const char **path) {int idx;const char *arch, *cross_env;
@@ -206,7 +205,7 @@ out_error:return -1 ; } -int perf_session_env__lookup_objdump (struct perf_env *env) +int perf_env__lookup_objdump (struct perf_env *env) {/* * For live mode, env->arch will be NULL and we can use
@@ -215,6 +214,5 @@ int perf_session_env__lookup_objdump(struct perf_env *env)if (env->arch ==NULL )return 0 ; -return perf_session_env__lookup_binutils_path (env,"objdump" , - &objdump_path); +return perf_env__lookup_binutils_path (env,"objdump" , &objdump_path); }
tools/perf/arch/common.h +2 -2
@@ -1,10 +1,10 @@#ifndef ARCH_PERF_COMMON_H #define ARCH_PERF_COMMON_H -#include "../util/session.h" +#include "../util/env.h" extern const char *objdump_path; -int perf_session_env__lookup_objdump (struct perf_env *env); +int perf_env__lookup_objdump (struct perf_env *env);#endif /* ARCH_PERF_COMMON_H */
tools/perf/builtin-annotate.c +1 -1
@@ -211,7 +211,7 @@ static int __cmd_annotate(struct perf_annotate *ann) }if (!objdump_path) { - ret =perf_session_env__lookup_objdump (&session->header.env); + ret =perf_env__lookup_objdump (&session->header.env);if (ret) goto out; }
tools/perf/builtin-top.c +1 -1
@@ -952,7 +952,7 @@ static int __cmd_top(struct perf_top *top)machines__set_symbol_filter (&top->session->machines, symbol_filter);if (!objdump_path) { - ret =perf_session_env__lookup_objdump (&top->session->header.env); + ret =perf_env__lookup_objdump (&top->session->header.env);if (ret) goto out_delete; }
tools/perf/ui/browsers/hists.c +1 -1
@@ -1442,7 +1442,7 @@ do_annotate(struct hist_browser *browser, struct popup_action *act)struct hist_entry *he;int err; -if (!objdump_path &&perf_session_env__lookup_objdump (browser->env)) +if (!objdump_path &&perf_env__lookup_objdump (browser->env))return 0 ; notes =symbol__annotation (act->ms.sym);
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 3/13 perf env: Adopt perf_header__set_cmdline
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Move this from two globals to perf_env global, that eventually will be just perf_header->env or something else, to ease the refactoring series, leave it as a global and go on reading more of its fields, not as part of the header writing process but as a perf_env init one that will be used for perf.data-less situations.
--- tools/perf/util/env.c | 39 ++++++++++++++++++++++++++++++++++++ tools/perf/util/env.h | 4 ++++ tools/perf/util/header.c | 44 +++++------------------------------------ tools/perf/util/parse-options.c | 2 +- 4 files changed, 49 insertions(+), 40 deletions(-)
tools/perf/util/env.c +39 -0
@@ -1,6 +1,8 @@#include "env.h" #include "util.h" +struct perf_env perf_env; +void perf_env__exit (struct perf_env *env) {zfree (&env->hostname);
@@ -17,3 +19,40 @@ void perf_env__exit(struct perf_env *env)zfree (&env->pmu_mappings);zfree (&env->cpu); } + +int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[]) +{ +int i; + +/* +* If env->cmdline_argv has already been set, do not override it. This allows +* a command to set the cmdline, parse args and then call another +* builtin function that implements a command -- e.g, cmd_kvm calling +* cmd_record. +*/ +if (env->cmdline_argv !=NULL ) +return 0 ; + +/* do not include NULL termination */ + env->cmdline_argv =calloc (argc,sizeof (char *)); +if (env->cmdline_argv ==NULL ) + goto out_enomem; + +/* +* Must copy argv contents because it gets moved around during option +* parsing: +*/ +for (i =0 ; i < argc ; i++) { + env->cmdline_argv[i] = argv[i]; +if (env->cmdline_argv[i] ==NULL ) + goto out_free; + } + + env->nr_cmdline = argc; + +return 0 ; +out_free: +zfree (&env->cmdline_argv); +out_enomem: +return -ENOMEM ; +}
tools/perf/util/env.h +4 -0
@@ -32,6 +32,10 @@ struct perf_env { struct cpu_topology_map *cpu; }; +extern struct perf_env perf_env; +void perf_env__exit (struct perf_env *env); +int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[]); +#endif /* __PERF_ENV_H */
tools/perf/util/header.c +5 -39
74 lines not on this page · raw message
tools/perf/util/parse-options.c +1 -1
@@ -496,7 +496,7 @@ int parse_options_subcommand(int argc, const char **argv, const struct option *o {struct parse_opt_ctx_t ctx; -perf_header__set_cmdline (argc, argv); +perf_env__set_cmdline (&perf_env, argc, argv);/* build usage string if it's not provided */ if (subcommands && !usagestr[0 ]) {
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 4/13 perf env: Introduce read_cpu_topology_map() method
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Out of the code to write the cpu topology map in the perf.data file header.
Now if one needs the CPU topology map for the running machine, one needs to call perf_env__read_cpu_topology_map(perf_env) and the info will be stored in perf_env.cpu.
For now we're using a global perf_env variable, that will have its contents freed after we run a builtin.
--- tools/perf/perf.c | 2 ++ tools/perf/util/env.c | 28 ++++++++++++++++++++++++++++ tools/perf/util/env.h | 2 ++ tools/perf/util/header.c | 26 ++++++++++---------------- 4 files changed, 42 insertions(+), 16 deletions(-)
tools/perf/perf.c +2 -0
@@ -8,6 +8,7 @@*/ #include "builtin.h" +#include "util/env.h" #include "util/exec_cmd.h" #include "util/cache.h" #include "util/quote.h"
@@ -369,6 +370,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) status = p->fn (argc, argv, prefix);exit_browser (status); +perf_env__exit (&perf_env);if (status)return status &0xff ;
tools/perf/util/env.c +28 -0
@@ -1,3 +1,4 @@ +#include "cpumap.h" #include "env.h" #include "util.h"
@@ -56,3 +57,30 @@ out_free: out_enomem:return -ENOMEM ; } + +int perf_env__read_cpu_topology_map (struct perf_env *env) +{ +int cpu, nr_cpus; + +if (env->cpu !=NULL ) +return 0 ; + +if (env->nr_cpus_avail ==0 ) + env->nr_cpus_avail =sysconf (_SC_NPROCESSORS_CONF); + + nr_cpus = env->nr_cpus_avail; +if (nr_cpus ==-1 ) +return -EINVAL ; + + env->cpu =calloc (nr_cpus,sizeof (env->cpu[0 ])); +if (env->cpu ==NULL ) +return -ENOMEM ; + +for (cpu =0 ; cpu < nr_cpus; ++cpu) { + env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); + env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + } + + env->nr_cpus_avail = nr_cpus; +return 0 ; +}
tools/perf/util/env.h +2 -0
@@ -38,4 +38,6 @@ void perf_env__exit(struct perf_env *env);int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[]); +int perf_env__read_cpu_topology_map (struct perf_env *env); +#endif /* __PERF_ENV_H */
tools/perf/util/header.c +10 -16
@@ -415,8 +415,6 @@ struct cpu_topo {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)
@@ -479,9 +477,6 @@ 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);
@@ -509,7 +504,7 @@ static struct cpu_topo *build_cpu_topology(void)struct cpu_topo *tp;void *addr;u32 nr, i; -size_t sz, sz_id; +size_t sz;long ncpus;int ret =-1 ;
@@ -520,9 +515,8 @@ 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 +2 * sz_id); + addr =calloc (1 ,sizeof (*tp) +2 * sz);if (!addr)return NULL ;
@@ -532,10 +526,6 @@ static struct cpu_topo *build_cpu_topology(void) 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);
@@ -554,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, {struct cpu_topo *tp;u32 i; -int ret; +int ret, j; tp =build_cpu_topology ();if (!tp)
@@ -579,11 +569,15 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,break ; } -for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); +perf_env__read_cpu_topology_map (&perf_env); + +for (j =0 ; j < perf_env.nr_cpus_avail; j++) { + ret =do_write (fd, &perf_env.cpu[j].core_id, +sizeof (perf_env.cpu[j].core_id));if (ret <0 )return ret; - ret =do_write (fd, &tp->phy_pkg_id[i],sizeof (int )); + ret =do_write (fd, &perf_env.cpu[j].socket_id, +sizeof (perf_env.cpu[j].socket_id));if (ret <0 )return ret; }
Signature · 1 line
2.1.0
RE: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Quoted 65 lines
tools/perf/util/header.c index renamed from tools/perf/util/header.c +0
-0
151b8310ac70..d4c8aa2f4db7100644tools/perf/util/header.c +0
-2@@ -415,8 +415,6 @@ struct cpu_topo {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) @@ -479,9 +477,6@@
try_threads:tools/perf/util/header.c +3
-11} 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);@@ -509,7 +504,7 @@ static struct cpu_topo *build_cpu_topology(void)struct cpu_topo *tp;void *addr;u32 nr, i; -size_t sz, sz_id; +size_t sz;long ncpus;int ret =-1 ;@@ -520,9 +515,8 @@ 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 +2 * sz_id); + addr =calloc (1 ,sizeof (*tp) +2 * sz);if (!addr)return NULL ;@@ -532,10 +526,6 @@ static struct cpu_topo *build_cpu_topology(void) 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);@@ -554,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, {struct cpu_topo *tp;u32 i; -int ret; +int ret, j; tp =build_cpu_topology ();if (!tp)
tools/perf/util/header.c static int write_cpu_topology(int fd, struct · line 574
Quoted 8 lines
tools/perf/util/header.c +2
-2@@ -579,11 +569,15 @@ static int write_cpu_topology(int fd, structperf_header *h__maybe_unused , break; } -for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); +perf_env__read_cpu_topology_map (&perf_env); +
I think we need to handle error here.
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Em Wed, Sep 09, 2015 at 09:41:18PM +0000, Liang, Kan escreveu:
Quoted 6 lines
Review
Quoted 4 lines
(quoted diff) +2
-2- for (i = 0; i < tp->cpu_nr; i++) { - ret = do_write(fd, &tp->core_id[i], sizeof(int)); + perf_env__read_cpu_topology_map(&perf_env); +I think we need to handle error here.
Ok, adding a test, updated patch below. While doing that, noticed that the in the thread_sib case the "ret = do_something()" doesn't makes the whole function fail, will fix later.
- Arnaldo
commit c98989f4a47a6fd3f3f8bd937b96faaced8b203e
Author: Arnaldo Carvalho de Melo <[email protected]> Date: Wed Sep 9 10:37:01 2015 -0300
perf env: Introduce read_cpu_topology_map() method
Out of the code to write the cpu topology map in the perf.data file header.
Now if one needs the CPU topology map for the running machine, one needs to call perf_env__read_cpu_topology_map(perf_env) and the info will be stored in perf_env.cpu.
For now we're using a global perf_env variable, that will have its contents freed after we run a builtin.
v2: Check perf_env__read_cpu_topology_map() return in
write_cpu_topology() (Kan Liang)
tools/perf/perf.c +2 -0
@@ -8,6 +8,7 @@*/ #include "builtin.h" +#include "util/env.h" #include "util/exec_cmd.h" #include "util/cache.h" #include "util/quote.h"
@@ -369,6 +370,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) status = p->fn (argc, argv, prefix);exit_browser (status); +perf_env__exit (&perf_env);if (status)return status &0xff ;
tools/perf/util/env.c +28 -0
@@ -1,3 +1,4 @@ +#include "cpumap.h" #include "env.h" #include "util.h"
@@ -56,3 +57,30 @@ out_free: out_enomem:return -ENOMEM ; } + +int perf_env__read_cpu_topology_map (struct perf_env *env) +{ +int cpu, nr_cpus; + +if (env->cpu !=NULL ) +return 0 ; + +if (env->nr_cpus_avail ==0 ) + env->nr_cpus_avail =sysconf (_SC_NPROCESSORS_CONF); + + nr_cpus = env->nr_cpus_avail; +if (nr_cpus ==-1 ) +return -EINVAL ; + + env->cpu =calloc (nr_cpus,sizeof (env->cpu[0 ])); +if (env->cpu ==NULL ) +return -ENOMEM ; + +for (cpu =0 ; cpu < nr_cpus; ++cpu) { + env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); + env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + } + + env->nr_cpus_avail = nr_cpus; +return 0 ; +}
tools/perf/util/env.h +2 -0
@@ -38,4 +38,6 @@ void perf_env__exit(struct perf_env *env);int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[]); +int perf_env__read_cpu_topology_map (struct perf_env *env); +#endif /* __PERF_ENV_H */
tools/perf/util/header.c +12 -16
@@ -415,8 +415,6 @@ struct cpu_topo {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)
@@ -479,9 +477,6 @@ 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);
@@ -509,7 +504,7 @@ static struct cpu_topo *build_cpu_topology(void)struct cpu_topo *tp;void *addr;u32 nr, i; -size_t sz, sz_id; +size_t sz;long ncpus;int ret =-1 ;
@@ -520,9 +515,8 @@ 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 +2 * sz_id); + addr =calloc (1 ,sizeof (*tp) +2 * sz);if (!addr)return NULL ;
@@ -532,10 +526,6 @@ static struct cpu_topo *build_cpu_topology(void) 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);
@@ -554,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, {struct cpu_topo *tp;u32 i; -int ret; +int ret, j; tp =build_cpu_topology ();if (!tp)
@@ -579,11 +569,17 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,break ; } -for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); + ret =perf_env__read_cpu_topology_map (&perf_env); +if (ret <0 ) + goto done; + +for (j =0 ; j < perf_env.nr_cpus_avail; j++) { + ret =do_write (fd, &perf_env.cpu[j].core_id, +sizeof (perf_env.cpu[j].core_id));if (ret <0 )return ret; - ret =do_write (fd, &tp->phy_pkg_id[i],sizeof (int )); + ret =do_write (fd, &perf_env.cpu[j].socket_id, +sizeof (perf_env.cpu[j].socket_id));if (ret <0 )return ret; }
RE: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Quoted 11 lines
Em Wed, Sep 09, 2015 at 09:41:18PM +0000, Liang, Kan escreveu:
Quoted 6 lines
tools/perf/util/header.c static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, · line 575
Quoted 4 lines
tools/perf/util/header.c +2
-2-for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); +perf_env__read_cpu_topology_map (&perf_env); +I think we need to handle error here.
Quoted 4 lines
Ok, adding a test, updated patch below. While doing that, noticed that the in the
thread_sibcase the "ret =do_something()" doesn't makes the whole function fail, will fix later.
Thanks.
Except patch 11 & 13 (for reverting), the rest of patches are good to me.
Thanks,
Kan
Quoted 194 lines
- Arnaldo
commit
c98989f4a47a6fd3f3f8bd937b96faaced8b203eAuthor: Arnaldo Carvalho de Melo <[email protected]> Date: Wed Sep 9 10:37:01 2015 -0300perf env: Introduce
read_cpu_topology_map()methodOut of the code to write the cpu topology map in the perf.data file header.
Now if one needs the CPU topology map for the running machine, one
needs
to callperf_env__read_cpu_topology_map(perf_env)and the info will
be
stored in perf_env.cpu.For now we're using a global
perf_envvariable, that will have its contents freed after we run a builtin.v2: Check
perf_env__read_cpu_topology_map()return in
write_cpu_topology()(Kan Liang)Cc Adrian Hunter <[email protected]>Cc Borislav Petkov <[email protected]>Cc David Ahern <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Jiri Olsa <[email protected]>Cc Kan Liang <[email protected]>Cc Namhyung Kim <[email protected]>Cc Stephane Eranian <[email protected]>Cc Wang Nan <[email protected]>Signed-off-by Arnaldo Carvalho de Melo <[email protected]>tools/perf/perf.c index renamed from tools/perf/perf.c +0
-0
f2fc019b3671..1fded922bcc8100644tools/perf/perf.c +2
-0@@ -8,6 +8,7 @@*/ #include "builtin.h" +#include "util/env.h" #include "util/exec_cmd.h" #include "util/cache.h" #include "util/quote.h" @@ -369,6 +370,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) status = p->fn (argc, argv, prefix);exit_browser (status); +perf_env__exit (&perf_env);if (status)tools/perf/perf.c +0
-0return status &0xff ;tools/perf/util/env.c index renamed from tools/perf/util/env.c +0
-0
ca1e33a2203e..6af4f7c36820100644tools/perf/util/env.c +22
-0@@ -1,3 +1,4 @@ +#include "cpumap.h" #include "env.h" #include "util.h" @@ -56,3 +57,30 @@ out_free: out_enomem:return -ENOMEM ; } + +int perf_env__read_cpu_topology_map (struct perf_env *env) { +int cpu, nr_cpus; + +if (env->cpu !=NULL ) +return 0 ; + +if (env->nr_cpus_avail ==0 ) + env->nr_cpus_avail =sysconf (_SC_NPROCESSORS_CONF); + + nr_cpus = env->nr_cpus_avail; +if (nr_cpus ==-1 ) +return -EINVAL ; + + env->cpu =calloc (nr_cpus,sizeof (env->cpu[0 ])); +if (env->cpu ==NULL ) +return -ENOMEM ; + +for (cpu =0 ; cpu < nr_cpus; ++cpu) { + env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); + env->cpu[cpu].socket_id =
cpu_map__get_socket_id(cpu);tools/perf/util/env.c +5
-0+ } + + env->nr_cpus_avail = nr_cpus; +return 0 ; +}tools/perf/util/env.h index renamed from tools/perf/util/env.h +0
-0
70124d9a1624..c4e36323d91e100644tools/perf/util/env.h +2
-0@@ -38,4 +38,6 @@ void perf_env__exit(struct perf_env *env);int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[]); +int perf_env__read_cpu_topology_map (struct perf_env *env); +#endif /*
__PERF_ENV_H*/tools/perf/util/header.c index renamed from tools/perf/util/header.c +0
-0
151b8310ac70..d6437465f70f100644tools/perf/util/header.c +0
-2@@ -415,8 +415,6 @@ struct cpu_topo {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) @@ -479,9 +477,6@@
try_threads:tools/perf/util/header.c +12
-14} 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);@@ -509,7 +504,7 @@ static struct cpu_topo *build_cpu_topology(void)struct cpu_topo *tp;void *addr;u32 nr, i; -size_t sz, sz_id; +size_t sz;long ncpus;int ret =-1 ;@@ -520,9 +515,8 @@ 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 +2 * sz_id); + addr =calloc (1 ,sizeof (*tp) +2 * sz);if (!addr)return NULL ;@@ -532,10 +526,6 @@ static struct cpu_topo *build_cpu_topology(void) 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);@@ -554,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, {struct cpu_topo *tp;u32 i; -int ret; +int ret, j; tp =build_cpu_topology ();if (!tp)@@ -579,11 +569,17 @@ static int write_cpu_topology(int fd, structperf_header *h__maybe_unused , break; } -for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); + ret =perf_env__read_cpu_topology_map (&perf_env); +if (ret <0 ) + goto done; + +for (j =0 ; j < perf_env.nr_cpus_avail; j++) { + ret =do_write (fd, &perf_env.cpu[j].core_id, +sizeof (perf_env.cpu[j].core_id));if (ret <0 )return ret; - ret =do_write (fd, &tp->phy_pkg_id[i],sizeof (int )); + ret =do_write (fd, &perf_env.cpu[j].socket_id, +sizeof (perf_env.cpu[j].socket_id));if (ret <0 )return ret;}
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Em Thu, Sep 10, 2015 at 08:00:54PM +0000, Liang, Kan escreveu:
Quoted 8 lines
Quoted 7 lines
Em Wed, Sep 09, 2015 at 09:41:18PM +0000, Liang, Kan escreveu:
Quoted 6 lines
tools/perf/util/header.c static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, · line 575
Quoted 4 lines
tools/perf/util/header.c +2
-2-for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); +perf_env__read_cpu_topology_map (&perf_env); +I think we need to handle error here.
Quoted 5 lines
Quoted 3 lines
Ok, adding a test, updated patch below. While doing that, noticed that the in the
thread_sibcase the "ret =do_something()" doesn't makes the whole function fail, will fix later.Except patch 11 & 13 (for reverting), the rest of patches are good to me.
Ok, so, to take it more formally, can I turn this "good to me" as justification for adding "Acked-by: Kan Liang", to those patches?
Please take a look at the other patches in the perf/env branch, I did it while trying to figure it out if the reverts should be kept.
- Arnaldo
RE: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Quoted 11 lines
Em Thu, Sep 10, 2015 at 08:00:54PM +0000, Liang, Kan escreveu:
Quoted 7 lines
Quoted 7 lines
Em Wed, Sep 09, 2015 at 09:41:18PM +0000, Liang, Kan escreveu:
Quoted 6 lines
tools/perf/util/header.c static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, · line 575
Quoted 4 lines
tools/perf/util/header.c +2
-2-for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); +perf_env__read_cpu_topology_map (&perf_env); +I think we need to handle error here.
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Ok, adding a test, updated patch below. While doing that, noticed that the in the
thread_sibcase the "ret =do_something()" doesn't makes the whole function fail, will fix later.Except patch 11 & 13 (for reverting), the rest of patches are good to me.
Ok, so, to take it more formally, can I turn this "good to me" as justification for adding "Acked-by: Kan Liang", to those patches?
Yes.
Quoted 4 lines
Please take a look at the other patches in the perf/env branch, I did it while trying to figure it out if the reverts should be kept.
OK
Thanks,
Kan
Quoted 1 line
- Arnaldo
Re: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
In reply to Arnaldo Carvalho de MeloOn 2015/9/10 21:12, Arnaldo Carvalho de Melo wrote:
[SNIP]
Quoted 13 lines
tools/perf/util/env.c +13
-0+ +int perf_env__read_cpu_topology_map (struct perf_env *env) +{ +int cpu, nr_cpus; + +if (env->cpu !=NULL ) +return 0 ; + +if (env->nr_cpus_avail ==0 ) + env->nr_cpus_avail =sysconf (_SC_NPROCESSORS_CONF); + + nr_cpus = env->nr_cpus_avail; +if (nr_cpus ==-1 )
tools/perf/util/env.c out_free: · line 82
Quoted 10 lines
tools/perf/util/env.c +10
-0+return -EINVAL ; + + env->cpu =calloc (nr_cpus,sizeof (env->cpu[0 ])); +if (env->cpu ==NULL ) +return -ENOMEM ; + +for (cpu =0 ; cpu < nr_cpus; ++cpu) { + env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); + env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + }
Shouldn't we check the failure of these two functions?
At this point perf_env__read_cpu_topology_map and build_cpu_topology are doing similar things. build_cpu_topology() reads /sys/xxxxx/cpu%d/topology/{core,thread}_siblings_list, perf_env__read_cpu_topology_map() reads /sys/xxxxx/cpu%d/topology/core_id,
but build_cpu_topology() returns error if any read failed, but perf_env__read_cpu_topology_map() fills core_id and socket_id with -1 if read fail.
I tried to offline a core between build_cpu_topology() and perf_env__read_cpu_topology_map(), and perf report say:
# perf report -v --header-only -I build id event received for [kernel.kallsyms]: (...) core_id number is too big.You may need to upgrade the perf tool. <-- *see this warning* # ======== # captured on: Sun Feb 15 15:01:05 2009 # hostname : localhost ... # sibling cores : ... # sibling threads : 7 # Core ID and Socket ID information is not available # pmu mappings: not available # ========
Thank you.
Quoted 99 lines
tools/perf/util/env.c +4
-0+ + env->nr_cpus_avail = nr_cpus; +return 0 ; +}tools/perf/util/env.h +2
-0@@ -38,4 +38,6 @@ void perf_env__exit(struct perf_env *env);int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[]); +int perf_env__read_cpu_topology_map (struct perf_env *env); +#endif /* __PERF_ENV_H */ tools/perf/util/header.c +12
-16@@ -415,8 +415,6 @@ struct cpu_topo {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)@@ -479,9 +477,6 @@ 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);@@ -509,7 +504,7 @@ static struct cpu_topo *build_cpu_topology(void)struct cpu_topo *tp;void *addr;u32 nr, i; -size_t sz, sz_id; +size_t sz;long ncpus;int ret =-1 ;@@ -520,9 +515,8 @@ 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 +2 * sz_id); + addr =calloc (1 ,sizeof (*tp) +2 * sz);if (!addr)return NULL ;@@ -532,10 +526,6 @@ static struct cpu_topo *build_cpu_topology(void) 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);@@ -554,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, {struct cpu_topo *tp;u32 i; -int ret; +int ret, j; tp =build_cpu_topology ();if (!tp)@@ -579,11 +569,17 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,break ; } -for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); + ret =perf_env__read_cpu_topology_map (&perf_env); +if (ret <0 ) + goto done; + +for (j =0 ; j < perf_env.nr_cpus_avail; j++) { + ret =do_write (fd, &perf_env.cpu[j].core_id, +sizeof (perf_env.cpu[j].core_id));if (ret <0 )return ret; - ret =do_write (fd, &tp->phy_pkg_id[i],sizeof (int )); + ret =do_write (fd, &perf_env.cpu[j].socket_id, +sizeof (perf_env.cpu[j].socket_id));if (ret <0 )return ret; }
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Em Fri, Sep 11, 2015 at 06:20:03PM +0800, Wangnan (F) escreveu:
Quoted 23 lines · Arnaldo Carvalho de Melo
[SNIP]
Quoted 17 lines
tools/perf/util/env.c +17
-0+ +int perf_env__read_cpu_topology_map (struct perf_env *env) +{ +int cpu, nr_cpus; + +if (env->cpu !=NULL ) +return 0 ; + +if (env->nr_cpus_avail ==0 ) + env->nr_cpus_avail =sysconf (_SC_NPROCESSORS_CONF); + + nr_cpus = env->nr_cpus_avail; +if (nr_cpus ==-1 ) +return -EINVAL ; + + env->cpu =calloc (nr_cpus,sizeof (env->cpu[0 ])); +if (env->cpu ==NULL )
Quoted 8 lines
tools/perf/util/env.c out_free: · line 82
Quoted 6 lines
tools/perf/util/env.c +6
-0+return -ENOMEM ; + +for (cpu =0 ; cpu < nr_cpus; ++cpu) { + env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); + env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + }Shouldn't we check the failure of these two functions?
Humm, the original code, in build_cpu_topology() was not checking that, i.e. if you tried it with or without my patches the result will be the same, no?
Quoted 13 lines
At this point
perf_env__read_cpu_topology_mapandbuild_cpu_topologyare doing
similar things.build_cpu_topology()reads /sys/xxxxx/cpu%d/topology/{core,thread}_siblings_list,perf_env__read_cpu_topology_map()reads /sys/xxxxx/cpu%d/topology/core_id, butbuild_cpu_topology()returns error if any read failed, butperf_env__read_cpu_topology_map()fillscore_idandsocket_idwith -1 if read fail.I tried to offline a core between
build_cpu_topology()andperf_env__read_cpu_topology_map(),
and perf report say:
Quoted 13 lines
# perf report -v --header-only -I build id event received for [kernel.kallsyms]: (...) core_id number is too big.You may need to upgrade the perf tool. <-- *see this warning* # ======== # captured on: Sun Feb 15 15:01:05 2009 # hostname : localhost ... # sibling cores : ... # sibling threads : 7 # Core ID and Socket ID information is not available # pmu mappings: not available # ========
So this is a problem before and after my patches, i.e. If I go on and do, with what we have in acme/perf/core, i.e. none of the changes I'm playing with in perf/env:
$ git remote update acme Fetching acme $ git checkout -b tmp acme/perf/core Branch tmp set up to track remote branch perf/core from acme. Switched to a new branch 'tmp' $ git log --oneline | head -5 7e150fb33a91 perf tests: Introduce iterator function for tests 1765d9b26f84 perf test: Add entry for hists socket filter 207bb55e9193 perf hists browser: Zoom in/out for processor socket 9a2843a5f421 perf report: Introduce --socket-filter option 99851c76436a perf tools: Introduce new sort type "socket" for the processor socket $ rm -rf /tmp/build/perf ; mkdir -p /tmp/build/perf ; make DEBUG=1 -C tools/perf O=/tmp/build/perf install-bin # echo 0 > /sys/devices/system/cpu/cpu2/online $ cat /sys/devices/system/cpu/cpu2/topology/core_id cat: /sys/devices/system/cpu/cpu2/topology/core_id: No such file or directory $ ls -la /sys/devices/system/cpu/cpu2/topology/ ls: cannot access /sys/devices/system/cpu/cpu2/topology/: No such file or directory $ perf record usleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.012 MB perf.data (7 samples) ] [acme@felicio linux]$ perf report --header-only -I # ======== # captured on: Fri Sep 11 11:34:18 2015 # hostname : felicio.ghostprotocols.net # os release : 4.2.0 # perf version : 4.2.g7e150f # arch : x86_64 # nrcpus online : 4 # nrcpus avail : 3 # cpudesc : Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz <SNIP> # node0 meminfo : total = 8085412 kB, free = 5317596 kB # node0 cpu list : 0-1,3 <SNIP> $
We can see multiple bugs here, right? online/avail is swapped, and when online != avail we simply do not record the cpu topology info at all!
If we get that CPU back online:
# echo 1 > /sys/devices/system/cpu/cpu2/online
Then all works:
$ perf record usleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.012 MB perf.data (7 samples) ] $ perf report --header-only -I # ======== # captured on: Fri Sep 11 11:37:31 2015 # hostname : felicio.ghostprotocols.net # os release : 4.2.0 # perf version : 4.2.g7e150f # arch : x86_64 # nrcpus online : 4 # nrcpus avail : 4 # cpudesc : Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz <SNIP> # sibling cores : 0-3 # sibling threads : 0 # sibling threads : 1 # sibling threads : 2 # sibling threads : 3 # CPU 0: Core ID 0, Socket ID 0 # CPU 1: Core ID 1, Socket ID 0 # CPU 2: Core ID 2, Socket ID 0 # CPU 3: Core ID 3, Socket ID 0 # node0 meminfo : total = 8085412 kB, free = 5316992 kB # node0 cpu list : 0-3
So, again, this was not introduced by this patchkit, but it is good that you did these offline tests, so we can fix it!
- Arnaldo
Quoted 90 lines
Quoted 89 lines
tools/perf/util/env.c +4
-0+ + env->nr_cpus_avail = nr_cpus; +return 0 ; +}tools/perf/util/env.h +2
-0@@ -38,4 +38,6 @@ void perf_env__exit(struct perf_env *env);int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[]); +int perf_env__read_cpu_topology_map (struct perf_env *env); +#endif /* __PERF_ENV_H */ tools/perf/util/header.c +12
-16@@ -415,8 +415,6 @@ struct cpu_topo {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)@@ -479,9 +477,6 @@ 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);@@ -509,7 +504,7 @@ static struct cpu_topo *build_cpu_topology(void)struct cpu_topo *tp;void *addr;u32 nr, i; -size_t sz, sz_id; +size_t sz;long ncpus;int ret =-1 ;@@ -520,9 +515,8 @@ 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 +2 * sz_id); + addr =calloc (1 ,sizeof (*tp) +2 * sz);if (!addr)return NULL ;@@ -532,10 +526,6 @@ static struct cpu_topo *build_cpu_topology(void) 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);@@ -554,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, {struct cpu_topo *tp;u32 i; -int ret; +int ret, j; tp =build_cpu_topology ();if (!tp)@@ -579,11 +569,17 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,break ; } -for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); + ret =perf_env__read_cpu_topology_map (&perf_env); +if (ret <0 ) + goto done; + +for (j =0 ; j < perf_env.nr_cpus_avail; j++) { + ret =do_write (fd, &perf_env.cpu[j].core_id, +sizeof (perf_env.cpu[j].core_id));if (ret <0 )return ret; - ret =do_write (fd, &tp->phy_pkg_id[i],sizeof (int )); + ret =do_write (fd, &perf_env.cpu[j].socket_id, +sizeof (perf_env.cpu[j].socket_id));if (ret <0 )return ret; }
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Em Fri, Sep 11, 2015 at 11:40:28AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 31 lines
So this is a problem before and after my patches, i.e. If I go on and do, with what we have in acme/perf/core, i.e. none of the changes I'm playing with in perf/env:
$ git remote update acme Fetching acme $ git checkout -b tmp acme/perf/core Branch tmp set up to track remote branch perf/core from acme. Switched to a new branch 'tmp' $ git log --oneline | head -5 7e150fb33a91 perf tests: Introduce iterator function for tests 1765d9b26f84 perf test: Add entry for hists socket filter 207bb55e9193 perf hists browser: Zoom in/out for processor socket 9a2843a5f421 perf report: Introduce --socket-filter option 99851c76436a perf tools: Introduce new sort type "socket" for the processor socket $ rm -rf /tmp/build/perf ; mkdir -p /tmp/build/perf ; make DEBUG=1 -C tools/perf O=/tmp/build/perf install-bin # echo 0 > /sys/devices/system/cpu/cpu2/online $ cat /sys/devices/system/cpu/cpu2/topology/core_id cat: /sys/devices/system/cpu/cpu2/topology/core_id: No such file or directory $ ls -la /sys/devices/system/cpu/cpu2/topology/ ls: cannot access /sys/devices/system/cpu/cpu2/topology/: No such file or directory $ perf record usleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.012 MB perf.data (7 samples) ] [acme@felicio linux]$ perf report --header-only -I # ======== # captured on: Fri Sep 11 11:34:18 2015 # hostname : felicio.ghostprotocols.net # os release : 4.2.0 # perf version : 4.2.g7e150f # arch : x86_64
Quoted 8 lines
# nrcpus online : 4 # nrcpus avail : 3 # cpudesc : Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz <SNIP> # node0 meminfo : total = 8085412 kB, free = 5317596 kB # node0 cpu list : 0-1,3 <SNIP> $
Stephane, Namhyung, the bug report below is about the online/avail above, they are swapped, full explanation below.
Quoted 35 lines
We can see multiple bugs here, right? online/avail is swapped, and when online != avail we simply do not record the cpu topology info at all!
If we get that CPU back online:
# echo 1 > /sys/devices/system/cpu/cpu2/onlineThen all works:
$ perf record usleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.012 MB perf.data (7 samples) ] $ perf report --header-only -I # ======== # captured on: Fri Sep 11 11:37:31 2015 # hostname : felicio.ghostprotocols.net # os release : 4.2.0 # perf version : 4.2.g7e150f # arch : x86_64 # nrcpus online : 4 # nrcpus avail : 4 # cpudesc : Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz <SNIP> # sibling cores : 0-3 # sibling threads : 0 # sibling threads : 1 # sibling threads : 2 # sibling threads : 3 # CPU 0: Core ID 0, Socket ID 0 # CPU 1: Core ID 1, Socket ID 0 # CPU 2: Core ID 2, Socket ID 0 # CPU 3: Core ID 3, Socket ID 0 # node0 meminfo : total = 8085412 kB, free = 5316992 kB # node0 cpu list : 0-3
Quoted 2 lines
So, again, this was not introduced by this patchkit, but it is good that you did these offline tests, so we can fix it!
Stephane, this was introduced in:
commit fbe96f29ce4b33e0a22219cc7f5996d9157717e3
Author: Stephane Eranian <[email protected]>
Date: Fri Sep 30 15:40:40 2011 +0200
perf tools: Make perf.data more self-descriptive (v8)
------------------
When you write this part:
- HEADER_NRCPUS: number of online/avail cpus
You do:
static int write_nrcpus(int fd, struct perf_header *h __used,
struct perf_evlist *evlist __used)
{
long nr;
u32 nrc, nra;
int ret;
nr = sysconf(_SC_NPROCESSORS_CONF);
if (nr < 0)
return -1;
nrc = (u32)(nr & UINT_MAX);
nr = sysconf(_SC_NPROCESSORS_ONLN);
if (nr < 0)
return -1;
nra = (u32)(nr & UINT_MAX);
ret = do_write(fd, &nrc, sizeof(nrc));
if (ret < 0)
return ret;
return do_write(fd, &nra, sizeof(nra));
}I.e. write what you called 'nrc' using what is in SC_NRPROCESSORS_CONF, that in the documentation for glibc reads:
---------------------
http://www.gnu.org/software/libc/manual/html_node/Processor-Resources.html
sysconf (_SC_NPROCESSORS_CONF)
which returns the number of processors the operating system configured. But it might be possible for the operating system to disable individual processors and so the call
---------------------
Which menas "NR_AVAILABLE", right?
But then you call a variable 'nra' which sounds like you think that what is in _SC_NPROCESSORS_ONLN is the "available" number of CPUs, which is confused a bit more by the glibc docs when refering to _SC_NPROCESSORS_ONLN:
---------------------
sysconf (_SC_NPROCESSORS_ONLN)
returns the number of processors which are currently online (i.e., available).
---------------------
Then, when printing the number of CPUs encoded in the perf.data file by the above write_nrcpus() routine, you did:
static void print_nrcpus(struct perf_header *ph, int fd, FILE *fp)
{
ssize_t ret;
u32 nr;
ret = read(fd, &nr, sizeof(nr));
if (ret != (ssize_t)sizeof(nr))
nr = -1; /* interpreted as error */
if (ph->needs_swap)
nr = bswap_32(nr);
fprintf(fp, "# nrcpus online : %u\n", nr);
ret = read(fd, &nr, sizeof(nr));
if (ret != (ssize_t)sizeof(nr))
nr = -1; /* interpreted as error */
if (ph->needs_swap)
nr = bswap_32(nr);
fprintf(fp, "# nrcpus avail : %u\n", nr);
}You inverted it, no?
So, could you please check if the below patch can have your Acked-by? Namhyung?
Thanks,
- Arnaldo
tools/perf/util/header.c +2 -2
@@ -1438,7 +1438,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,if (ph->needs_swap) nr =bswap_32 (nr); - ph->env.nr_cpus_online = nr; + ph->env.nr_cpus_avail = nr; ret =readn (fd, &nr,sizeof (nr));if (ret !=sizeof (nr))
@@ -1447,7 +1447,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,if (ph->needs_swap) nr =bswap_32 (nr); - ph->env.nr_cpus_avail = nr; + ph->env.nr_cpus_online = nr;return 0 ; }
Re: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Hi Arnaldo,
Quoted 178 lines · Arnaldo Carvalho de Melo
Em Fri, Sep 11, 2015 at 11:40:28AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 31 lines
So this is a problem before and after my patches, i.e. If I go on and do, with what we have in acme/perf/core, i.e. none of the changes I'm playing with in perf/env:
$ git remote update acme Fetching acme $ git checkout -b tmp acme/perf/core Branch tmp set up to track remote branch perf/core from acme. Switched to a new branch 'tmp' $ git log --oneline | head -5 7e150fb33a91 perf tests: Introduce iterator function for tests 1765d9b26f84 perf test: Add entry for hists socket filter 207bb55e9193 perf hists browser: Zoom in/out for processor socket 9a2843a5f421 perf report: Introduce --socket-filter option 99851c76436a perf tools: Introduce new sort type "socket" for the processor socket $ rm -rf /tmp/build/perf ; mkdir -p /tmp/build/perf ; make DEBUG=1 -C tools/perf O=/tmp/build/perf install-bin # echo 0 > /sys/devices/system/cpu/cpu2/online $ cat /sys/devices/system/cpu/cpu2/topology/core_id cat: /sys/devices/system/cpu/cpu2/topology/core_id: No such file or directory $ ls -la /sys/devices/system/cpu/cpu2/topology/ ls: cannot access /sys/devices/system/cpu/cpu2/topology/: No such file or directory $ perf record usleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.012 MB perf.data (7 samples) ] [acme@felicio linux]$ perf report --header-only -I # ======== # captured on: Fri Sep 11 11:34:18 2015 # hostname : felicio.ghostprotocols.net # os release : 4.2.0 # perf version : 4.2.g7e150f # arch : x86_64Quoted 8 lines
# nrcpus online : 4 # nrcpus avail : 3 # cpudesc : Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz <SNIP> # node0 meminfo : total = 8085412 kB, free = 5317596 kB # node0 cpu list : 0-1,3 <SNIP> $Stephane, Namhyung, the bug report below is about the online/avail above, they are swapped, full explanation below.
Quoted 35 lines
We can see multiple bugs here, right? online/avail is swapped, and when online != avail we simply do not record the cpu topology info at all!
If we get that CPU back online:
# echo 1 > /sys/devices/system/cpu/cpu2/onlineThen all works:
$ perf record usleep 1 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.012 MB perf.data (7 samples) ] $ perf report --header-only -I # ======== # captured on: Fri Sep 11 11:37:31 2015 # hostname : felicio.ghostprotocols.net # os release : 4.2.0 # perf version : 4.2.g7e150f # arch : x86_64 # nrcpus online : 4 # nrcpus avail : 4 # cpudesc : Intel(R) Core(TM) i5-2400 CPU @ 3.10GHz <SNIP> # sibling cores : 0-3 # sibling threads : 0 # sibling threads : 1 # sibling threads : 2 # sibling threads : 3 # CPU 0: Core ID 0, Socket ID 0 # CPU 1: Core ID 1, Socket ID 0 # CPU 2: Core ID 2, Socket ID 0 # CPU 3: Core ID 3, Socket ID 0 # node0 meminfo : total = 8085412 kB, free = 5316992 kB # node0 cpu list : 0-3Quoted 2 lines
So, again, this was not introduced by this patchkit, but it is good that you did these offline tests, so we can fix it!
Stephane, this was introduced in:
commit
fbe96f29ce4b33e0a22219cc7f5996d9157717e3
Author: Stephane Eranian <[email protected]>
Date: Fri Sep 30 15:40:40 2011 +0200perf tools: Make perf.data more self-descriptive (v8)
------------------
When you write this part:
-
HEADER_NRCPUS: number of online/avail cpusYou do:
static int write_nrcpus(int fd, struct
perf_header*h__used,
structperf_evlist*evlist__used){ long nr; u32 nrc, nra; int ret; nr = sysconf(_SC_NPROCESSORS_CONF); if (nr < 0) return -1; nrc = (u32)(nr & UINT_MAX); nr = sysconf(_SC_NPROCESSORS_ONLN); if (nr < 0) return -1; nra = (u32)(nr & UINT_MAX); ret = do_write(fd, &nrc, sizeof(nrc)); if (ret < 0) return ret; return do_write(fd, &nra, sizeof(nra)); }I.e. write what you called 'nrc' using what is in
SC_NRPROCESSORS_CONF, that in the documentation for glibc reads:---------------------
http://www.gnu.org/software/libc/manual/html_node/Processor-Resources.html
sysconf (
_SC_NPROCESSORS_CONF)which returns the number of processors the operating system configured. But it might be possible for the operating system to disable individual processors and so the call
---------------------
Which menas "
NR_AVAILABLE", right?But then you call a variable 'nra' which sounds like you think that what is in
_SC_NPROCESSORS_ONLNis the "available" number of CPUs, which is confused a bit more by the glibc docs when refering to_SC_NPROCESSORS_ONLN:---------------------
sysconf (_SC_NPROCESSORS_ONLN)returns the number of processors which are currently online (i.e., available).
---------------------Then, when printing the number of CPUs encoded in the perf.data file by the above
write_nrcpus()routine, you did:static void
print_nrcpus(struct perf_header *ph, int fd, FILE *fp){ ssize_t ret; u32 nr; ret = read(fd, &nr, sizeof(nr)); if (ret != (ssize_t)sizeof(nr)) nr = -1; /* interpreted as error */ if (ph->needs_swap) nr = bswap_32(nr); fprintf(fp, "# nrcpus online : %u\n", nr); ret = read(fd, &nr, sizeof(nr)); if (ret != (ssize_t)sizeof(nr)) nr = -1; /* interpreted as error */ if (ph->needs_swap) nr = bswap_32(nr); fprintf(fp, "# nrcpus avail : %u\n", nr); }
Quoted 4 lines
You inverted it, no?
So, could you please check if the below patch can have your Acked-by? Namhyung?
Looks good to me.
Thanks,
Namhyung
Quoted 27 lines
Thanks,
- Arnaldo
tools/perf/util/header.c +2
-2@@ -1438,7 +1438,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,if (ph->needs_swap) nr =bswap_32 (nr); - ph->env.nr_cpus_online = nr; + ph->env.nr_cpus_avail = nr; ret =readn (fd, &nr,sizeof (nr));if (ret !=sizeof (nr))@@ -1447,7 +1447,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,if (ph->needs_swap) nr =bswap_32 (nr); - ph->env.nr_cpus_avail = nr; + ph->env.nr_cpus_online = nr;return 0 ; }
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 04/13] perf env: Introduce read_cpu_topology_map() method
Em Sat, Sep 12, 2015 at 01:14:02AM +0900, Namhyung Kim escreveu:
Quoted 8 lines
Quoted 4 lines
You inverted it, no?
So, could you please check if the below patch can have your Acked-by? Namhyung?
Looks good to me.
Acked-by Namhyung Kim <[email protected]>
Thanks, added it to the patch, after lunch I should have another patch for another bug introduced in the same patch, i.e. if one CPU is offlined, we simply refuse to collect the topology information.
To fix it, I think, we need to insert "(offline)" where one expects to find the thread and core siblings info.
- Arnaldo
tip-bot for Arnaldo Carvalho de Melo
merge bot[tip:perf/urgent] perf header: Fixup reading of HEADER_NRCPUS feature
In reply to Arnaldo Carvalho de Meloperf header: Fixup reading of HEADER_NRCPUS feature
Commit-ID: caa470475d9b59eeff093ae650800d34612c4379 Gitweb: http://git.kernel.org/tip/caa470475d9b59eeff093ae650800d34612c4379 Author: Arnaldo Carvalho de Melo <[email protected]> AuthorDate: Fri, 11 Sep 2015 12:36:12 -0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Sun, 13 Sep 2015 11:41:34 -0300
perf header: Fixup reading of HEADER_NRCPUS feature
The original patch introducing this header wrote the number of CPUs available and online in one order and then swapped those values when reading, fix it.
Before:
# perf record usleep 1 # perf report --header-only | grep 'nrcpus \(online\|avail\)' # nrcpus online : 4 # nrcpus avail : 4 # echo 0 > /sys/devices/system/cpu/cpu2/online # perf record usleep 1 # perf report --header-only | grep 'nrcpus \(online\|avail\)' # nrcpus online : 4 # nrcpus avail : 3 # echo 0 > /sys/devices/system/cpu/cpu1/online # perf record usleep 1 # perf report --header-only | grep 'nrcpus \(online\|avail\)' # nrcpus online : 4 # nrcpus avail : 2
After the fix, bringing back the CPUs online:
# perf report --header-only | grep 'nrcpus \(online\|avail\)' # nrcpus online : 2 # nrcpus avail : 4 # echo 1 > /sys/devices/system/cpu/cpu2/online # perf record usleep 1 # perf report --header-only | grep 'nrcpus \(online\|avail\)' # nrcpus online : 3 # nrcpus avail : 4 # echo 1 > /sys/devices/system/cpu/cpu1/online # perf record usleep 1 # perf report --header-only | grep 'nrcpus \(online\|avail\)' # nrcpus online : 4 # nrcpus avail : 4
--- tools/perf/util/header.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/util/header.c +2 -2
@@ -1438,7 +1438,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,if (ph->needs_swap) nr =bswap_32 (nr); - ph->env.nr_cpus_online = nr; + ph->env.nr_cpus_avail = nr; ret =readn (fd, &nr,sizeof (nr));if (ret !=sizeof (nr))
@@ -1447,7 +1447,7 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused,if (ph->needs_swap) nr =bswap_32 (nr); - ph->env.nr_cpus_avail = nr; + ph->env.nr_cpus_online = nr;return 0 ; }
tip-bot for Arnaldo Carvalho de Melo
merge bot[tip:perf/core] perf env: Introduce read_cpu_topology_map() method
In reply to Arnaldo Carvalho de Meloperf env: Introduce read_cpu_topology_map() method
Commit-ID: aa36ddd7afbb0a3db216c1391e28cd6d80ed1706 Gitweb: http://git.kernel.org/tip/aa36ddd7afbb0a3db216c1391e28cd6d80ed1706 Author: Arnaldo Carvalho de Melo <[email protected]> AuthorDate: Wed, 9 Sep 2015 10:37:01 -0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Mon, 14 Sep 2015 12:50:28 -0300
perf env: Introduce read_cpu_topology_map() method
Out of the code to write the cpu topology map in the perf.data file header.
Now if one needs the CPU topology map for the running machine, one needs to call perf_env__read_cpu_topology_map(perf_env) and the info will be stored in perf_env.cpu.
For now we're using a global perf_env variable, that will have its contents freed after we run a builtin.
v2: Check perf_env__read_cpu_topology_map() return in
write_cpu_topology() (Kan Liang)
--- tools/perf/perf.c | 2 ++ tools/perf/util/env.c | 28 ++++++++++++++++++++++++++++ tools/perf/util/env.h | 2 ++ tools/perf/util/header.c | 28 ++++++++++++---------------- 4 files changed, 44 insertions(+), 16 deletions(-)
tools/perf/perf.c +2 -0
@@ -8,6 +8,7 @@*/ #include "builtin.h" +#include "util/env.h" #include "util/exec_cmd.h" #include "util/cache.h" #include "util/quote.h"
@@ -369,6 +370,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) status = p->fn (argc, argv, prefix);exit_browser (status); +perf_env__exit (&perf_env);if (status)return status &0xff ;
tools/perf/util/env.c +28 -0
@@ -1,3 +1,4 @@ +#include "cpumap.h" #include "env.h" #include "util.h"
@@ -56,3 +57,30 @@ out_free: out_enomem:return -ENOMEM ; } + +int perf_env__read_cpu_topology_map (struct perf_env *env) +{ +int cpu, nr_cpus; + +if (env->cpu !=NULL ) +return 0 ; + +if (env->nr_cpus_avail ==0 ) + env->nr_cpus_avail =sysconf (_SC_NPROCESSORS_CONF); + + nr_cpus = env->nr_cpus_avail; +if (nr_cpus ==-1 ) +return -EINVAL ; + + env->cpu =calloc (nr_cpus,sizeof (env->cpu[0 ])); +if (env->cpu ==NULL ) +return -ENOMEM ; + +for (cpu =0 ; cpu < nr_cpus; ++cpu) { + env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); + env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + } + + env->nr_cpus_avail = nr_cpus; +return 0 ; +}
tools/perf/util/env.h +2 -0
@@ -39,4 +39,6 @@ void perf_env__exit(struct perf_env *env);int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[]); +int perf_env__read_cpu_topology_map (struct perf_env *env); +#endif /* __PERF_ENV_H */
tools/perf/util/header.c +12 -16
@@ -415,8 +415,6 @@ struct cpu_topo {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)
@@ -479,9 +477,6 @@ 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);
@@ -509,7 +504,7 @@ static struct cpu_topo *build_cpu_topology(void)struct cpu_topo *tp;void *addr;u32 nr, i; -size_t sz, sz_id; +size_t sz;long ncpus;int ret =-1 ;
@@ -520,9 +515,8 @@ 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 +2 * sz_id); + addr =calloc (1 ,sizeof (*tp) +2 * sz);if (!addr)return NULL ;
@@ -532,10 +526,6 @@ static struct cpu_topo *build_cpu_topology(void) 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);
@@ -554,7 +544,7 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, {struct cpu_topo *tp;u32 i; -int ret; +int ret, j; tp =build_cpu_topology ();if (!tp)
@@ -579,11 +569,17 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused,break ; } -for (i =0 ; i < tp->cpu_nr; i++) { - ret =do_write (fd, &tp->core_id[i],sizeof (int )); + ret =perf_env__read_cpu_topology_map (&perf_env); +if (ret <0 ) + goto done; + +for (j =0 ; j < perf_env.nr_cpus_avail; j++) { + ret =do_write (fd, &perf_env.cpu[j].core_id, +sizeof (perf_env.cpu[j].core_id));if (ret <0 )return ret; - ret =do_write (fd, &tp->phy_pkg_id[i],sizeof (int )); + ret =do_write (fd, &perf_env.cpu[j].socket_id, +sizeof (perf_env.cpu[j].socket_id));if (ret <0 )return ret; }
Arnaldo Carvalho de Melo
maintainerPATCH 5/13 perf sort: Set flag stating if the "socket" key is being used
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Because it will require that we read the current machine CPU topology map when the tool is not processing a perf.data file, from where it would obtain that map.
Other tools may want to do some other initialization in such case.
We need to have a better way to figure out if a given sort key is being used, perhaps a bitmap, but that is left for another patch.
--- tools/perf/util/sort.c | 3 +++ tools/perf/util/sort.h | 1 + 2 files changed, 4 insertions(+)
tools/perf/util/sort.c +3 -0
@@ -21,6 +21,7 @@ int sort__need_collapse = 0;int sort__has_parent =0 ;int sort__has_sym =0 ;int sort__has_dso =0 ; +int sort__has_socket =0 ;enum sort_mode sort__mode =SORT_MODE__NORMAL ;
@@ -1572,6 +1573,8 @@ int sort_dimension__add(const char *tok) }else if (sd->entry == &sort_dso) { sort__has_dso =1 ; + }else if (sd->entry == &sort_socket) { + sort__has_socket =1 ; }return __sort_dimension__add (sd);
tools/perf/util/sort.h +1 -0
@@ -34,6 +34,7 @@ extern int have_ignore_callees;extern int sort__need_collapse;extern int sort__has_parent;extern int sort__has_sym; +extern int sort__has_socket;extern enum sort_mode sort__mode;extern struct sort_entry sort_comm;extern struct sort_entry sort_dso;
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 6/13 perf top: Cache the cpu topology info when "-s socket" is used
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We need to cache that info to use in perf_event__preprocess_sample(), so that we don't read sysfs files for each sample.
The next patches will add machine->env pointer that will point to either the perf_env read from a perf.data file header or from the current system.
Tools needing some specific info should call the perf_env methods that cache the info, in this case perf_env__read_cpu_topology_map().
--- tools/perf/builtin-top.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
tools/perf/builtin-top.c +15 -0
@@ -963,6 +963,13 @@ static int __cmd_top(struct perf_top *top)machine__synthesize_threads (&top->session->machines.host, &opts->target, top->evlist->threads, false, opts->proc_map_timeout); + +if (sort__has_socket) { + ret =perf_env__read_cpu_topology_map (&perf_env); +if (ret <0 ) + goto out_err_cpu_topo; + } + ret =perf_top__start_counters (top);if (ret) goto out_delete;
@@ -1020,6 +1027,14 @@ out_delete: top->session =NULL ;return ret; + +out_err_cpu_topo: { +char errbuf[BUFSIZ ]; +const char *err =strerror_r (-ret, errbuf,sizeof (errbuf)); + +ui__error ("Could not read the CPU topology map: %s\n" , err); + goto out_delete; +} } static int
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 7/13 perf hists browser: Fixup the "cpu" column width calculation
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Since we were not setting it to at least 3 chars ('CPU'), it was being reset to zero when recalculating the columns width when refreshing the screen, in 'perf top'. Fix it.
--- tools/perf/util/hist.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/hist.c +1 -0
@@ -146,6 +146,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)hists__set_unres_dso_col_len (hists,HISTC_MEM_DADDR_DSO ); } +hists__new_col_len (hists,HISTC_CPU ,3 );hists__new_col_len (hists,HISTC_SOCKET ,6 );hists__new_col_len (hists,HISTC_MEM_LOCKED ,6 );hists__new_col_len (hists,HISTC_MEM_TLB ,22 );
Signature · 1 line
2.1.0
Re: [PATCH 07/13] perf hists browser: Fixup the "cpu" column width calculation
Quoted 5 lines · Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <[email protected]>
Since we were not setting it to at least 3 chars ('CPU'), it was being reset to zero when recalculating the columns width when refreshing the screen, in 'perf top'. Fix it.
Quoted 27 lines
Cc Adrian Hunter <[email protected]>Cc Borislav Petkov <[email protected]>Cc David Ahern <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Jiri Olsa <[email protected]>Cc Kan Liang <[email protected]>Cc Namhyung Kim <[email protected]>Cc Stephane Eranian <[email protected]>Cc Wang Nan <[email protected]>Signed-off-by Arnaldo Carvalho de Melo <[email protected]>--- tools/perf/util/hist.c | 1 + 1 file changed, 1 insertion(+)tools/perf/util/hist.c +1
-0@@ -146,6 +146,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)hists__set_unres_dso_col_len (hists,HISTC_MEM_DADDR_DSO ); } +hists__new_col_len (hists,HISTC_CPU ,3 );hists__new_col_len (hists,HISTC_SOCKET ,6 );hists__new_col_len (hists,HISTC_MEM_LOCKED ,6 );hists__new_col_len (hists,HISTC_MEM_TLB ,22 );
Arnaldo Carvalho de Melo
maintainerPATCH 8/13 perf machine: Add pointer to sample's environment
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
The 'struct machine' represents the machine where the samples were/are being collected, and we also have a 'struct perf_env' with extra details about such machine, that we were collecting at 'perf.data' creation time but we also needed when no perf.data file is being used, such as in 'perf top'.
So, get those structs closer together, as they provide a bigger picture of the sample's environment.
In 'perf session', when the file argument is NULL, we can assume that the tool is sampling the running machine, so point machine->env to the global put in place in previous patches, while set it to the perf_header.env one when reading from a file.
This paves the way for machine->env to be used in perf_event__preprocess_sample to populate addr_location.socket.
--- tools/perf/util/header.c | 1 + tools/perf/util/machine.c | 1 + tools/perf/util/machine.h | 1 + tools/perf/util/session.c | 2 ++ 4 files changed, 5 insertions(+)
tools/perf/util/header.c +1 -0
@@ -2559,6 +2559,7 @@ int perf_session__read_header(struct perf_session *session)return -ENOMEM ; session->evlist->env = &header->env; + session->machines.host.env = &header->env;if (perf_data_file__is_pipe (file))return perf_header__read_pipe (session);
tools/perf/util/machine.c +1 -0
@@ -35,6 +35,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) machine->last_match =NULL ; machine->vdso_info =NULL ; + machine->env =NULL ; machine->pid = pid;
tools/perf/util/machine.h +1 -0
@@ -34,6 +34,7 @@ struct machine {struct list_head dead_threads;struct thread *last_match;struct vdso_info *vdso_info; +struct perf_env *env;struct dsos dsos;struct map_groups kmaps;struct map *vmlinux_maps[MAP__NR_TYPES ];
tools/perf/util/session.c +2 -0
@@ -138,6 +138,8 @@ struct perf_session *perf_session__new(struct perf_data_file *file,perf_session__set_id_hdr_size (session);perf_session__set_comm_exec (session); } + }else { + session->machines.host.env = &perf_env; }if (!file ||perf_data_file__is_write (file)) {
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 9/13 perf event: Use machine->env to find the cpu -> socket mapping
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Instead of reading /sysfs/devices/system/cpu/cpu%d/topology/physical_package_id for each sample.
While at it, check that the sample has PERF_SAMPLE_CPU, i.e. that sample.cpu >= 0, to avoid an out of bounds access.
--- tools/perf/util/event.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
tools/perf/util/event.c +8 -1
@@ -1021,7 +1021,14 @@ int perf_event__preprocess_sample(const union perf_event *event, al->sym =NULL ; al->cpu = sample->cpu; - al->socket =cpu_map__get_socket_id (al->cpu); + al->socket =-1 ; + +if (al->cpu >=0 ) { +struct perf_env *env = machine->env; + +if (env && env->cpu) + al->socket = env->cpu[al->cpu].socket_id; + }if (al->map) {struct dso *dso = al->map->dso;
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 10/13 perf report: Do not blindly use env->cpu[al.cpu].socket_id
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
As al.cpu may be -1, i.e. no PERF_SAMPLE_CPU, and env->cpu may be NULL.
Rely instead on the work now done in perf_event__preprocess_sample(), that does all those checks.
--- tools/perf/builtin-report.c | 4 ---- 1 file changed, 4 deletions(-)
tools/perf/builtin-report.c +0 -4
@@ -150,7 +150,6 @@ static int process_sample_event(struct perf_tool *tool, .add_entry_cb = hist_iter__report_callback, };int ret =0 ; -struct perf_env *env = evsel->evlist->env;if (perf_event__preprocess_sample (event, machine, &al, sample) <0 ) { pr_debug("problem processing %d event, skipping it.\n",
@@ -158,9 +157,6 @@ static int process_sample_event(struct perf_tool *tool,return -1 ; } -/* read socket id from perf.data for perf report */ - al.socket = env->cpu[al.cpu].socket_id; -if (rep->hide_unresolved && al.sym ==NULL ) goto out_put;
Signature · 1 line
2.1.0
Re: [PATCH 10/13] perf report: Do not blindly use env->cpu[al.cpu].socket_id
Quoted 36 lines · Arnaldo Carvalho de Melo
From: Arnaldo Carvalho de Melo <[email protected]>
As al.cpu may be -1, i.e. no
PERF_SAMPLE_CPU, andenv->cpumay be NULL.Rely instead on the work now done in
perf_event__preprocess_sample(), that does all those checks.Reported-by Wang Nan <[email protected]>Based-on-a-patch-by Jiri Olsa <[email protected]>Cc Adrian Hunter <[email protected]>Cc Borislav Petkov <[email protected]>Cc David Ahern <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Kan Liang <[email protected]>Cc Namhyung Kim <[email protected]>Cc Stephane Eranian <[email protected]>Cc Wang Nan <[email protected]>Signed-off-by Arnaldo Carvalho de Melo <[email protected]>--- tools/perf/builtin-report.c | 4 ---- 1 file changed, 4 deletions(-)tools/perf/builtin-report.c +0
-1@@ -150,7 +150,6 @@ static int process_sample_event(struct perf_tool *tool, .add_entry_cb = hist_iter__report_callback, };int ret =0 ; -struct perf_env *env = evsel->evlist->env;if (perf_event__preprocess_sample (event, machine, &al, sample) <0 ) { pr_debug("problem processing %d event, skipping it.\n",
tools/perf/builtin-report.c static int process_sample_event(struct perf_tool *tool, · line 162
Quoted 9 lines
tools/perf/builtin-report.c +0
-3@@ -158,9 +157,6 @@ static int process_sample_event(struct perf_tool *tool,return -1 ; } -/* read socket id from perf.data for perf report */ - al.socket = env->cpu[al.cpu].socket_id; -if (rep->hide_unresolved && al.sym ==NULL ) goto out_put;
I tested this patch on an 8 cores SOC. No segfault found now.
Normal case:
# ./perf record -a ls
# ...
# ./perf_arm64 report -v --stdio -s socket,cpu
build id event received for [kernel.kallsyms]: ...
# To display the perf.data header info, please use
--header/--header-only options.
#
symsrc__init: cannot get elf header.
Looking at the vmlinux_path (7 entries long)
Failed to open /proc/kcore. Note /proc/kcore requires CAP_SYS_RAWIO
capability to access.
Using /proc/kallsyms for symbols
Failed to open /sbin/adbd, continuing without symbols
#
# Total Lost Samples: 0
#
# Samples: 291 of event 'cycles'
# Event count (approx.): 40968659
#
# Overhead Socket CPU
# ........ ...... ...
#
58.01% 000 004
35.61% 000 007
3.65% 000 005
1.23% 001 000
1.18% 001 001
0.19% 000 006
0.08% 001 002
0.07% 001 003If one of CPUs is offlined before 'perf record':
# ./perf record -a ls
# ...
# ./perf_arm64 report -v --stdio -s socket,cpu
build id event received for [kernel.kallsyms]:
d287ff3393fb1a01d3a785c3a1dac6e63d973bce
# To display the perf.data header info, please use
--header/--header-only options.
#
symsrc__init: cannot get elf header.
Looking at the vmlinux_path (7 entries long)
Failed to open /proc/kcore. Note /proc/kcore requires CAP_SYS_RAWIO
capability to access.
Using /proc/kallsyms for symbols
Failed to open /sbin/adbd, continuing without symbols
#
# Total Lost Samples: 0
#
# Samples: 304 of event 'cycles'
# Event count (approx.): 42027298
#
# Overhead Socket CPU
# ........ ...... ...
#
60.25% -001 004
32.69% -001 007
5.00% -001 005
1.34% -001 003
0.37% -001 000
0.20% -001 006
0.08% -001 002
0.07% -001 001And if CPU is offlined during perf record (between build_cpu_topology() and perf_env__read_cpu_topology_map()):
# ./perf report -v --stdio -s socket,cpu
build id event received for [kernel.kallsyms]: ...
core_id number is too big.You may need to upgrade the perf tool. <---
*please see this line*
# To display the perf.data header info, please use
--header/--header-only options.
#
symsrc__init: cannot get elf header.
Looking at the vmlinux_path (7 entries long)
Failed to open /proc/kcore. Note /proc/kcore requires CAP_SYS_RAWIO
capability to access.
Using /proc/kallsyms for symbols
#
# Total Lost Samples: 0
#
# Samples: 278 of event 'cycles'
# Event count (approx.): 37729429
#
# Overhead Socket CPU
# ........ ...... ...
#
59.06% -001 004
36.93% -001 007
1.33% -001 000
1.18% -001 005
0.82% -001 006
0.50% -001 001
0.08% -001 002
0.08% -001 003Arnaldo Carvalho de Melo
maintainerPATCH 11/13 Revert "perf evsel: Add a backpointer to the evlist a evsel is in"
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This reverts commit d49e4695077278ee3016cd242967de23072ec331.
We don't need it, using machine->env seems to be enough.
--- tools/perf/util/evlist.c | 2 -- tools/perf/util/evsel.c | 2 -- tools/perf/util/evsel.h | 4 ---- 3 files changed, 8 deletions(-)
tools/perf/util/evlist.c +0 -2
@@ -98,7 +98,6 @@ static void perf_evlist__purge(struct perf_evlist *evlist)evlist__for_each_safe (evlist, n, pos) {list_del_init (&pos->node); - pos->evlist =NULL ;perf_evsel__delete (pos); }
@@ -126,7 +125,6 @@ void perf_evlist__delete(struct perf_evlist *evlist)void perf_evlist__add (struct perf_evlist *evlist,struct perf_evsel *entry) { - entry->evlist = evlist;list_add_tail (&entry->node, &evlist->entries); entry->idx = evlist->nr_entries; entry->tracking = !entry->idx;
tools/perf/util/evsel.c +0 -2
@@ -206,7 +206,6 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->leader = evsel; evsel->unit ="" ; evsel->scale =1.0 ; - evsel->evlist =NULL ;INIT_LIST_HEAD (&evsel->node);INIT_LIST_HEAD (&evsel->config_terms); perf_evsel__object.init (evsel);
@@ -1027,7 +1026,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)void perf_evsel__exit (struct perf_evsel *evsel) {assert (list_empty (&evsel->node)); -assert (evsel->evlist ==NULL );perf_evsel__free_fd (evsel);perf_evsel__free_id (evsel);perf_evsel__free_config_terms (evsel);
tools/perf/util/evsel.h +0 -4
@@ -60,9 +60,6 @@ struct perf_evsel_config_term {/** struct perf_evsel - event selector * -* @evlist - evlist this evsel is in, if it is in one. -* @node - To insert it into evlist->entries or in other list_heads, say in -* the event parsing routines. * @name - Can be set to retain the original event name passed by the user, * so that when showing results in tools such as 'perf stat', we * show the name used, not some alias.
@@ -76,7 +73,6 @@ struct perf_evsel_config_term {*/ struct perf_evsel {struct list_head node; -struct perf_evlist *evlist;struct perf_event_attr attr;char *filter;struct xyarray *fd;
Signature · 1 line
2.1.0
RE: [PATCH 11/13] Revert "perf evsel: Add a backpointer to the evlist a evsel is in"
Quoted 8 lines
From: Arnaldo Carvalho de Melo <[email protected]>
This reverts commit
d49e4695077278ee3016cd242967de23072ec331.We don't need it, using
machine->envseems to be enough.
The patchset to dump freq per sample need commit d49e469507. It also needs commit 2c07144dfc which is revert by PATCH 13.
https://lkml.org/lkml/2015/9/8/758
Otherwise, we have to pass evlist and machine through dump_sample.
Quoted 83 lines
Cc Adrian Hunter <[email protected]>Cc Borislav Petkov <[email protected]>Cc David Ahern <[email protected]>Cc Frederic Weisbecker <[email protected]>Cc Jiri Olsa <[email protected]>Cc Kan Liang <[email protected]>Cc Namhyung Kim <[email protected]>Cc Stephane Eranian <[email protected]>Cc Wang Nan <[email protected]>Signed-off-by Arnaldo Carvalho de Melo <[email protected]>--- tools/perf/util/evlist.c | 2 -- tools/perf/util/evsel.c | 2 -- tools/perf/util/evsel.h | 4 ---- 3 files changed, 8 deletions(-)tools/perf/util/evlist.c index renamed from tools/perf/util/evlist.c +0
-0
d51a5200c8af..09b4ec221dda100644tools/perf/util/evlist.c +0
-2@@ -98,7 +98,6 @@ static void perf_evlist__purge(struct perf_evlist *evlist)evlist__for_each_safe (evlist, n, pos) {list_del_init (&pos->node); - pos->evlist =NULL ;perf_evsel__delete (pos); }@@ -126,7 +125,6 @@ void perf_evlist__delete(struct perf_evlist *evlist)void perf_evlist__add (struct perf_evlist *evlist,struct perf_evsel *entry) { - entry->evlist = evlist;list_add_tail (&entry->node, &evlist->entries); entry->idx = evlist->nr_entries; entry->tracking = !entry->idx;tools/perf/util/evsel.c index renamed from tools/perf/util/evsel.c +0
-0
771ade4d5966..8f4d45002461100644tools/perf/util/evsel.c +0
-2@@ -206,7 +206,6 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->leader = evsel; evsel->unit ="" ; evsel->scale =1.0 ; - evsel->evlist =NULL ;INIT_LIST_HEAD (&evsel->node);INIT_LIST_HEAD (&evsel->config_terms); perf_evsel__object.init (evsel);@@ -1027,7 +1026,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads) void perf_evsel__exit(struct perf_evsel *evsel) {assert (list_empty (&evsel->node)); -assert (evsel->evlist ==NULL );perf_evsel__free_fd (evsel);perf_evsel__free_id (evsel);perf_evsel__free_config_terms (evsel);tools/perf/util/evsel.h index renamed from tools/perf/util/evsel.h +0
-0
298e6bbca200..93ac6b128149100644tools/perf/util/evsel.h +0
-3@@ -60,9 +60,6 @@ struct perf_evsel_config_term {/** struct perf_evsel - event selector * -* @evlist - evlist this evsel is in, if it is in one. -* @node - To insert it into evlist->entries or in other list_heads, say in -* the event parsing routines. * @name - Can be set to retain the original event name passed by the user, * so that when showing results in tools such as 'perf stat', we * show the name used, not some alias.
tools/perf/util/evsel.h +0
-2@@ -76,7 +73,6 @@ struct perf_evsel_config_term {*/ struct perf_evsel {struct list_head node; -struct perf_evlist *evlist;struct perf_event_attr attr;char *filter;struct xyarray *fd; --2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 12/13 perf evsel: Remove forward declaration of 'struct perf_evlist'
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We have no use for it in evsel.h.
--- tools/perf/util/evsel.h | 1 - 1 file changed, 1 deletion(-)
tools/perf/util/evsel.h +0 -1
@@ -125,7 +125,6 @@ union u64_swap {struct cpu_map ;struct target ;struct thread_map ; -struct perf_evlist ;struct record_opts ;static inline struct cpu_map *perf_evsel__cpus (struct perf_evsel *evsel)
Signature · 1 line
2.1.0
Arnaldo Carvalho de Melo
maintainerPATCH 13/13 Revert "perf evlist: Add backpointer for perf_env to evlist"
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This reverts commit 2c07144dfce366e21465cc7b0ada9f0b6dc7b7ed.
We don't need it, machine->env provides what is needed.
--- tools/perf/util/evlist.h | 1 - tools/perf/util/header.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-)
tools/perf/util/evlist.h +0 -1
@@ -56,7 +56,6 @@ struct perf_evlist {struct cpu_map *cpus;struct perf_evsel *selected;struct events_stats stats; -struct perf_env *env; };struct perf_evsel_str_handler {
tools/perf/util/header.c +1 -1
@@ -2558,8 +2558,8 @@ int perf_session__read_header(struct perf_session *session)if (session->evlist ==NULL )return -ENOMEM ; - session->evlist->env = &header->env; session->machines.host.env = &header->env; +if (perf_data_file__is_pipe (file))return perf_header__read_pipe (session);
Signature · 1 line
2.1.0
Quoted 14 lines · Arnaldo Carvalho de Melo
Hi,
Please take a look at these changes to fix the problems reported by
Wang Nan wrt accesses to thecpu_topology_mapinformation.The fixes are present on these following two csets:
perf event: Use
machine->envto find the cpu -> socket mapping perf report: Do not blindly use env->cpu[al.cpu].socket_idThe rest are fixes made while working on this, infrastructure to enable
the fixes, reverts for things that ended up not being necessary and some cleanups.
Quoted 6 lines
It is available at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gitperf/envPlease let me know if I can have your Acked-by, Tested-by or
Reviewed-by.
perf_env holds the data for perf.data session.. is the plan to keep it like this, or it's to be used in some other way? Moving it out of session/header real suggest that.. just asking ;-)
jirka
Arnaldo Carvalho de Melo
maintainerEm Thu, Sep 10, 2015 at 11:19:06AM +0200, Jiri Olsa escreveu:
Quoted 13 lines · Arnaldo Carvalho de Melo
Quoted 12 lines
Please take a look at these changes to fix the problems reported by
Wang Nan wrt accesses to thecpu_topology_mapinformation.The fixes are present on these following two csets:
perf event: Use
machine->envto find the cpu -> socket mapping perf report: Do not blindly use env->cpu[al.cpu].socket_idThe rest are fixes made while working on this, infrastructure to enable
the fixes, reverts for things that ended up not being necessary and some cleanups.
Quoted 8 lines
Quoted 6 lines
It is available at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gitperf/envPlease let me know if I can have your Acked-by, Tested-by or
Reviewed-by.
perf_envholds the data for perf.data session.. is the plan to keep
No, perf_env holds the data for the environment where samples were taken.
It is needed to generate a perf.data file, and also now is needed to map cpu -> socket_id, be it in a live session, where no perf.data file, nor perf_session stuff is used (perf trace, I keep meaning to do the 'perf top' conversion away from perf_session, others in the future).
I.e. perf_event__preprocess_sample() doesn't have to know if the samples were freshly taken or if they come from another machine, possibly of a different architecture.
Quoted 2 lines
it like this, or it's to be used in some other way? Moving it out of session/header real suggest that.. just asking ;-)
They are already used in another way, i.e. we need to have that mapping of cpu -> socket_id, to stop reading /sys/ to figure that out. I.e. perf_env is, among other sampling/tracing environment, a cache of that info, taken at perf.data generation time or at tool start time, if that info is needed (i.e. if we use "socket" in -s).
- Arnaldo
Hi Arnaldo,
I have tested patch 1 to 10. They looks good to me except patch 4/13. Please see my email in that thread.
However, during the testing I found a limitation related to cpu online/offline and 'perf top' that, if I offline most of cores before 'perf top', then online them during 'perf top' running, 'perf top' dooesn't report new CPUs. It still reports the CPUs which are online when 'perf top' starts consume 100% cycles. So if CPUs are online and offlined dynamically and there are many CPUs, user of 'perf top' may get confusion result if he or she doesn't noticed that 'perf top' doesn't listed all cores they have.
Here is how I did this:
# for i in `seq 2 7` ; do echo 0 > /sys/devices/system/cpu/cpu$i/online ; done # perf top -s cpu,socket
The result is something like:
Samples: 28K of event 'cycles', Event count (approx.): 23640606383 Overhead Socket CPU
67.14% 000 000 32.86% 000 001
Then online them:
# for i in `seq 2 7` ; do echo 1 > /sys/devices/system/cpu/cpu$i/online ; done
After a while, 'perf top' still reports two CPUs.
Samples: 400K of event 'cycles', Event count (approx.): 38728257939 Overhead Socket CPU
51.02% 000 001 48.98% 000 000
And another 'perf top' report correct result:
Samples: 28K of event 'cycles', Event count (approx.): 24741565854 Overhead Socket CPU
27.26% 000 005 21.07% 000 002 13.07% 000 001 12.69% 000 000 8.07% 000 006 6.75% 000 007 5.64% 000 004 5.45% 000 003
However, It is relatively a rare case. I don't think we have to fix it in this patchset.
Thank you.
Quoted 37 lines · Arnaldo Carvalho de Melo
Hi,
Please take a look at these changes to fix the problems reported by
Wang Nan wrt accesses to thecpu_topology_mapinformation.The fixes are present on these following two csets:
perf event: Use
machine->envto find the cpu -> socket mapping perf report: Do not blindly use env->cpu[al.cpu].socket_idThe rest are fixes made while working on this, infrastructure to enable
the fixes, reverts for things that ended up not being necessary and some cleanups.It is available at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gitperf/envPlease let me know if I can have your Acked-by, Tested-by or
Reviewed-by.- Arnaldo
Arnaldo Carvalho de Melo (13):
perf env: Moveperf_envout ofheader.handsession.cinto separate object perf env: Rename some leftovers from rename toperf_env
perf env: Adoptperf_header__set_cmdline
perf env: Introduceread_cpu_topology_map()method
perf sort: Set flag stating if the "socket" key is being used perf top: Cache the cpu topology info when "-s socket" is used perf hists browser: Fixup the "cpu" column width calculation perf machine: Add pointer to sample's environment
perf event: Usemachine->envto find the cpu -> socket mapping perf report: Do not blindly use env->cpu[al.cpu].socket_id Revert "perf evsel: Add a backpointer to the evlist a evsel is in" perf evsel: Remove forward declaration of 'structperf_evlist' Revert "perf evlist: Add backpointer forperf_envto evlist"
Arnaldo Carvalho de Melo
maintainerEm Fri, Sep 11, 2015 at 08:20:54PM +0800, Wangnan (F) escreveu:
Quoted 1 line
I have tested patch 1 to 10. They looks good to me except patch 4/13. Please
Ok, I'll take that as a Tested-by: you for 1-10 with 4/13 having the checks added, ok?
Quoted 1 line
see my email in that thread.
I add those checks.
Quoted 4 lines
However, during the testing I found a limitation related to cpu online/offline and 'perf top' that, if I offline most of cores before 'perf top', then online them during 'perf top' running, 'perf top' dooesn't report new CPUs. It still reports the CPUs which are online
<SNIP>
Quoted 2 lines
However, It is relatively a rare case. I don't think we have to fix it in this patchset.
Yup, unrelated to this patchset. But we need to seamlessly support that situation, even telling the user that a CPU went offline/online.
- Arnaldo
Arnaldo Carvalho de Melo
maintainerEm Fri, Sep 11, 2015 at 10:03:39AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Fri, Sep 11, 2015 at 08:20:54PM +0800, Wangnan (F) escreveu:
Quoted 1 line
I have tested patch 1 to 10. They looks good to me except patch 4/13. Please
Ok, I'll take that as a Tested-by: you for 1-10 with 4/13 having the checks added, ok?
Quoted 1 line
see my email in that thread.
I add those checks.
Ok, below is the diff for adding the checks. The get_{core,socket}_id functions should be moved to tools/lib/api/cpu.[ch], using the same interface as cpu__get_max_freq(&value), using the int return value to propagate the precise error, etc. Will do it in a follow up patch.
- Arnaldo
tools/perf/util/env.c +11 -4
@@ -60,7 +60,7 @@ out_enomem:int perf_env__read_cpu_topology_map (struct perf_env *env) { -int cpu, nr_cpus; +int cpu, nr_cpus, err;if (env->cpu !=NULL )return 0 ;
@@ -77,10 +77,17 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)return -ENOMEM ;for (cpu =0 ; cpu < nr_cpus; ++cpu) { - env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); - env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + err = env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); +if (err <0 ) + goto out_free; + err = env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); +if (err <0 ) + goto out_free; } - env->nr_cpus_avail = nr_cpus;return 0 ; + +out_free: +zfree (&env->cpu); +return err; }
Arnaldo Carvalho de Melo
maintainerEm Fri, Sep 11, 2015 at 10:29:37AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 7 lines
Em Fri, Sep 11, 2015 at 10:03:39AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 5 lines
Em Fri, Sep 11, 2015 at 08:20:54PM +0800, Wangnan (F) escreveu:
Quoted 1 line
I have tested patch 1 to 10. They looks good to me except patch 4/13. Please
Ok, I'll take that as a Tested-by: you for 1-10 with 4/13 having the checks added, ok?
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
see my email in that thread.
I add those checks.
Ok, below is the diff for adding the checks. The get_{core,socket}_id functions should be moved to tools/lib/api/cpu.[ch], using the same interface as
cpu__get_max_freq(&value), using the int return value to propagate the precise error, etc. Will do it in a follow up patch.
Humm, but then, what happens if a CPU is offline? I'm checking it now...
- Arnaldo
Quoted 36 lines
- Arnaldo
tools/perf/util/env.c +11
-4@@ -60,7 +60,7 @@ out_enomem:int perf_env__read_cpu_topology_map (struct perf_env *env) { -int cpu, nr_cpus; +int cpu, nr_cpus, err;if (env->cpu !=NULL )return 0 ;@@ -77,10 +77,17 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)return -ENOMEM ;for (cpu =0 ; cpu < nr_cpus; ++cpu) { - env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); - env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + err = env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); +if (err <0 ) + goto out_free; + err = env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); +if (err <0 ) + goto out_free; } - env->nr_cpus_avail = nr_cpus;return 0 ; + +out_free: +zfree (&env->cpu); +return err; }
Arnaldo Carvalho de Melo
maintainerEm Fri, Sep 11, 2015 at 10:30:52AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 10 lines
Em Fri, Sep 11, 2015 at 10:29:37AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 9 lines
Em Fri, Sep 11, 2015 at 10:03:39AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 7 lines
Em Fri, Sep 11, 2015 at 08:20:54PM +0800, Wangnan (F) escreveu:
Quoted 1 line
I have tested patch 1 to 10. They looks good to me except patch 4/13. Please
Ok, I'll take that as a Tested-by: you for 1-10 with 4/13 having the checks added, ok?
Quoted 1 line
see my email in that thread.
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
I add those checks.
Ok, below is the diff for adding the checks. The get_{core,socket}_id functions should be moved to tools/lib/api/cpu.[ch], using the same interface as
cpu__get_max_freq(&value), using the int return value to propagate the precise error, etc. Will do it in a follow up patch.Humm, but then, what happens if a CPU is offline? I'm checking it now...
# cat /sys/devices/system/cpu/cpu3/topology/core_id 3 # cat /sys/devices/system/cpu/cpu3/topology/physical_package_id 0 # echo 0 > /sys/devices/system/cpu/cpu3/online # cat /sys/devices/system/cpu/cpu3/topology/physical_package_id cat: /sys/devices/system/cpu/cpu3/topology/physical_package_id: No such file or directory # cat /sys/devices/system/cpu/cpu3/topology/core_id cat: /sys/devices/system/cpu/cpu3/topology/core_id: No such file or directory #
So we shouldn't check the result, right? We could further validate it by checking:
# cat /sys/devices/system/cpu/cpu3/online 0 #
But assuming that not being able to access it means it is offline looks almost reasonable, if not strictly correct, so I'm removing the tests and will revisit this when I move those functions to tools/lib/api/cpu.[ch].
- Arnaldo
Quoted 34 lines
Quoted 34 lines
tools/perf/util/env.c +11
-4@@ -60,7 +60,7 @@ out_enomem:int perf_env__read_cpu_topology_map (struct perf_env *env) { -int cpu, nr_cpus; +int cpu, nr_cpus, err;if (env->cpu !=NULL )return 0 ;@@ -77,10 +77,17 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)return -ENOMEM ;for (cpu =0 ; cpu < nr_cpus; ++cpu) { - env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); - env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + err = env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); +if (err <0 ) + goto out_free; + err = env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); +if (err <0 ) + goto out_free; } - env->nr_cpus_avail = nr_cpus;return 0 ; + +out_free: +zfree (&env->cpu); +return err; }
Quoted 32 lines · Arnaldo Carvalho de Melo
Em Fri, Sep 11, 2015 at 10:30:52AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 7 lines
Em Fri, Sep 11, 2015 at 10:29:37AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 6 lines
Em Fri, Sep 11, 2015 at 10:03:39AM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 4 lines
Em Fri, Sep 11, 2015 at 08:20:54PM +0800, Wangnan (F) escreveu:
Quoted 1 line
I have tested patch 1 to 10. They looks good to me except patch 4/13. Please
Ok, I'll take that as a Tested-by: you for 1-10 with 4/13 having the checks added, ok?
Quoted 8 lines
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
see my email in that thread.
I add those checks.
Ok, below is the diff for adding the checks. The get_{core,socket}_id functions should be moved to tools/lib/api/cpu.[ch], using the same interface as
cpu__get_max_freq(&value), using the int return value to propagate the precise error, etc. Will do it in a follow up patch.Humm, but then, what happens if a CPU is offline? I'm checking it now...
# cat /sys/devices/system/cpu/cpu3/topology/core_id 3 # cat /sys/devices/system/cpu/cpu3/topology/physical_package_id 0 # echo 0 > /sys/devices/system/cpu/cpu3/online # cat /sys/devices/system/cpu/cpu3/topology/physical_package_id cat: /sys/devices/system/cpu/cpu3/topology/physical_package_id: No such file or directory # cat /sys/devices/system/cpu/cpu3/topology/core_id cat: /sys/devices/system/cpu/cpu3/topology/core_id: No such file or directory #So we shouldn't check the result, right? We could further validate it by checking:
Quoted 8 lines
# cat /sys/devices/system/cpu/cpu3/online 0 #But assuming that not being able to access it means it is offline looks almost reasonable, if not strictly correct, so I'm removing the tests and will revisit this when I move those functions to tools/lib/api/cpu.[ch].
I highly suspect that setting 'online' to 0 is not the only reason of the removal of topology directory. Testing the existance of the two files should be better.
Thank you.
Quoted 36 lines
- Arnaldo
Quoted 34 lines
Quoted 34 lines
tools/perf/util/env.c +11
-4@@ -60,7 +60,7 @@ out_enomem:int perf_env__read_cpu_topology_map (struct perf_env *env) { -int cpu, nr_cpus; +int cpu, nr_cpus, err;if (env->cpu !=NULL )return 0 ;@@ -77,10 +77,17 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)return -ENOMEM ;for (cpu =0 ; cpu < nr_cpus; ++cpu) { - env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); - env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); + err = env->cpu[cpu].core_id =cpu_map__get_core_id (cpu); +if (err <0 ) + goto out_free; + err = env->cpu[cpu].socket_id =cpu_map__get_socket_id (cpu); +if (err <0 ) + goto out_free; } - env->nr_cpus_avail = nr_cpus;return 0 ; + +out_free: +zfree (&env->cpu); +return err; }
Wangnan (F)
Tested-byQuoted 4 lines · Arnaldo Carvalho de Melo
Em Fri, Sep 11, 2015 at 08:20:54PM +0800, Wangnan (F) escreveu:
Quoted 1 line
I have tested patch 1 to 10. They looks good to me except patch 4/13. Please
Ok, I'll take that as a Tested-by: you for 1-10 with 4/13 having the checks added, ok?
Sure.
Quoted 15 lines
Quoted 1 line
see my email in that thread.
I add those checks.
Quoted 4 lines
However, during the testing I found a limitation related to cpu online/offline and 'perf top' that, if I offline most of cores before 'perf top', then online them during 'perf top' running, 'perf top' dooesn't report new CPUs. It still reports the CPUs which are online
<SNIP>
Quoted 2 lines
However, It is relatively a rare case. I don't think we have to fix it in this patchset.
Yup, unrelated to this patchset. But we need to seamlessly support that situation, even telling the user that a CPU went offline/online.
- Arnaldo