perf tools: Assorted fixes
Jiri Olsa
reviewerv2 cover perf tools: Assorted fixes
hi,
sending assorted general fixes that queued
up in my other branches.
v2 changes:
- rebased, some patches already taken
- multiple fixes suggested by Arnaldo
- new patch that frees memory_nodes in perf_env__exit
Also available in here:
https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
perf/fixes
thanks,
jirka
---
Jiri Olsa (9):
perf tools: Free memory nodes data
perf tools: Add mem2node object
perf tests: Add mem2node object test
perf c2c record: Record physical addresses in samples perf c2c report: Make calc_width work with struct c2c_hist_entry perf c2c report: Call calc_width only for displayed entries perf c2c report: Display node for cacheline address perf c2c report: Add span header over cacheline data perf c2c report: Add cacheline address count column
tools/perf/Documentation/perf-c2c.txt | 2 +- tools/perf/builtin-c2c.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 +++ tools/perf/tests/mem2node.c | 75 ++++++++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + tools/perf/util/Build | 1 + tools/perf/util/env.c | 4 +++ tools/perf/util/mem2node.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/mem2node.h | 19 ++++++++++ 10 files changed, 446 insertions(+), 18 deletions(-) create mode 100644 tools/perf/tests/mem2node.c create mode 100644 tools/perf/util/mem2node.c create mode 100644 tools/perf/util/mem2node.h
Jiri Olsa
reviewerPATCH v2 1/9 perf tools: Free memory nodes data
Forgot to free env's memory nodes, adding
needed code to perf_env__exit.
--- tools/perf/util/env.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/env.c +4 -0
@@ -32,6 +32,10 @@ void perf_env__exit(struct perf_env *env)for (i =0 ; i < env->caches_cnt; i++)cpu_cache_level__free (&env->caches[i]);zfree (&env->caches); + +for (i =0 ; i < env->nr_memory_nodes; i++) +free (env->memory_nodes[i].set); +zfree (&env->memory_nodes); }int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[])
Signature · 1 line
2.13.6
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf env: Free memory nodes data
perf env: Free memory nodes data
Commit-ID: e725920cdb1c79fdc71f2f164f59be8c411cad68 Gitweb: https://git.kernel.org/tip/e725920cdb1c79fdc71f2f164f59be8c411cad68 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:34 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:52:09 -0300
perf env: Free memory nodes data
Forgot to free env's memory nodes, adding needed code to perf_env__exit.
--- tools/perf/util/env.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/env.c +4 -0
@@ -32,6 +32,10 @@ void perf_env__exit(struct perf_env *env)for (i =0 ; i < env->caches_cnt; i++)cpu_cache_level__free (&env->caches[i]);zfree (&env->caches); + +for (i =0 ; i < env->nr_memory_nodes; i++) +free (env->memory_nodes[i].set); +zfree (&env->memory_nodes); }int perf_env__set_cmdline (struct perf_env *env,int argc,const char *argv[])
Jiri Olsa
reviewerPATCH v2 2/9 perf tools: Add mem2node object
In reply to Jiri OlsaAdding mem2node object to allow the easy lookup
of the node for the physical address.
It has following interface:
int mem2node__init(struct mem2node *map, struct perf_env *env); void mem2node__exit(struct mem2node *map); int mem2node__node(struct mem2node *map, u64 addr);
The mem2node__init initialize object from the perf data file MEM_TOPOLOGY feature data. Following calls to mem2node__node will return node number for given physical address. The mem2node__exit function frees the object.
--- tools/perf/util/Build | 1 + tools/perf/util/mem2node.c | 134 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/mem2node.h | 19 +++++++ 3 files changed, 154 insertions(+) create mode 100644 tools/perf/util/mem2node.c create mode 100644 tools/perf/util/mem2node.h
tools/perf/util/Build +1 -0
@@ -106,6 +106,7 @@ libperf-y += units.o libperf-y += time-utils.o libperf-y += expr-bison.o libperf-y += branch.o +libperf-y += mem2node.o libperf-$(CONFIG_LIBBPF) += bpf-loader.o libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
tools/perf/util/mem2node.c new file +134 -0
134 lines not on this page · raw message
tools/perf/util/mem2node.h new file +19 -0
@@ -0,0 +1,19 @@ +#ifndef __MEM2NODE_H +#define __MEM2NODE_H + +#include <linux/rbtree.h> +#include "env.h" + +struct phys_entry ; + +struct mem2node { +struct rb_root root; +struct phys_entry *entries; +int cnt; +}; + +int mem2node__init (struct mem2node *map,struct perf_env *env); +void mem2node__exit (struct mem2node *map); +int mem2node__node (struct mem2node *map,u64 addr); + +#endif /* __MEM2NODE_H */
Signature · 1 line
2.13.6
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf tools: Add mem2node object
perf tools: Add mem2node object
Commit-ID: 4acf6142de3fbc4fc9cc8da0a1aec073f05b724f Gitweb: https://git.kernel.org/tip/4acf6142de3fbc4fc9cc8da0a1aec073f05b724f Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:35 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:52:37 -0300
perf tools: Add mem2node object
Adding mem2node object to allow the easy lookup of the node for the physical address.
It has following interface:
int mem2node__init(struct mem2node *map, struct perf_env *env); void mem2node__exit(struct mem2node *map); int mem2node__node(struct mem2node *map, u64 addr);
The mem2node__toolsinit initialize object from the perf data file MEM_TOPOLOGY feature data. Following calls to mem2node__node will return node number for given physical address. The mem2node__exit function frees the object.
--- tools/perf/util/Build | 1 + tools/perf/util/mem2node.c | 134 +++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/mem2node.h | 19 +++++++ 3 files changed, 154 insertions(+)
tools/perf/util/Build +1 -0
@@ -106,6 +106,7 @@ libperf-y += units.o libperf-y += time-utils.o libperf-y += expr-bison.o libperf-y += branch.o +libperf-y += mem2node.o libperf-$(CONFIG_LIBBPF) += bpf-loader.o libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
tools/perf/util/mem2node.c new file +134 -0
134 lines not on this page · raw message
tools/perf/util/mem2node.h new file +19 -0
@@ -0,0 +1,19 @@ +#ifndef __MEM2NODE_H +#define __MEM2NODE_H + +#include <linux/rbtree.h> +#include "env.h" + +struct phys_entry ; + +struct mem2node { +struct rb_root root; +struct phys_entry *entries; +int cnt; +}; + +int mem2node__init (struct mem2node *map,struct perf_env *env); +void mem2node__exit (struct mem2node *map); +int mem2node__node (struct mem2node *map,u64 addr); + +#endif /* __MEM2NODE_H */
Jiri Olsa
reviewerPATCH v2 3/9 perf tests: Add mem2node object test
In reply to Jiri OlsaAdding mem2node object automated test.
The test prepares few artificial node - memory maps and verifies the mem2node object returns proper node values to given addresses.
--- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 +++ tools/perf/tests/mem2node.c | 75 +++++++++++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 81 insertions(+) create mode 100644 tools/perf/tests/mem2node.c
tools/perf/tests/Build +1 -0
@@ -47,6 +47,7 @@ perf-y += bitmap.o perf-y += perf-hooks.o perf-y += clang.o perf-y += unit_number__scnprintf.o +perf-y += mem2node.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir)
tools/perf/tests/builtin-test.c +4 -0
@@ -271,6 +271,10 @@ static struct test generic_tests[] = { .func = test__unit_number__scnprint, }, { + .desc = "mem2node", + .func = test__mem2node, + }, + { .func = NULL, }, };
tools/perf/tests/mem2node.c new file +75 -0
75 lines not on this page · raw message
tools/perf/tests/tests.h +1 -0
@@ -102,6 +102,7 @@ int test__clang(struct test *test, int subtest);const char *test__clang_subtest_get_desc (int subtest);int test__clang_subtest_get_nr (void );int test__unit_number__scnprint (struct test *test,int subtest); +int test__mem2node (struct test *t,int subtest);bool test__bp_signal_is_supported (void );
Signature · 1 line
2.13.6
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf tests: Add mem2node object test
perf tests: Add mem2node object test
Commit-ID: 8185850ad603acfc66f5b3d284955809dffa5d2c Gitweb: https://git.kernel.org/tip/8185850ad603acfc66f5b3d284955809dffa5d2c Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:36 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:52:48 -0300
perf tests: Add mem2node object test
Adding mem2node object automated test.
The test prepares few artificial nodes - memory maps and verifies the mem2node object returns proper node values to given addresses.
--- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 +++ tools/perf/tests/mem2node.c | 75 +++++++++++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 81 insertions(+)
tools/perf/tests/Build +1 -0
@@ -48,6 +48,7 @@ perf-y += bitmap.o perf-y += perf-hooks.o perf-y += clang.o perf-y += unit_number__scnprintf.o +perf-y += mem2node.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir)
tools/perf/tests/builtin-test.c +4 -0
@@ -274,6 +274,10 @@ static struct test generic_tests[] = { .desc = "unit_number__scnprintf", .func = test__unit_number__scnprint, }, + { + .desc = "mem2node", + .func = test__mem2node, + }, { .func = NULL, },
tools/perf/tests/mem2node.c new file +75 -0
75 lines not on this page · raw message
tools/perf/tests/tests.h +1 -0
@@ -103,6 +103,7 @@ int test__clang(struct test *test, int subtest);const char *test__clang_subtest_get_desc (int subtest);int test__clang_subtest_get_nr (void );int test__unit_number__scnprint (struct test *test,int subtest); +int test__mem2node (struct test *t,int subtest);bool test__bp_signal_is_supported (void );
Jiri Olsa
reviewerPATCH v2 4/9 perf c2c record: Record physical addresses in samples
In reply to Jiri OlsaWe are going to display NUMA node information in following patches. For this we need to have physical address data in the sample.
Adding --phys-data as a default option for perf c2c record.
--- tools/perf/Documentation/perf-c2c.txt | 2 +- tools/perf/builtin-c2c.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-c2c.txt +1 -1
@@ -116,7 +116,7 @@ and calls standard perf record command. Following perf record options are configured by default: (check perf record man page for details) - -W,-d,--sample-cpu + -W,-d,--phys-data,--sample-cpu Unless specified otherwise with '-e' option, following events are monitored by default:
tools/perf/builtin-c2c.c +2 -1
@@ -2704,7 +2704,7 @@ static int perf_c2c__record(int argc, const char **argv) argc =parse_options (argc, argv, options, record_mem_usage,PARSE_OPT_KEEP_UNKNOWN ); - rec_argc = argc +10 ;/* max number of arguments */ + rec_argc = argc +11 ;/* max number of arguments */ rec_argv =calloc (rec_argc +1 ,sizeof (char *));if (!rec_argv)return -1 ;
@@ -2720,6 +2720,7 @@ static int perf_c2c__record(int argc, const char **argv) rec_argv[i++] ="-W" ; rec_argv[i++] ="-d" ; + rec_argv[i++] ="--phys-data" ; rec_argv[i++] ="--sample-cpu" ;for (j =0 ; j <PERF_MEM_EVENTS__MAX ; j++) {
Signature · 1 line
2.13.6
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf c2c record: Record physical addresses in samples
perf c2c record: Record physical addresses in samples
Commit-ID: 8fab7843a15078814764e01c303d175c92b500c1 Gitweb: https://git.kernel.org/tip/8fab7843a15078814764e01c303d175c92b500c1 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:37 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:52:57 -0300
perf c2c record: Record physical addresses in samples
We are going to display NUMA node information in following patches. For this we need to have physical address data in the sample.
Adding --phys-data as a default option for perf c2c record.
--- tools/perf/Documentation/perf-c2c.txt | 2 +- tools/perf/builtin-c2c.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-c2c.txt +1 -1
@@ -116,7 +116,7 @@ and calls standard perf record command. Following perf record options are configured by default: (check perf record man page for details) - -W,-d,--sample-cpu + -W,-d,--phys-data,--sample-cpu Unless specified otherwise with '-e' option, following events are monitored by default:
tools/perf/builtin-c2c.c +2 -1
@@ -2704,7 +2704,7 @@ static int perf_c2c__record(int argc, const char **argv) argc =parse_options (argc, argv, options, record_mem_usage,PARSE_OPT_KEEP_UNKNOWN ); - rec_argc = argc +10 ;/* max number of arguments */ + rec_argc = argc +11 ;/* max number of arguments */ rec_argv =calloc (rec_argc +1 ,sizeof (char *));if (!rec_argv)return -1 ;
@@ -2720,6 +2720,7 @@ static int perf_c2c__record(int argc, const char **argv) rec_argv[i++] ="-W" ; rec_argv[i++] ="-d" ; + rec_argv[i++] ="--phys-data" ; rec_argv[i++] ="--sample-cpu" ;for (j =0 ; j <PERF_MEM_EVENTS__MAX ; j++) {
Jiri Olsa
reviewerPATCH v2 5/9 perf c2c report: Make calc_width work with struct c2c_hist_entry
In reply to Jiri OlsaWe are going to calculate column width based on the struct c2c_hist_entry data, so making calc_width to work with struct c2c_hist_entry.
--- tools/perf/builtin-c2c.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
tools/perf/builtin-c2c.c +9 -5
@@ -1839,20 +1839,24 @@ static inline int valid_hitm_or_store(struct hist_entry *he)return has_hitm || c2c_he->stats.store; } -static void calc_width (struct hist_entry *he) +static void calc_width (struct c2c_hist_entry *c2c_he) {struct c2c_hists *c2c_hists; - c2c_hists = container_of(he->hists, struct c2c_hists, hists); -hists__calc_col_len (&c2c_hists->hists, he); + c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists); +hists__calc_col_len (&c2c_hists->hists, &c2c_he->he); }static int filter_cb (struct hist_entry *he) { +struct c2c_hist_entry *c2c_he; + + c2c_he = container_of(he, struct c2c_hist_entry, he); +if (c2c.show_src && !he->srcline) he->srcline =hist_entry__get_srcline (he); -calc_width (he); +calc_width (c2c_he);if (!valid_hitm_or_store (he)) he->filtered =HIST_FILTER__C2C ;
@@ -1869,7 +1873,7 @@ static int resort_cl_cb(struct hist_entry *he) c2c_he = container_of(he, struct c2c_hist_entry, he); c2c_hists = c2c_he->hists; -calc_width (he); +calc_width (c2c_he);if (display && c2c_hists) {static unsigned int idx;
Signature · 1 line
2.13.6
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf c2c report: Make calc_width work with struct c2c_hist_entry
perf c2c report: Make calc_width work with struct c2c_hist_entry
Commit-ID: 3773138828b38f3f1364ef318cd876b16182388a Gitweb: https://git.kernel.org/tip/3773138828b38f3f1364ef318cd876b16182388a Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:38 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:53:05 -0300
perf c2c report: Make calc_width work with struct c2c_hist_entry
We are going to calculate tje column width based on the struct c2c_hist_entry data, so making calc_width to work with struct c2c_hist_entry.
--- tools/perf/builtin-c2c.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
tools/perf/builtin-c2c.c +9 -5
@@ -1839,20 +1839,24 @@ static inline int valid_hitm_or_store(struct hist_entry *he)return has_hitm || c2c_he->stats.store; } -static void calc_width (struct hist_entry *he) +static void calc_width (struct c2c_hist_entry *c2c_he) {struct c2c_hists *c2c_hists; - c2c_hists = container_of(he->hists, struct c2c_hists, hists); -hists__calc_col_len (&c2c_hists->hists, he); + c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists); +hists__calc_col_len (&c2c_hists->hists, &c2c_he->he); }static int filter_cb (struct hist_entry *he) { +struct c2c_hist_entry *c2c_he; + + c2c_he = container_of(he, struct c2c_hist_entry, he); +if (c2c.show_src && !he->srcline) he->srcline =hist_entry__get_srcline (he); -calc_width (he); +calc_width (c2c_he);if (!valid_hitm_or_store (he)) he->filtered =HIST_FILTER__C2C ;
@@ -1869,7 +1873,7 @@ static int resort_cl_cb(struct hist_entry *he) c2c_he = container_of(he, struct c2c_hist_entry, he); c2c_hists = c2c_he->hists; -calc_width (he); +calc_width (c2c_he);if (display && c2c_hists) {static unsigned int idx;
Jiri Olsa
reviewerPATCH v2 6/9 perf c2c report: Call calc_width only for displayed entries
In reply to Jiri OlsaThere's no need to calculate column width on entries that are not going to be displayed.
--- tools/perf/builtin-c2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
tools/perf/builtin-c2c.c +1 -2
@@ -1873,12 +1873,11 @@ static int resort_cl_cb(struct hist_entry *he) c2c_he = container_of(he, struct c2c_hist_entry, he); c2c_hists = c2c_he->hists; -calc_width (c2c_he); -if (display && c2c_hists) {static unsigned int idx; c2c_he->cacheline_idx = idx++; +calc_width (c2c_he);c2c_hists__reinit (c2c_hists, c2c.cl_output, c2c.cl_resort);
Signature · 1 line
2.13.6
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf c2c report: Call calc_width() only for displayed entries
perf c2c report: Call calc_width() only for displayed entries
Commit-ID: bc229c21f2c79ef0f7b30d3a2fce8c2886ffa6c7 Gitweb: https://git.kernel.org/tip/bc229c21f2c79ef0f7b30d3a2fce8c2886ffa6c7 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:39 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:53:13 -0300
perf c2c report: Call calc_width() only for displayed entries
There's no need to calculate column widths for entries that are not going to be displayed.
--- tools/perf/builtin-c2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
tools/perf/builtin-c2c.c +1 -2
@@ -1873,12 +1873,11 @@ static int resort_cl_cb(struct hist_entry *he) c2c_he = container_of(he, struct c2c_hist_entry, he); c2c_hists = c2c_he->hists; -calc_width (c2c_he); -if (display && c2c_hists) {static unsigned int idx; c2c_he->cacheline_idx = idx++; +calc_width (c2c_he);c2c_hists__reinit (c2c_hists, c2c.cl_output, c2c.cl_resort);
Jiri Olsa
reviewerPATCH v2 7/9 perf c2c report: Display node for cacheline address
In reply to Jiri OlsaAdding the NUMA node info for the data cacheline. Adding the new column to both Shared Data Cache Line Table and Shared Cache Line Distribution Pareto.
Note the new 'Node' column next to the 'Cacheline'.
$ perf c2c report --stdio
=================================================
Shared Data Cache Line Table
=================================================
#
# Total Tot ----- LLC Load Hitm -----
# Index Cacheline Node records Hitm Total Lcl Rmt
# ..... .................. .... ....... ....... ....... ....... .......
#
0 0x7f0830100000 0 84 10.53% 8 8 0
1 0xffff922a93154200 0 3 2.63% 2 2 0
2 0xffff922a93154500 0 4 2.63% 2 2 0
...Note the new 'Node' column next to the 'Offset'.
=================================================
Shared Cache Line Distribution Pareto
=================================================
#
# ----- HITM ----- -- Store Refs -- Data address
# Num Rmt Lcl L1 Hit L1 Miss Offset Node Pid
# ..... ....... ....... ....... ....... .................. .... .......
#
-------------------------------------------------------------
0 0 8 32 2 0x7f0830100000
-------------------------------------------------------------
0.00% 75.00% 21.88% 0.00% 0x18 0 1791
0.00% 12.50% 37.50% 0.00% 0x18 0 1791
0.00% 0.00% 34.38% 0.00% 0x18 0 1791Using the mem2node object to get the NUMA node data.
--- tools/perf/builtin-c2c.c | 119 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 5 deletions(-)
tools/perf/builtin-c2c.c +114 -5
@@ -32,6 +32,7 @@#include "evsel.h" #include "ui/browsers/hists.h" #include "thread.h" +#include "mem2node.h" struct c2c_hists {struct hists hists;
@@ -49,6 +50,7 @@ struct c2c_hist_entry {struct c2c_hists *hists;struct c2c_stats stats;unsigned long *cpuset; +unsigned long *nodeset;struct c2c_stats *node_stats;unsigned int cacheline_idx;
@@ -59,6 +61,11 @@ struct c2c_hist_entry {* because of its callchain dynamic entry */ struct hist_entry he; + +unsigned long paddr; +unsigned long paddr_cnt; +bool paddr_zero; +char *nodestr; };static char const *coalesce_default ="pid,iaddr" ;
@@ -66,6 +73,7 @@ static char const *coalesce_default = "pid,iaddr";struct perf_c2c {struct perf_tool tool;struct c2c_hists hists; +struct mem2node mem2node;unsigned long **nodes;int nodes_cnt;
@@ -123,6 +131,10 @@ static void *c2c_he_zalloc(size_t size)if (!c2c_he->cpuset)return NULL ; + c2c_he->nodeset =bitmap_alloc (c2c.nodes_cnt); +if (!c2c_he->nodeset) +return NULL ; + c2c_he->node_stats =zalloc (c2c.nodes_cnt *sizeof (*c2c_he->node_stats));if (!c2c_he->node_stats)return NULL ;
@@ -145,6 +157,8 @@ static void c2c_he_free(void *he) }free (c2c_he->cpuset); +free (c2c_he->nodeset); +free (c2c_he->nodestr);free (c2c_he->node_stats);free (c2c_he); }
@@ -194,6 +208,28 @@ static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,set_bit (sample->cpu, c2c_he->cpuset); } +static void c2c_he__set_node (struct c2c_hist_entry *c2c_he, +struct perf_sample *sample) +{ +int node; + +if (!sample->phys_addr) { + c2c_he->paddr_zero = true; +return ; + } + + node =mem2node__node (&c2c.mem2node, sample->phys_addr); +if (WARN_ONCE (node <0 ,"WARNING: failed to find node\n" )) +return ; + +set_bit (node, c2c_he->nodeset); + +if (c2c_he->paddr != sample->phys_addr) { + c2c_he->paddr_cnt++; + c2c_he->paddr = sample->phys_addr; + } +} +static void compute_stats (struct c2c_hist_entry *c2c_he,struct c2c_stats *stats,u64 weight)
@@ -257,6 +293,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,c2c_add_stats (&c2c_hists->stats, &stats);c2c_he__set_cpu (c2c_he, sample); +c2c_he__set_node (c2c_he, sample);hists__inc_nr_samples (&c2c_hists->hists, he->filtered); ret =hist_entry__append_callchain (he, sample);
@@ -293,6 +330,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,compute_stats (c2c_he, &stats, sample->weight);c2c_he__set_cpu (c2c_he, sample); +c2c_he__set_node (c2c_he, sample);hists__inc_nr_samples (&c2c_hists->hists, he->filtered); ret =hist_entry__append_callchain (he, sample);
@@ -455,6 +493,20 @@ static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,return scnprintf (hpp->buf, hpp->size,"%*s" , width,HEX_STR (buf, addr)); } +static int +dcacheline_node_entry (struct perf_hpp_fmt *fmt,struct perf_hpp *hpp, +struct hist_entry *he) +{ +struct c2c_hist_entry *c2c_he; +int width =c2c_width (fmt, hpp, he->hists); + + c2c_he = container_of(he, struct c2c_hist_entry, he); +if (WARN_ON_ONCE (!c2c_he->nodestr)) +return 0 ; + +return scnprintf (hpp->buf, hpp->size,"%*s" , width, c2c_he->nodestr); +} +static int offset_entry (struct perf_hpp_fmt *fmt,struct perf_hpp *hpp,struct hist_entry *he) {
@@ -1207,6 +1259,14 @@ static struct c2c_dimension dim_dcacheline = { .width = 18, }; +static struct c2c_dimension dim_dcacheline_node = { + .header =HEADER_LOW ("Node" ), + .name ="dcacheline_node" , + .cmp = empty_cmp, + .entry = dcacheline_node_entry, + .width =4 , +}; +static struct c2c_header header_offset_tui =HEADER_LOW ("Off" );static struct c2c_dimension dim_offset = {
@@ -1217,6 +1277,14 @@ static struct c2c_dimension dim_offset = { .width = 18, }; +static struct c2c_dimension dim_offset_node = { + .header =HEADER_LOW ("Node" ), + .name ="offset_node" , + .cmp = empty_cmp, + .entry = dcacheline_node_entry, + .width =4 , +}; +static struct c2c_dimension dim_iaddr = { .header =HEADER_LOW ("Code address" ), .name ="iaddr" ,
@@ -1536,7 +1604,9 @@ static struct c2c_dimension dim_dcacheline_num_empty = {static struct c2c_dimension *dimensions[] = { &dim_dcacheline, + &dim_dcacheline_node, &dim_offset, + &dim_offset_node, &dim_iaddr, &dim_tot_hitm, &dim_lcl_hitm,
@@ -1839,12 +1909,44 @@ static inline int valid_hitm_or_store(struct hist_entry *he)return has_hitm || c2c_he->stats.store; } +static void set_node_width (struct c2c_hist_entry *c2c_he,int len) +{ +struct c2c_dimension *dim; + + dim = &c2c.hists == c2c_he->hists ? + &dim_dcacheline_node : &dim_offset_node; + +if (len > dim->width) + dim->width = len; +} + +static int set_nodestr (struct c2c_hist_entry *c2c_he) +{ +char buf[30 ]; +int len; + +if (c2c_he->nodestr) +return 0 ; + +if (bitmap_weight (c2c_he->nodeset, c2c.nodes_cnt)) { + len =bitmap_scnprintf (c2c_he->nodeset, c2c.nodes_cnt, + buf,sizeof (buf)); + }else { + len =scnprintf (buf,sizeof (buf),"N/A" ); + } + +set_node_width (c2c_he, len); + c2c_he->nodestr =strdup (buf); +return c2c_he->nodestr ?0 : -ENOMEM ; +} +static void calc_width (struct c2c_hist_entry *c2c_he) {struct c2c_hists *c2c_hists; c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);hists__calc_col_len (&c2c_hists->hists, &c2c_he->he); +set_nodestr (c2c_he); }static int filter_cb (struct hist_entry *he)
@@ -2474,7 +2576,7 @@ static int build_cl_output(char *cl_sort, bool no_source)"percent_lcl_hitm," "percent_stores_l1hit," "percent_stores_l1miss," -"offset," , +"offset,offset_node," , add_pid ?"pid," :"" , add_tid ?"tid," :"" , add_iaddr ? "iaddr," : "",
@@ -2603,17 +2705,21 @@ static int perf_c2c__report(int argc, const char **argv) goto out; } - err =setup_callchain (session->evlist); + err =mem2node__init (&c2c.mem2node, &session->header.env);if (err) goto out_session; + err =setup_callchain (session->evlist); +if (err) + goto out_mem2node; +if (symbol__init (&session->header.env) <0 ) - goto out_session; + goto out_mem2node;/* No pipe support at the moment. */ if (perf_data__is_pipe (session->data)) {pr_debug ("No pipe support at the moment.\n" ); - goto out_session; + goto out_mem2node; }if (c2c.use_stdio)
@@ -2626,12 +2732,13 @@ static int perf_c2c__report(int argc, const char **argv) err =perf_session__process_events (session);if (err) {pr_err ("failed to process sample\n" ); - goto out_session; + goto out_mem2node; }c2c_hists__reinit (&c2c.hists,"cl_idx," "dcacheline," +"dcacheline_node," "tot_recs," "percent_hitm," "tot_hitm,lcl_hitm,rmt_hitm,"
@@ -2657,6 +2764,8 @@ static int perf_c2c__report(int argc, const char **argv)perf_c2c_display (session); +out_mem2node: +mem2node__exit (&c2c.mem2node); out_session:perf_session__delete (session); out:
Signature · 1 line
2.13.6
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf c2c report: Display node for cacheline address
perf c2c report: Display node for cacheline address
Commit-ID: 7f834c2e84bbcf94a1ed65a2ae648129e1901370 Gitweb: https://git.kernel.org/tip/7f834c2e84bbcf94a1ed65a2ae648129e1901370 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:40 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:53:23 -0300
perf c2c report: Display node for cacheline address
Adding the NUMA node info for the data cacheline. Adding the new column to both "Shared Data Cache Line Table" and "Shared Cache Line Distribution Pareto".
Note the new 'Node' column next to the 'Cacheline'.
$ perf c2c report --stdio
=================================================
Shared Data Cache Line Table
=================================================
#
# Total Tot ----- LLC Load Hitm -----
# Index Cacheline Node records Hitm Total Lcl Rmt
# ..... .................. .... ....... ....... ....... ....... .......
#
0 0x7f0830100000 0 84 10.53% 8 8 0
1 0xffff922a93154200 0 3 2.63% 2 2 0
2 0xffff922a93154500 0 4 2.63% 2 2 0
...Note the new 'Node' column next to the 'Offset'.
=================================================
Shared Cache Line Distribution Pareto
=================================================
#
# ----- HITM ----- -- Store Refs -- Data address
# Num Rmt Lcl L1 Hit L1 Miss Offset Node Pid
# ..... ....... ....... ....... ....... .................. .... .......
#
-------------------------------------------------------------
0 0 8 32 2 0x7f0830100000
-------------------------------------------------------------
0.00% 75.00% 21.88% 0.00% 0x18 0 1791
0.00% 12.50% 37.50% 0.00% 0x18 0 1791
0.00% 0.00% 34.38% 0.00% 0x18 0 1791Using the mem2node object to get the NUMA node data.
--- tools/perf/builtin-c2c.c | 119 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 5 deletions(-)
tools/perf/builtin-c2c.c +114 -5
@@ -32,6 +32,7 @@#include "evsel.h" #include "ui/browsers/hists.h" #include "thread.h" +#include "mem2node.h" struct c2c_hists {struct hists hists;
@@ -49,6 +50,7 @@ struct c2c_hist_entry {struct c2c_hists *hists;struct c2c_stats stats;unsigned long *cpuset; +unsigned long *nodeset;struct c2c_stats *node_stats;unsigned int cacheline_idx;
@@ -59,6 +61,11 @@ struct c2c_hist_entry {* because of its callchain dynamic entry */ struct hist_entry he; + +unsigned long paddr; +unsigned long paddr_cnt; +bool paddr_zero; +char *nodestr; };static char const *coalesce_default ="pid,iaddr" ;
@@ -66,6 +73,7 @@ static char const *coalesce_default = "pid,iaddr";struct perf_c2c {struct perf_tool tool;struct c2c_hists hists; +struct mem2node mem2node;unsigned long **nodes;int nodes_cnt;
@@ -123,6 +131,10 @@ static void *c2c_he_zalloc(size_t size)if (!c2c_he->cpuset)return NULL ; + c2c_he->nodeset =bitmap_alloc (c2c.nodes_cnt); +if (!c2c_he->nodeset) +return NULL ; + c2c_he->node_stats =zalloc (c2c.nodes_cnt *sizeof (*c2c_he->node_stats));if (!c2c_he->node_stats)return NULL ;
@@ -145,6 +157,8 @@ static void c2c_he_free(void *he) }free (c2c_he->cpuset); +free (c2c_he->nodeset); +free (c2c_he->nodestr);free (c2c_he->node_stats);free (c2c_he); }
@@ -194,6 +208,28 @@ static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,set_bit (sample->cpu, c2c_he->cpuset); } +static void c2c_he__set_node (struct c2c_hist_entry *c2c_he, +struct perf_sample *sample) +{ +int node; + +if (!sample->phys_addr) { + c2c_he->paddr_zero = true; +return ; + } + + node =mem2node__node (&c2c.mem2node, sample->phys_addr); +if (WARN_ONCE (node <0 ,"WARNING: failed to find node\n" )) +return ; + +set_bit (node, c2c_he->nodeset); + +if (c2c_he->paddr != sample->phys_addr) { + c2c_he->paddr_cnt++; + c2c_he->paddr = sample->phys_addr; + } +} +static void compute_stats (struct c2c_hist_entry *c2c_he,struct c2c_stats *stats,u64 weight)
@@ -257,6 +293,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,c2c_add_stats (&c2c_hists->stats, &stats);c2c_he__set_cpu (c2c_he, sample); +c2c_he__set_node (c2c_he, sample);hists__inc_nr_samples (&c2c_hists->hists, he->filtered); ret =hist_entry__append_callchain (he, sample);
@@ -293,6 +330,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,compute_stats (c2c_he, &stats, sample->weight);c2c_he__set_cpu (c2c_he, sample); +c2c_he__set_node (c2c_he, sample);hists__inc_nr_samples (&c2c_hists->hists, he->filtered); ret =hist_entry__append_callchain (he, sample);
@@ -455,6 +493,20 @@ static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,return scnprintf (hpp->buf, hpp->size,"%*s" , width,HEX_STR (buf, addr)); } +static int +dcacheline_node_entry (struct perf_hpp_fmt *fmt,struct perf_hpp *hpp, +struct hist_entry *he) +{ +struct c2c_hist_entry *c2c_he; +int width =c2c_width (fmt, hpp, he->hists); + + c2c_he = container_of(he, struct c2c_hist_entry, he); +if (WARN_ON_ONCE (!c2c_he->nodestr)) +return 0 ; + +return scnprintf (hpp->buf, hpp->size,"%*s" , width, c2c_he->nodestr); +} +static int offset_entry (struct perf_hpp_fmt *fmt,struct perf_hpp *hpp,struct hist_entry *he) {
@@ -1207,6 +1259,14 @@ static struct c2c_dimension dim_dcacheline = { .width = 18, }; +static struct c2c_dimension dim_dcacheline_node = { + .header =HEADER_LOW ("Node" ), + .name ="dcacheline_node" , + .cmp = empty_cmp, + .entry = dcacheline_node_entry, + .width =4 , +}; +static struct c2c_header header_offset_tui =HEADER_LOW ("Off" );static struct c2c_dimension dim_offset = {
@@ -1217,6 +1277,14 @@ static struct c2c_dimension dim_offset = { .width = 18, }; +static struct c2c_dimension dim_offset_node = { + .header =HEADER_LOW ("Node" ), + .name ="offset_node" , + .cmp = empty_cmp, + .entry = dcacheline_node_entry, + .width =4 , +}; +static struct c2c_dimension dim_iaddr = { .header =HEADER_LOW ("Code address" ), .name ="iaddr" ,
@@ -1536,7 +1604,9 @@ static struct c2c_dimension dim_dcacheline_num_empty = {static struct c2c_dimension *dimensions[] = { &dim_dcacheline, + &dim_dcacheline_node, &dim_offset, + &dim_offset_node, &dim_iaddr, &dim_tot_hitm, &dim_lcl_hitm,
@@ -1839,12 +1909,44 @@ static inline int valid_hitm_or_store(struct hist_entry *he)return has_hitm || c2c_he->stats.store; } +static void set_node_width (struct c2c_hist_entry *c2c_he,int len) +{ +struct c2c_dimension *dim; + + dim = &c2c.hists == c2c_he->hists ? + &dim_dcacheline_node : &dim_offset_node; + +if (len > dim->width) + dim->width = len; +} + +static int set_nodestr (struct c2c_hist_entry *c2c_he) +{ +char buf[30 ]; +int len; + +if (c2c_he->nodestr) +return 0 ; + +if (bitmap_weight (c2c_he->nodeset, c2c.nodes_cnt)) { + len =bitmap_scnprintf (c2c_he->nodeset, c2c.nodes_cnt, + buf,sizeof (buf)); + }else { + len =scnprintf (buf,sizeof (buf),"N/A" ); + } + +set_node_width (c2c_he, len); + c2c_he->nodestr =strdup (buf); +return c2c_he->nodestr ?0 : -ENOMEM ; +} +static void calc_width (struct c2c_hist_entry *c2c_he) {struct c2c_hists *c2c_hists; c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);hists__calc_col_len (&c2c_hists->hists, &c2c_he->he); +set_nodestr (c2c_he); }static int filter_cb (struct hist_entry *he)
@@ -2474,7 +2576,7 @@ static int build_cl_output(char *cl_sort, bool no_source)"percent_lcl_hitm," "percent_stores_l1hit," "percent_stores_l1miss," -"offset," , +"offset,offset_node," , add_pid ?"pid," :"" , add_tid ?"tid," :"" , add_iaddr ? "iaddr," : "",
@@ -2603,17 +2705,21 @@ static int perf_c2c__report(int argc, const char **argv) goto out; } - err =setup_callchain (session->evlist); + err =mem2node__init (&c2c.mem2node, &session->header.env);if (err) goto out_session; + err =setup_callchain (session->evlist); +if (err) + goto out_mem2node; +if (symbol__init (&session->header.env) <0 ) - goto out_session; + goto out_mem2node;/* No pipe support at the moment. */ if (perf_data__is_pipe (session->data)) {pr_debug ("No pipe support at the moment.\n" ); - goto out_session; + goto out_mem2node; }if (c2c.use_stdio)
@@ -2626,12 +2732,13 @@ static int perf_c2c__report(int argc, const char **argv) err =perf_session__process_events (session);if (err) {pr_err ("failed to process sample\n" ); - goto out_session; + goto out_mem2node; }c2c_hists__reinit (&c2c.hists,"cl_idx," "dcacheline," +"dcacheline_node," "tot_recs," "percent_hitm," "tot_hitm,lcl_hitm,rmt_hitm,"
@@ -2657,6 +2764,8 @@ static int perf_c2c__report(int argc, const char **argv)perf_c2c_display (session); +out_mem2node: +mem2node__exit (&c2c.mem2node); out_session:perf_session__delete (session); out:
Jiri Olsa
reviewerPATCH v2 8/9 perf c2c report: Add span header over cacheline data
In reply to Jiri OlsaForcing the NUMA node output to be grouped with the Cacheline column in both Shared Data Cache Line Table and Shared Cache Line Distribution Pareto.
Before:
# Total Tot ----- LLC Load Hitm -----
# Index Cacheline Node records Hitm Total Lcl Rmt
# ..... .................. .... ....... ....... ....... ....... .......
#
0 0x7f0830100000 0 84 10.53% 8 8 0
1 0xffff922a93154200 0 3 2.63% 2 2 0
2 0xffff922a93154500 0 4 2.63% 2 2 0After:
# ------- Cacheline ------ Total Tot ----- LLC Load Hitm -----
# Index Address Node records Hitm Total Lcl Rmt
# ..... .................. .... ....... ....... ....... ....... .......
#
0 0x7f0830100000 0 84 10.53% 8 8 0
1 0xffff922a93154200 0 3 2.63% 2 2 0
2 0xffff922a93154500 0 4 2.63% 2 2 0Before:
# ----- HITM ----- -- Store Refs -- Data address
# Num Rmt Lcl L1 Hit L1 Miss Offset Node Pid
# ..... ....... ....... ....... ....... .................. .... .......
#
-------------------------------------------------------------
0 0 8 32 2 0x7f0830100000
-------------------------------------------------------------
0.00% 75.00% 21.88% 0.00% 0x18 0 1791
0.00% 12.50% 37.50% 0.00% 0x18 0 1791
0.00% 0.00% 34.38% 0.00% 0x18 0 1791After:
# ----- HITM ----- -- Store Refs -- ----- Data address -----
# Num Rmt Lcl L1 Hit L1 Miss Offset Node Pid
# ..... ....... ....... ....... ....... .................. .... .......
#
-------------------------------------------------------------
0 0 8 32 2 0x7f0830100000
-------------------------------------------------------------
0.00% 75.00% 21.88% 0.00% 0x18 0 1791
0.00% 12.50% 37.50% 0.00% 0x18 0 1791
0.00% 0.00% 34.38% 0.00% 0x18 0 1791--- tools/perf/builtin-c2c.c | 63 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-)
tools/perf/builtin-c2c.c +58 -5
@@ -1252,7 +1252,7 @@ cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, }static struct c2c_dimension dim_dcacheline = { - .header =HEADER_LOW ("Cacheline" ), + .header =HEADER_SPAN ("--- Cacheline ----" ,"Address" ,1 ), .name ="dcacheline" , .cmp = dcacheline_cmp, .entry = dcacheline_entry,
@@ -1267,10 +1267,10 @@ static struct c2c_dimension dim_dcacheline_node = { .width = 4, }; -static struct c2c_header header_offset_tui =HEADER_LOW ("Off" ); +static struct c2c_header header_offset_tui =HEADER_SPAN ("-----" ,"Off" ,1 );static struct c2c_dimension dim_offset = { - .header =HEADER_BOTH ("Data address" ,"Offset" ), + .header =HEADER_SPAN ("--- Data address -" ,"Offset" ,1 ), .name ="offset" , .cmp = offset_cmp, .entry = offset_entry,
@@ -2453,14 +2453,64 @@ static void perf_c2c_display(struct perf_session *session) }#endif /* HAVE_SLANG_SUPPORT */ -static void ui_quirks (void ) +static char *fill_line (const char *orig,int len) { +int i, j, olen =strlen (orig); +char *buf; + + buf =zalloc (len +1 ); +if (!buf) +return NULL ; + + j = len /2 - olen /2 ; + +for (i =0 ; i < j -1 ; i++) + buf[i] ='-' ; + + buf[i++] =' ' ; + +strcpy (buf + i, orig); + + i += olen; + + buf[i++] =' ' ; + +for (; i < len; i++) + buf[i] ='-' ; + +return buf; +} + +static int ui_quirks (void ) +{ +const char *nodestr ="Data address" ; +char *buf; +if (!c2c.use_stdio) { dim_offset.width =5 ; dim_offset.header = header_offset_tui; + nodestr ="CL" ; } dim_percent_hitm.header = percent_hitm_header[c2c.display]; + +/* Fix the zero line for dcacheline column. */ + buf =fill_line ("Cacheline" , dim_dcacheline.width + + dim_dcacheline_node.width +2 ); +if (!buf) +return -ENOMEM ; + + dim_dcacheline.header.line[0 ].text = buf; + +/* Fix the zero line for offset column. */ + buf =fill_line (nodestr, dim_offset.width + + dim_offset_node.width +2 ); +if (!buf) +return -ENOMEM ; + + dim_offset.header.line[0 ].text = buf; + +return 0 ; }#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
@@ -2760,7 +2810,10 @@ static int perf_c2c__report(int argc, const char **argv)ui_progress__finish (); -ui_quirks (); +if (ui_quirks ()) { +pr_err ("failed to setup UI\n" ); + goto out_mem2node; + }perf_c2c_display (session);
Signature · 1 line
2.13.6
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf c2c report: Add span header over cacheline data
perf c2c report: Add span header over cacheline data
Commit-ID: d0802b1ee2c8b95e960f46fa14fe0fee562cb79a Gitweb: https://git.kernel.org/tip/d0802b1ee2c8b95e960f46fa14fe0fee562cb79a Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:41 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:53:30 -0300
perf c2c report: Add span header over cacheline data
Forcing the NUMA node output to be grouped with the "Cacheline" column in both "Shared Data Cache Line Table" and "Shared Cache Line Distribution Pareto" tables.
Before:
# Total Tot ----- LLC Load Hitm -----
# Index Cacheline Node records Hitm Total Lcl Rmt
# ..... .................. .... ....... ....... ....... ....... .......
#
0 0x7f0830100000 0 84 10.53% 8 8 0
1 0xffff922a93154200 0 3 2.63% 2 2 0
2 0xffff922a93154500 0 4 2.63% 2 2 0After:
# ------- Cacheline ------ Total Tot ----- LLC Load Hitm -----
# Index Address Node records Hitm Total Lcl Rmt
# ..... .................. .... ....... ....... ....... ....... .......
#
0 0x7f0830100000 0 84 10.53% 8 8 0
1 0xffff922a93154200 0 3 2.63% 2 2 0
2 0xffff922a93154500 0 4 2.63% 2 2 0Before:
# ----- HITM ----- -- Store Refs -- Data address
# Num Rmt Lcl L1 Hit L1 Miss Offset Node Pid
# ..... ....... ....... ....... ....... .................. .... .......
#
-------------------------------------------------------------
0 0 8 32 2 0x7f0830100000
-------------------------------------------------------------
0.00% 75.00% 21.88% 0.00% 0x18 0 1791
0.00% 12.50% 37.50% 0.00% 0x18 0 1791
0.00% 0.00% 34.38% 0.00% 0x18 0 1791After:
# ----- HITM ----- -- Store Refs -- ----- Data address -----
# Num Rmt Lcl L1 Hit L1 Miss Offset Node Pid
# ..... ....... ....... ....... ....... .................. .... .......
#
-------------------------------------------------------------
0 0 8 32 2 0x7f0830100000
-------------------------------------------------------------
0.00% 75.00% 21.88% 0.00% 0x18 0 1791
0.00% 12.50% 37.50% 0.00% 0x18 0 1791
0.00% 0.00% 34.38% 0.00% 0x18 0 1791--- tools/perf/builtin-c2c.c | 63 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-)
tools/perf/builtin-c2c.c +58 -5
@@ -1252,7 +1252,7 @@ cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, }static struct c2c_dimension dim_dcacheline = { - .header =HEADER_LOW ("Cacheline" ), + .header =HEADER_SPAN ("--- Cacheline ----" ,"Address" ,1 ), .name ="dcacheline" , .cmp = dcacheline_cmp, .entry = dcacheline_entry,
@@ -1267,10 +1267,10 @@ static struct c2c_dimension dim_dcacheline_node = { .width = 4, }; -static struct c2c_header header_offset_tui =HEADER_LOW ("Off" ); +static struct c2c_header header_offset_tui =HEADER_SPAN ("-----" ,"Off" ,1 );static struct c2c_dimension dim_offset = { - .header =HEADER_BOTH ("Data address" ,"Offset" ), + .header =HEADER_SPAN ("--- Data address -" ,"Offset" ,1 ), .name ="offset" , .cmp = offset_cmp, .entry = offset_entry,
@@ -2453,14 +2453,64 @@ static void perf_c2c_display(struct perf_session *session) }#endif /* HAVE_SLANG_SUPPORT */ -static void ui_quirks (void ) +static char *fill_line (const char *orig,int len) { +int i, j, olen =strlen (orig); +char *buf; + + buf =zalloc (len +1 ); +if (!buf) +return NULL ; + + j = len /2 - olen /2 ; + +for (i =0 ; i < j -1 ; i++) + buf[i] ='-' ; + + buf[i++] =' ' ; + +strcpy (buf + i, orig); + + i += olen; + + buf[i++] =' ' ; + +for (; i < len; i++) + buf[i] ='-' ; + +return buf; +} + +static int ui_quirks (void ) +{ +const char *nodestr ="Data address" ; +char *buf; +if (!c2c.use_stdio) { dim_offset.width =5 ; dim_offset.header = header_offset_tui; + nodestr ="CL" ; } dim_percent_hitm.header = percent_hitm_header[c2c.display]; + +/* Fix the zero line for dcacheline column. */ + buf =fill_line ("Cacheline" , dim_dcacheline.width + + dim_dcacheline_node.width +2 ); +if (!buf) +return -ENOMEM ; + + dim_dcacheline.header.line[0 ].text = buf; + +/* Fix the zero line for offset column. */ + buf =fill_line (nodestr, dim_offset.width + + dim_offset_node.width +2 ); +if (!buf) +return -ENOMEM ; + + dim_offset.header.line[0 ].text = buf; + +return 0 ; }#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
@@ -2760,7 +2810,10 @@ static int perf_c2c__report(int argc, const char **argv)ui_progress__finish (); -ui_quirks (); +if (ui_quirks ()) { +pr_err ("failed to setup UI\n" ); + goto out_mem2node; + }perf_c2c_display (session);
Jiri Olsa
reviewerPATCH v2 9/9 perf c2c report: Add cacheline address count column
In reply to Jiri OlsaAdding the 'PA cnt' column grouped under data cacheline address.
It shows how many times the physical addresses changed for the hist entry. It does not show the number of different physical addresses for entry, because we don't store those. We only track the number of times we got different address than we currently hold, which is not expensive and gives similar info.
$ perf c2c report --stdio
# ----------- Cacheline ---------- Total Tot ----- LLC Load Hitm -----
# Index Address Node PA cnt records Hitm Total Lcl Rmt
# ..... .................. .... ...... ....... ....... ....... ....... .......
#
0 0xffff9ad56dca0a80 0 9 10 7.69% 2 2 0
1 0xffff9ad56dce0a80 0 9 9 7.69% 2 2 0
2 0xffff9ad37659ad80 0 1 2 3.85% 1 1 0...
# ----- HITM ----- -- Store Refs -- --------- Data address ---------
# Num Rmt Lcl L1 Hit L1 Miss Offset Node PA cnt Pid
# ..... ....... ....... ....... ....... .................. .... ...... .......
#
-------------------------------------------------------------
0 0 2 3 0 0xffff9ad56dca0a80
-------------------------------------------------------------
0.00% 0.00% 33.33% 0.00% 0x0 0 1 2510
0.00% 0.00% 33.33% 0.00% 0x4 0 1 2476
0.00% 0.00% 33.33% 0.00% 0x20 0 1 0
0.00% 100.00% 0.00% 0.00% 0x38 0 1 0--- tools/perf/builtin-c2c.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-)
tools/perf/builtin-c2c.c +29 -6
@@ -507,6 +507,17 @@ dcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,return scnprintf (hpp->buf, hpp->size,"%*s" , width, c2c_he->nodestr); } +static int +dcacheline_node_count (struct perf_hpp_fmt *fmt,struct perf_hpp *hpp, +struct hist_entry *he) +{ +struct c2c_hist_entry *c2c_he; +int width =c2c_width (fmt, hpp, he->hists); + + c2c_he = container_of(he, struct c2c_hist_entry, he); +return scnprintf (hpp->buf, hpp->size,"%*lu" , width, c2c_he->paddr_cnt); +} +static int offset_entry (struct perf_hpp_fmt *fmt,struct perf_hpp *hpp,struct hist_entry *he) {
@@ -1252,7 +1263,7 @@ cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, }static struct c2c_dimension dim_dcacheline = { - .header =HEADER_SPAN ("--- Cacheline ----" ,"Address" ,1 ), + .header =HEADER_SPAN ("--- Cacheline ----" ,"Address" ,2 ), .name ="dcacheline" , .cmp = dcacheline_cmp, .entry = dcacheline_entry,
@@ -1267,10 +1278,18 @@ static struct c2c_dimension dim_dcacheline_node = { .width = 4, }; -static struct c2c_header header_offset_tui =HEADER_SPAN ("-----" ,"Off" ,1 ); +static struct c2c_dimension dim_dcacheline_count = { + .header =HEADER_LOW ("PA cnt" ), + .name ="dcacheline_count" , + .cmp = empty_cmp, + .entry = dcacheline_node_count, + .width =6 , +}; + +static struct c2c_header header_offset_tui =HEADER_SPAN ("-----" ,"Off" ,2 );static struct c2c_dimension dim_offset = { - .header =HEADER_SPAN ("--- Data address -" ,"Offset" ,1 ), + .header =HEADER_SPAN ("--- Data address -" ,"Offset" ,2 ), .name ="offset" , .cmp = offset_cmp, .entry = offset_entry,
@@ -1605,6 +1624,7 @@ static struct c2c_dimension dim_dcacheline_num_empty = {static struct c2c_dimension *dimensions[] = { &dim_dcacheline, &dim_dcacheline_node, + &dim_dcacheline_count, &dim_offset, &dim_offset_node, &dim_iaddr,
@@ -2496,7 +2516,8 @@ static int ui_quirks(void)/* Fix the zero line for dcacheline column. */ buf =fill_line ("Cacheline" , dim_dcacheline.width + - dim_dcacheline_node.width +2 ); + dim_dcacheline_node.width + + dim_dcacheline_count.width +4 );if (!buf)return -ENOMEM ;
@@ -2504,7 +2525,8 @@ static int ui_quirks(void)/* Fix the zero line for offset column. */ buf =fill_line (nodestr, dim_offset.width + - dim_offset_node.width +2 ); + dim_offset_node.width + + dim_dcacheline_count.width +4 );if (!buf)return -ENOMEM ;
@@ -2626,7 +2648,7 @@ static int build_cl_output(char *cl_sort, bool no_source)"percent_lcl_hitm," "percent_stores_l1hit," "percent_stores_l1miss," -"offset,offset_node," , +"offset,offset_node,dcacheline_count," , add_pid ?"pid," :"" , add_tid ?"tid," :"" , add_iaddr ? "iaddr," : "",
@@ -2789,6 +2811,7 @@ static int perf_c2c__report(int argc, const char **argv)"cl_idx," "dcacheline," "dcacheline_node," +"dcacheline_count," "tot_recs," "percent_hitm," "tot_hitm,lcl_hitm,rmt_hitm,"
Signature · 1 line
2.13.6
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 9/9] perf c2c report: Add cacheline address count column
Em Fri, Mar 09, 2018 at 11:14:42AM +0100, Jiri Olsa escreveu:
Quoted 8 lines
Adding the 'PA cnt' column grouped under data cacheline address.
It shows how many times the physical addresses changed for the hist entry. It does not show the number of different physical addresses for entry, because we don't store those. We only track the number of times we got different address than we currently hold, which is not expensive and gives similar info.
Quoted 6 lines
$ perf c2c report --stdio# ----------- Cacheline ---------- Total Tot ----- LLC Load Hitm -----
# Index Address Node PA cnt records Hitm Total Lcl Rmt # ..... .................. .... ...... ....... ....... ....... ....... .......#
I'm adding this to the docs, ack?
tools/perf/Documentation/perf-report.txt +2 -1
@@ -127,7 +127,7 @@ OPTIONS If the --mem-mode option is used, the following sort keys are also available (incompatible with --branch-stack): - symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline. + symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline, dcacheline_count. - symbol_daddr: name of data symbol being executed on at the time of sample - dso_daddr: name of library or module containing the data being executed
@@ -137,6 +137,7 @@ OPTIONS - mem: type of memory access for the data at the time of the sample - snoop: type of snoop (if any) for the data at the time of the sample - dcacheline: the cacheline the data address is on at the time of the sample + - dcacheline_count: the number of physical addresses sampled for this dcacheline - phys_daddr: physical address of data being executed on at the time of sample And the default sort keys are changed to local_weight, mem, sym, dso,
Re: [PATCH 9/9] perf c2c report: Add cacheline address count column
Quoted 11 lines · Arnaldo Carvalho de Melo
Em Fri, Mar 09, 2018 at 11:14:42AM +0100, Jiri Olsa escreveu:
Quoted 10 lines
Adding the 'PA cnt' column grouped under data cacheline address.
It shows how many times the physical addresses changed for the hist entry. It does not show the number of different physical addresses for entry, because we don't store those. We only track the number of times we got different address than we currently hold, which is not expensive and gives similar info.
$ perf c2c report --stdio
Quoted 7 lines
Quoted 4 lines
# ----------- Cacheline ---------- Total Tot ----- LLC Load Hitm -----
# Index Address Node PA cnt records Hitm Total Lcl Rmt # ..... .................. .... ...... ....... ....... ....... ....... .......#
I'm adding this to the docs, ack?
nope.. those fields are c2c report only.. hardcoded
I'm preparing a change to share c2c fields with the general report.. should come with other perf mem changes later
jirka
Quoted 22 lines
tools/perf/Documentation/perf-report.txt +2
-1@@ -127,7 +127,7 @@ OPTIONS If the --mem-mode option is used, the following sort keys are also available (incompatible with --branch-stack): - symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline. + symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline, dcacheline_count. - symbol_daddr: name of data symbol being executed on at the time of sample - dso_daddr: name of library or module containing the data being executed@@ -137,6 +137,7 @@ OPTIONS - mem: type of memory access for the data at the time of the sample - snoop: type of snoop (if any) for the data at the time of the sample - dcacheline: the cacheline the data address is on at the time of the sample + - dcacheline_count: the number of physical addresses sampled for this dcacheline - phys_daddr: physical address of data being executed on at the time of sample And the default sort keys are changed to local_weight, mem, sym, dso,
Arnaldo Carvalho de Melo
maintainerRe: [PATCH 9/9] perf c2c report: Add cacheline address count column
Em Fri, Mar 09, 2018 at 05:28:28PM +0100, Jiri Olsa escreveu:
Quoted 18 lines · Arnaldo Carvalho de Melo
Quoted 17 lines
Em Fri, Mar 09, 2018 at 11:14:42AM +0100, Jiri Olsa escreveu:
Quoted 14 lines
Adding the 'PA cnt' column grouped under data cacheline address.
It shows how many times the physical addresses changed for the hist entry. It does not show the number of different physical addresses for entry, because we don't store those. We only track the number of times we got different address than we currently hold, which is not expensive and gives similar info.
$ perf c2c report --stdio# ----------- Cacheline ---------- Total Tot ----- LLC Load Hitm -----
# Index Address Node PA cnt records Hitm Total Lcl Rmt # ..... .................. .... ...... ....... ....... ....... ....... .......#
Quoted 7 lines
Quoted 1 line
I'm adding this to the docs, ack?
nope.. those fields are c2c report only.. hardcoded
I'm preparing a change to share c2c fields with the general report.. should come with other perf mem changes later
Ok, dropping that then
Quoted 24 lines
jirka
Quoted 22 lines
tools/perf/Documentation/perf-report.txt +2
-1@@ -127,7 +127,7 @@ OPTIONS If the --mem-mode option is used, the following sort keys are also available (incompatible with --branch-stack): - symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline. + symbol_daddr, dso_daddr, locked, tlb, mem, snoop, dcacheline, dcacheline_count. - symbol_daddr: name of data symbol being executed on at the time of sample - dso_daddr: name of library or module containing the data being executed@@ -137,6 +137,7 @@ OPTIONS - mem: type of memory access for the data at the time of the sample - snoop: type of snoop (if any) for the data at the time of the sample - dcacheline: the cacheline the data address is on at the time of the sample + - dcacheline_count: the number of physical addresses sampled for this dcacheline - phys_daddr: physical address of data being executed on at the time of sample And the default sort keys are changed to local_weight, mem, sym, dso,
tip-bot for Jiri Olsa
merge bot[tip:perf/core] perf c2c report: Add cacheline address count column
In reply to Jiri Olsaperf c2c report: Add cacheline address count column
Commit-ID: 03d9fcb701340de3446b4ff4ddb9f5407d1412f5 Gitweb: https://git.kernel.org/tip/03d9fcb701340de3446b4ff4ddb9f5407d1412f5 Author: Jiri Olsa <[email protected]> AuthorDate: Fri, 9 Mar 2018 11:14:42 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 16 Mar 2018 13:53:38 -0300
perf c2c report: Add cacheline address count column
Adding the 'PA cnt' column grouped under data cacheline address.
It shows how many times the physical addresses changed for the hist entry. It does not show the number of different physical addresses for entry, because we don't store those. We only track the number of times we got different address than we currently hold, which is not expensive and gives similar info.
$ perf c2c report --stdio
# ----------- Cacheline ---------- Total Tot ----- LLC Load Hitm -----
# Index Address Node PA cnt records Hitm Total Lcl Rmt
# ..... .................. .... ...... ....... ....... ....... ....... .......
#
0 0xffff9ad56dca0a80 0 9 10 7.69% 2 2 0
1 0xffff9ad56dce0a80 0 9 9 7.69% 2 2 0
2 0xffff9ad37659ad80 0 1 2 3.85% 1 1 0...
# ----- HITM ----- -- Store Refs -- --------- Data address ---------
# Num Rmt Lcl L1 Hit L1 Miss Offset Node PA cnt Pid
# ..... ....... ....... ....... ....... .................. .... ...... .......
#
-------------------------------------------------------------
0 0 2 3 0 0xffff9ad56dca0a80
-------------------------------------------------------------
0.00% 0.00% 33.33% 0.00% 0x0 0 1 2510
0.00% 0.00% 33.33% 0.00% 0x4 0 1 2476
0.00% 0.00% 33.33% 0.00% 0x20 0 1 0
0.00% 100.00% 0.00% 0.00% 0x38 0 1 0--- tools/perf/builtin-c2c.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-)
tools/perf/builtin-c2c.c +29 -6
@@ -507,6 +507,17 @@ dcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,return scnprintf (hpp->buf, hpp->size,"%*s" , width, c2c_he->nodestr); } +static int +dcacheline_node_count (struct perf_hpp_fmt *fmt,struct perf_hpp *hpp, +struct hist_entry *he) +{ +struct c2c_hist_entry *c2c_he; +int width =c2c_width (fmt, hpp, he->hists); + + c2c_he = container_of(he, struct c2c_hist_entry, he); +return scnprintf (hpp->buf, hpp->size,"%*lu" , width, c2c_he->paddr_cnt); +} +static int offset_entry (struct perf_hpp_fmt *fmt,struct perf_hpp *hpp,struct hist_entry *he) {
@@ -1252,7 +1263,7 @@ cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, }static struct c2c_dimension dim_dcacheline = { - .header =HEADER_SPAN ("--- Cacheline ----" ,"Address" ,1 ), + .header =HEADER_SPAN ("--- Cacheline ----" ,"Address" ,2 ), .name ="dcacheline" , .cmp = dcacheline_cmp, .entry = dcacheline_entry,
@@ -1267,10 +1278,18 @@ static struct c2c_dimension dim_dcacheline_node = { .width = 4, }; -static struct c2c_header header_offset_tui =HEADER_SPAN ("-----" ,"Off" ,1 ); +static struct c2c_dimension dim_dcacheline_count = { + .header =HEADER_LOW ("PA cnt" ), + .name ="dcacheline_count" , + .cmp = empty_cmp, + .entry = dcacheline_node_count, + .width =6 , +}; + +static struct c2c_header header_offset_tui =HEADER_SPAN ("-----" ,"Off" ,2 );static struct c2c_dimension dim_offset = { - .header =HEADER_SPAN ("--- Data address -" ,"Offset" ,1 ), + .header =HEADER_SPAN ("--- Data address -" ,"Offset" ,2 ), .name ="offset" , .cmp = offset_cmp, .entry = offset_entry,
@@ -1605,6 +1624,7 @@ static struct c2c_dimension dim_dcacheline_num_empty = {static struct c2c_dimension *dimensions[] = { &dim_dcacheline, &dim_dcacheline_node, + &dim_dcacheline_count, &dim_offset, &dim_offset_node, &dim_iaddr,
@@ -2496,7 +2516,8 @@ static int ui_quirks(void)/* Fix the zero line for dcacheline column. */ buf =fill_line ("Cacheline" , dim_dcacheline.width + - dim_dcacheline_node.width +2 ); + dim_dcacheline_node.width + + dim_dcacheline_count.width +4 );if (!buf)return -ENOMEM ;
@@ -2504,7 +2525,8 @@ static int ui_quirks(void)/* Fix the zero line for offset column. */ buf =fill_line (nodestr, dim_offset.width + - dim_offset_node.width +2 ); + dim_offset_node.width + + dim_dcacheline_count.width +4 );if (!buf)return -ENOMEM ;
@@ -2626,7 +2648,7 @@ static int build_cl_output(char *cl_sort, bool no_source)"percent_lcl_hitm," "percent_stores_l1hit," "percent_stores_l1miss," -"offset,offset_node," , +"offset,offset_node,dcacheline_count," , add_pid ?"pid," :"" , add_tid ?"tid," :"" , add_iaddr ? "iaddr," : "",
@@ -2789,6 +2811,7 @@ static int perf_c2c__report(int argc, const char **argv)"cl_idx," "dcacheline," "dcacheline_node," +"dcacheline_count," "tot_recs," "percent_hitm," "tot_hitm,lcl_hitm,rmt_hitm,"