perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit 4e6e311e596eadba30d4f56f64eae7d45611a01c:
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2014-11-20 08:32:01 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
for you to fetch changes up to 1d9e446b91e182055d874fbb30150aad479a4981:
perf tools: Add snapshot format file parsing (2014-11-24 18:03:51 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Callchain improvements from Andi Kleen including:
* Enable printing the srcline in the history
* Make get_srcline fall back to sym+offset
- Allow to force redirect pr_debug to stderr. (Andi Kleen)
- TUI hist_entry browser fixes, including showing missing overhead value for first level callchain. Detected comparing the output of --stdio/--gui (that matched) with --tui, that had this problem. (Namhyung Kim)
- Fix segfault due to invalid kernel dso access (Namhyung Kim)
Infrastructure:
- Move bfd_demangle stubbing to its only user (Arnaldo Carvalho de Melo)
- 'perf stat' refactorings, moving stuff from it to evsel.c to use in per-pkg/snapshot format changes (Jiri Olsa)
- Add per-pkg format file parsing (Matt Fleming)
----------------------------------------------------------------
Andi Kleen (3):
perf callchain: Enable printing the srcline in the history perf callchain: Make get_srcline fall back to sym+offset perf tools: Allow to force redirect pr_debug to stderr.
Arnaldo Carvalho de Melo (1):
perf symbols: Move bfd_demangle stubbing to its only user
Jiri Olsa (4):
perf evsel: Introduce perf_evsel__compute_deltas function perf evsel: Introduce perf_counts_values__scale function perf evsel: Introduce perf_evsel__read_cb function perf tools: Add snapshot format file parsing
Matt Fleming (1):
perf tools: Add per-pkg format file parsing
Namhyung Kim (3):
perf hists browser: Print overhead percent value for first-level callchain perf tools: Collapse first level callchain entry if it has sibling perf tools: Fix segfault due to invalid kernel dso access
tools/perf/ui/browsers/hists.c | 25 +++++++++++--- tools/perf/util/annotate.c | 2 +- tools/perf/util/callchain.c | 12 ++++++- tools/perf/util/callchain.h | 1 + tools/perf/util/debug.c | 4 ++- tools/perf/util/evsel.c | 72 +++++++++++++++++++++++----------------- tools/perf/util/evsel.h | 15 +++++++++ tools/perf/util/machine.c | 4 +-- tools/perf/util/map.c | 2 +- tools/perf/util/parse-events.c | 2 ++ tools/perf/util/pmu.c | 74 +++++++++++++++++++++++++++++++++++------- tools/perf/util/pmu.h | 4 +++ tools/perf/util/sort.c | 6 ++-- tools/perf/util/srcline.c | 15 +++++++-- tools/perf/util/symbol-elf.c | 21 ++++++++++++ tools/perf/util/symbol.h | 21 ------------ tools/perf/util/util.h | 4 ++- 17 files changed, 205 insertions(+), 79 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/12 perf hists browser: Print overhead percent value for first-level callchain
From: Namhyung Kim <[email protected]>
Currently perf report on TUI doesn't print percent for first-level callchain entry.
I guess it (wrongly) assumes that there's only a single callchain in the first level.
This patch fixes it by handling the first level callchains same as others - if it's not 100% it should print the percent value.
Also it'll affect other callchains in the other way around - if it's 100% (single callchain) it should not print the percentage.
Before:
- 30.95% 6.84% abc2 abc2 [.] a
- a
- 70.00% c
- 100.00% apic_timer_interrupt
smp_apic_timer_interrupt
local_apic_timer_interrupt
hrtimer_interrupt
...
+ 30.00% b
+ __libc_start_main
After:
- 30.95% 6.84% abc2 abc2 [.] a
- 77.90% a
- 70.00% c
- apic_timer_interrupt
smp_apic_timer_interrupt
local_apic_timer_interrupt
hrtimer_interrupt
...
+ 30.00% b
+ 22.10% __libc_start_main
--- tools/perf/ui/browsers/hists.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-)
tools/perf/ui/browsers/hists.c +12 -2
@@ -542,8 +542,11 @@ static int hist_browser__show_callchain(struct hist_browser *browser,struct rb_node *node;int first_row = row, offset = level *LEVEL_OFFSET_STEP ;u64 new_total; +bool need_percent; node =rb_first (root); + need_percent = !!rb_next (node); +while (node) { struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);struct rb_node *next =rb_next (node);
@@ -560,7 +563,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,if (first) first = false; -else if (level >1 ) +else if (need_percent) extra_offset =LEVEL_OFFSET_STEP ; folded_sign =callchain_list__folded (chain);
@@ -573,7 +576,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, str =callchain_list__sym_name (chain, bf,sizeof (bf), browser->show_dso); -if (was_first && level >1 ) { +if (was_first && need_percent) {double percent = cumul *100.0 / total;if (asprintf (&alloc_str,"%2.2f%% %s" , percent, str) <0 )
@@ -790,6 +793,13 @@ static int hist_browser__show_entry(struct hist_browser *browser, .is_current_entry = current_entry, }; +if (callchain_param.mode ==CHAIN_GRAPH_REL ) { +if (symbol_conf.cumulate_callchain) + total = entry->stat_acc->period; +else + total = entry->stat.period; + } + printed += hist_browser__show_callchain(browser, &entry->sorted_chain, 1, row, total, hist_browser__show_callchain_entry, &arg,
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/12 perf tools: Collapse first level callchain entry if it has sibling
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
If first level callchain has more than single path like when -g caller option is given, it should show only first one in the path and hide others. But it didn't do it properly and just hindered the output.
Before:
- 80.33% 11.11% abc2 abc2 [.] main
+ 86.18% main
13.82% __libc_start_main
main
After:
- 80.33% 11.11% abc2 abc2 [.] main
+ 86.18% main
+ 13.82% __libc_start_main
--- tools/perf/ui/browsers/hists.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
tools/perf/ui/browsers/hists.c +8 -3
@@ -227,10 +227,14 @@ static void callchain_node__init_have_children_rb_tree(struct callchain_node *no } } -static void callchain_node__init_have_children (struct callchain_node *node) +static void callchain_node__init_have_children (struct callchain_node *node, +bool has_sibling) {struct callchain_list *chain; + chain = list_entry(node->val.next, struct callchain_list, list); + chain->ms.has_children = has_sibling; +if (!list_empty (&node->val)) { chain = list_entry(node->val.prev, struct callchain_list, list); chain->ms.has_children = !RB_EMPTY_ROOT (&node->rb_root);
@@ -241,11 +245,12 @@ static void callchain_node__init_have_children(struct callchain_node *node)static void callchain__init_have_children (struct rb_root *root) { -struct rb_node *nd; +struct rb_node *nd =rb_first (root); +bool has_sibling = nd &&rb_next (nd);for (nd =rb_first (root); nd; nd =rb_next (nd)) { struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); -callchain_node__init_have_children (node); +callchain_node__init_have_children (node, has_sibling); } }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/12 perf callchain: Enable printing the srcline in the history
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
For lbr-as-callgraph we need to see the line number in the history, because many LBR entries can be in a single function, and just showing the same function name many times is not useful.
When the history code is configured to sort by address, also try to resolve the address to a file:srcline and display this in the browser. If that doesn't work still display the address.
This can be also useful without LBRs for understanding which call in a large function (or in which inlined function) called something else.
Contains fixes from Namhyung Kim
v2: Refactor code into common function
v3: Fix GTK build
v4: Rebase
--- tools/perf/util/callchain.c | 11 ++++++++++- tools/perf/util/callchain.h | 1 + tools/perf/util/srcline.c | 6 ++++-- 3 files changed, 15 insertions(+), 3 deletions(-)
tools/perf/util/callchain.c +10 -1
@@ -815,7 +815,16 @@ char *callchain_list__sym_name(struct callchain_list *cl,int printed;if (cl->ms.sym) { - printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); +if (callchain_param.key ==CCKEY_ADDRESS && + cl->ms.map && !cl->srcline) + cl->srcline =get_srcline (cl->ms.map->dso, +map__rip_2objdump (cl->ms.map, + cl->ip)); +if (cl->srcline) + printed =scnprintf (bf, bfsize,"%s %s" , + cl->ms.sym->name, cl->srcline); +else + printed =scnprintf (bf, bfsize,"%s" , cl->ms.sym->name); }else printed =scnprintf (bf, bfsize,"%#" PRIx64, cl->ip);
tools/perf/util/callchain.h +1 -0
@@ -70,6 +70,7 @@ extern struct callchain_param callchain_param;struct callchain_list {u64 ip;struct map_symbol ms; +char *srcline;struct list_head list; };
tools/perf/util/srcline.c +4 -2
@@ -258,7 +258,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)const char *dso_name;if (!dso->has_srcline) -return SRCLINE_UNKNOWN ; + goto out;if (dso->symsrc_filename) dso_name = dso->symsrc_filename;
@@ -289,7 +289,9 @@ out: dso->has_srcline =0 ;dso__free_a2l (dso); } -return SRCLINE_UNKNOWN ; +if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 ) +return SRCLINE_UNKNOWN ; +return srcline; }void free_srcline (char *srcline)
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 4/12 perf symbols: Move bfd_demangle stubbing to its only user
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We need to define bfd_demangle() to either a wrapper for cplus_demangle() or to a stub when NO_DEMANGLE is defined.
That is at odds with using bfd.h for some other reason, as it defines bfd_demangle() and then if code that wants to use symbol.h, where the above stubbing/wrapping is done, and bfd.h for other reasons, we end up with a build error where bfd_demangle() is found to be redefined.
Avoid that by moving the stubbing/wrapping to symbol-elf.c, that is the only user of such function. If we ever get to a point where there are more valid users, we can then introduce a header for that.
--- tools/perf/util/symbol-elf.c | 21 +++++++++++++++++++++ tools/perf/util/symbol.h | 21 --------------------- 2 files changed, 21 insertions(+), 21 deletions(-)
tools/perf/util/symbol-elf.c +21 -0
@@ -11,6 +11,27 @@#include <symbol/kallsyms.h> #include "debug.h" +#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT +extern char *cplus_demangle (const char *,int ); + +static inline char *bfd_demangle (void __maybe_unused *v,const char *c,int i) +{ +return cplus_demangle (c, i); +} +#else +#ifdef NO_DEMANGLE +static inline char *bfd_demangle (void __maybe_unused *v, +const char __maybe_unused *c, +int __maybe_unused i) +{ +return NULL ; +} +#else +#define PACKAGE 'perf' +#include <bfd.h> +#endif +#endif +#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT static int elf_getphdrnum (Elf *elf,size_t *dst) {
tools/perf/util/symbol.h +0 -21
@@ -23,27 +23,6 @@#include "dso.h" -#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT -extern char *cplus_demangle (const char *,int ); - -static inline char *bfd_demangle (void __maybe_unused *v,const char *c,int i) -{ -return cplus_demangle (c, i); -} -#else -#ifdef NO_DEMANGLE -static inline char *bfd_demangle (void __maybe_unused *v, -const char __maybe_unused *c, -int __maybe_unused i) -{ -return NULL ; -} -#else -#define PACKAGE 'perf' -#include <bfd.h> -#endif -#endif -/* * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; * for newer versions we can use mmap to reduce memory usage:
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/12 perf callchain: Make get_srcline fall back to sym+offset
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
When the source line is not found fall back to sym + offset. This is generally much more useful than a raw address.
For this we need to pass in the symbol from the caller.
For some callers it's awkward to compute, so we stay at the old behaviour.
--- tools/perf/util/annotate.c | 2 +- tools/perf/util/callchain.c | 3 ++- tools/perf/util/map.c | 2 +- tools/perf/util/sort.c | 6 ++++-- tools/perf/util/srcline.c | 11 +++++++++-- tools/perf/util/util.h | 4 +++- 6 files changed, 20 insertions(+), 8 deletions(-)
tools/perf/util/annotate.c +1 -1
@@ -1192,7 +1192,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, goto next; offset = start + i; - src_line->path =get_srcline (map->dso, offset); + src_line->path =get_srcline (map->dso, offset,NULL , false);insert_source_line (&tmp_root, src_line); next:
tools/perf/util/callchain.c +2 -1
@@ -819,7 +819,8 @@ char *callchain_list__sym_name(struct callchain_list *cl, cl->ms.map && !cl->srcline) cl->srcline =get_srcline (cl->ms.map->dso,map__rip_2objdump (cl->ms.map, - cl->ip)); + cl->ip), + cl->ms.sym, false);if (cl->srcline) printed =scnprintf (bf, bfsize,"%s %s" , cl->ms.sym->name, cl->srcline);
tools/perf/util/map.c +1 -1
@@ -360,7 +360,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,if (map && map->dso) { srcline =get_srcline (map->dso, -map__rip_2objdump (map, addr)); +map__rip_2objdump (map, addr),NULL , true);if (srcline !=SRCLINE_UNKNOWN ) ret =fprintf (fp,"%s%s" , prefix, srcline);free_srcline (srcline);
tools/perf/util/sort.c +4 -2
@@ -291,7 +291,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)else {struct map *map = left->ms.map; left->srcline =get_srcline (map->dso, -map__rip_2objdump (map, left->ip)); +map__rip_2objdump (map, left->ip), + left->ms.sym, true); } }if (!right->srcline) {
@@ -300,7 +301,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)else {struct map *map = right->ms.map; right->srcline =get_srcline (map->dso, -map__rip_2objdump (map, right->ip)); +map__rip_2objdump (map, right->ip), + right->ms.sym, true); } }return strcmp (right->srcline, left->srcline);
tools/perf/util/srcline.c +9 -2
@@ -8,6 +8,8 @@#include "util/util.h" #include "util/debug.h" +#include "symbol.h" +#ifdef HAVE_LIBBFD_SUPPORT /*
@@ -250,7 +252,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused)*/ #define A2L_FAIL_LIMIT 123 -char *get_srcline (struct dso *dso,unsigned long addr) +char *get_srcline (struct dso *dso,unsigned long addr,struct symbol *sym, +bool show_sym) {char *file =NULL ;unsigned line =0 ;
@@ -289,7 +292,11 @@ out: dso->has_srcline =0 ;dso__free_a2l (dso); } -if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 ) +if (sym) { +if (asprintf (&srcline,"%s+%ld" , show_sym ? sym->name :"" , + addr - sym->start) <0 ) +return SRCLINE_UNKNOWN ; + }else if (asprintf (&srcline,"%s[%lx]" , dso->short_name, addr) <0 )return SRCLINE_UNKNOWN ;return srcline; }
tools/perf/util/util.h +3 -1
@@ -337,8 +337,10 @@ static inline int path__join3(char *bf, size_t size, }struct dso ; +struct symbol ; -char *get_srcline (struct dso *dso,unsigned long addr); +char *get_srcline (struct dso *dso,unsigned long addr,struct symbol *sym, +bool show_sym);void free_srcline (char *srcline);int filename__read_int (const char *filename,int *value);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 6/12 perf tools: Fix segfault due to invalid kernel dso access
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Jiri reported that the commit 96d78059d6d9 ("perf tools: Make vmlinux short name more like kallsyms short name") segfaults on perf script.
When processing kernel mmap event, it should access the 'kernel' variable as sometimes it cannot find a matching dso from build-id table so 'dso' might be invalid.
--- tools/perf/util/machine.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/util/machine.c +2 -2
@@ -1106,8 +1106,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,if (__machine__create_kernel_maps (machine, kernel) <0 ) goto out_problem; -if (strstr (dso->long_name,"vmlinux" )) -dso__set_short_name (dso,"[kernel.vmlinux]" , false); +if (strstr (kernel->long_name,"vmlinux" )) +dso__set_short_name (kernel,"[kernel.vmlinux]" , false);machine__set_kernel_mmap_len (machine, event);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 7/12 perf tools: Allow to force redirect pr_debug to stderr.
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
When debugging the tui browser I find it useful to redirect the debug log into a file. Currently it's always forced to the message line.
Add an option to force it to stderr. Then it can be easily redirected.
Example:
[root@zoo ~]# perf --debug stderr report -vv 2> /tmp/debug
[root@zoo ~]# tail /tmp/debug
dso open failed, mmap: No such file or directory
dso open failed, mmap: No such file or directory
dso open failed, mmap: No such file or directory
dso open failed, mmap: No such file or directory
dso open failed, mmap: No such file or directory
Using /root/.debug/.build-id/4e/841948927029fb650132253642d5dbb2c1fb93 for symbols Failed to open /tmp/perf-8831.map, continuing without symbols
Failed to open /tmp/perf-12721.map, continuing without symbols Failed to open /tmp/perf-6966.map, continuing without symbols
Failed to open /tmp/perf-8802.map, continuing without symbols [root@zoo ~]#
--- tools/perf/util/debug.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/debug.c +3 -1
@@ -19,13 +19,14 @@int verbose;bool dump_trace = false, quiet = false;int debug_ordered_events; +static int redirect_to_stderr;static int _eprintf (int level,int var,const char *fmt,va_list args) {int ret =0 ;if (var >= level) { -if (use_browser >=1 ) +if (use_browser >=1 && !redirect_to_stderr)ui_helpline__vshow (fmt, args);else ret =vfprintf (stderr, fmt, args);
@@ -145,6 +146,7 @@ static struct debug_variable { } debug_variables[] = { { .name = "verbose", .ptr = &verbose }, { .name = "ordered-events", .ptr = &debug_ordered_events}, + { .name = "stderr", .ptr = &redirect_to_stderr}, { .name = NULL, } };
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 8/12 perf evsel: Introduce perf_evsel__compute_deltas function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Making compute_deltas functions global and renaming it to perf_evsel__compute_deltas.
It will be used in stat command in later patch.
--- tools/perf/util/evsel.c | 9 ++++----- tools/perf/util/evsel.h | 3 +++ 2 files changed, 7 insertions(+), 5 deletions(-)
tools/perf/util/evsel.c +4 -5
@@ -876,9 +876,8 @@ void perf_evsel__delete(struct perf_evsel *evsel)free (evsel); } -static inline void compute_deltas (struct perf_evsel *evsel, -int cpu, -struct perf_counts_values *count) +void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu, +struct perf_counts_values *count) {struct perf_counts_values tmp;
@@ -913,7 +912,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,if (readn (FD (evsel, cpu, thread), &count, nv *sizeof (u64)) <0 )return -errno; -compute_deltas (evsel, cpu, &count); +perf_evsel__compute_deltas (evsel, cpu, &count);if (scale) {if (count.run ==0 )
@@ -956,7 +955,7 @@ int __perf_evsel__read(struct perf_evsel *evsel, } } -compute_deltas (evsel,-1 , aggr); +perf_evsel__compute_deltas (evsel,-1 , aggr); evsel->counts->scaled =0 ;if (scale) {
tools/perf/util/evsel.h +3 -0
@@ -110,6 +110,9 @@ struct thread_map;struct perf_evlist ;struct record_opts ; +void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu, +struct perf_counts_values *count); +int perf_evsel__object_config (size_t object_size,int (*init)(struct perf_evsel *evsel),void (*fini)(struct perf_evsel *evsel));
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 9/12 perf evsel: Introduce perf_counts_values__scale function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Factoring out scale login into perf_counts_values__scale function.
--- tools/perf/util/evsel.c | 47 ++++++++++++++++++++++------------------------- tools/perf/util/evsel.h | 3 +++ 2 files changed, 25 insertions(+), 25 deletions(-)
tools/perf/util/evsel.c +22 -25
@@ -897,6 +897,26 @@ void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, count->run = count->run - tmp.run; } +void perf_counts_values__scale (struct perf_counts_values *count, +bool scale,s8 *pscaled) +{ +s8 scaled =0 ; + +if (scale) { +if (count->run ==0 ) { + scaled =-1 ; + count->val =0 ; + }else if (count->run < count->ena) { + scaled =1 ; + count->val = (u64)((double ) count->val * count->ena / count->run +0.5 ); + } + }else + count->ena = count->run =0 ; + +if (pscaled) + *pscaled = scaled; +} +int __perf_evsel__read_on_cpu (struct perf_evsel *evsel,int cpu,int thread,bool scale) {
@@ -913,15 +933,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,return -errno;perf_evsel__compute_deltas (evsel, cpu, &count); - -if (scale) { -if (count.run ==0 ) - count.val =0 ; -else if (count.run < count.ena) - count.val = (u64)((double )count.val * count.ena / count.run +0.5 ); - }else - count.ena = count.run =0 ; - +perf_counts_values__scale (&count, scale,NULL ); evsel->counts->cpu[cpu] = count;return 0 ; }
@@ -956,22 +968,7 @@ int __perf_evsel__read(struct perf_evsel *evsel, }perf_evsel__compute_deltas (evsel,-1 , aggr); - - evsel->counts->scaled =0 ; -if (scale) { -if (aggr->run ==0 ) { - evsel->counts->scaled =-1 ; - aggr->val =0 ; -return 0 ; - } - -if (aggr->run < aggr->ena) { - evsel->counts->scaled =1 ; - aggr->val = (u64)((double )aggr->val * aggr->ena / aggr->run +0.5 ); - } - }else - aggr->ena = aggr->run =0 ; - +perf_counts_values__scale (aggr, scale, &evsel->counts->scaled);return 0 ; }
tools/perf/util/evsel.h +3 -0
@@ -110,6 +110,9 @@ struct thread_map;struct perf_evlist ;struct record_opts ; +void perf_counts_values__scale (struct perf_counts_values *count, +bool scale,s8 *pscaled); +void perf_evsel__compute_deltas (struct perf_evsel *evsel,int cpu,struct perf_counts_values *count);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 10/12 perf evsel: Introduce perf_evsel__read_cb function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Adding perf_evsel__read_cb read function that retuns count values via callback. It will be used later in stat command as single way to retrieve counter values.
--- tools/perf/util/evsel.c | 16 ++++++++++++++++ tools/perf/util/evsel.h | 7 +++++++ 2 files changed, 23 insertions(+)
tools/perf/util/evsel.c +16 -0
@@ -917,6 +917,22 @@ void perf_counts_values__scale(struct perf_counts_values *count, *pscaled = scaled; } +int perf_evsel__read_cb (struct perf_evsel *evsel,int cpu,int thread, +perf_evsel__read_cb_t cb) +{ +struct perf_counts_values count; + +memset (&count,0 ,sizeof (count)); + +if (FD (evsel, cpu, thread) <0 ) +return -EINVAL ; + +if (readn (FD (evsel, cpu, thread), &count,sizeof (count)) <0 ) +return -errno; + +return cb (evsel, cpu, thread, &count); +} +int __perf_evsel__read_on_cpu (struct perf_evsel *evsel,int cpu,int thread,bool scale) {
tools/perf/util/evsel.h +7 -0
@@ -233,6 +233,13 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1, (a)->attr.type == (b)->attr.type && \ (a)->attr.config == (b)->attr.config) +typedef int (perf_evsel__read_cb_t )(struct perf_evsel *evsel, +int cpu,int thread, +struct perf_counts_values *count); + +int perf_evsel__read_cb (struct perf_evsel *evsel,int cpu,int thread, +perf_evsel__read_cb_t cb); +int __perf_evsel__read_on_cpu (struct perf_evsel *evsel,int cpu,int thread,bool scale);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 11/12 perf tools: Add per-pkg format file parsing
In reply to Arnaldo Carvalho de MeloFrom: Matt Fleming <[email protected]>
The .per-pkg file indicates that all but one value per socket should be discarded. Adding support to check up this file and set event flag accordingly.
This patch is part of Matt's original patch:
http://marc.info/?l=linux-kernel&m=141527675002139&w=2 only the file parsing part, the rest is solved differently.
--- tools/perf/util/evsel.h | 1 + tools/perf/util/parse-events.c | 1 + tools/perf/util/pmu.c | 27 +++++++++++++++++++++++++++ tools/perf/util/pmu.h | 2 ++ 4 files changed, 31 insertions(+)
tools/perf/util/evsel.h +1 -0
@@ -91,6 +91,7 @@ struct perf_evsel {bool immediate;bool system_wide;bool tracking; +bool per_pkg;/* parse modifier helper */ int exclude_GH;int nr_members;
tools/perf/util/parse-events.c +1 -0
@@ -681,6 +681,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx,if (evsel) { evsel->unit = info.unit; evsel->scale = info.scale; + evsel->per_pkg = info.per_pkg; }return evsel ?0 : -ENOMEM ;
tools/perf/util/pmu.c +27 -0
@@ -163,6 +163,24 @@ error:return -1 ; } +static int +perf_pmu__parse_per_pkg (struct perf_pmu_alias *alias,char *dir,char *name) +{ +char path[PATH_MAX ]; +int fd; + +snprintf (path,PATH_MAX ,"%s/%s.per-pkg" , dir, name); + + fd =open (path,O_RDONLY ); +if (fd ==-1 ) +return -1 ; + +close (fd); + + alias->per_pkg = true; +return 0 ; +} +static int perf_pmu__new_alias (struct list_head *list,char *dir,char *name,FILE *file) {struct perf_pmu_alias *alias;
@@ -181,6 +199,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FIINIT_LIST_HEAD (&alias->terms); alias->scale =1.0 ; alias->unit[0 ] ='\0' ; + alias->per_pkg = false; ret =parse_events_terms (&alias->terms, buf);if (ret) {
@@ -194,6 +213,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI*/ perf_pmu__parse_unit (alias, dir, name);perf_pmu__parse_scale (alias, dir, name); +perf_pmu__parse_per_pkg (alias, dir, name);list_add_tail (&alias->list, list);
@@ -209,6 +229,8 @@ static inline bool pmu_alias_info_file(char *name)return true;if (len >6 && !strcmp (name + len -6 ,".scale" ))return true; +if (len >8 && !strcmp (name + len -8 ,".per-pkg" )) +return true;return false; }
@@ -649,6 +671,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,struct perf_pmu_alias *alias;int ret; + info->per_pkg = false; +/* * Mark unit and scale as not set * (different from default values, see below)
@@ -668,6 +692,9 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,if (ret)return ret; +if (alias->per_pkg) + info->per_pkg = true; +list_del (&term->list);free (term); }
tools/perf/util/pmu.h +2 -0
@@ -29,6 +29,7 @@ struct perf_pmu {struct perf_pmu_info {const char *unit;double scale; +bool per_pkg; };#define UNIT_MAX_LEN 31/* max length for event unit name */
@@ -39,6 +40,7 @@ struct perf_pmu_alias {struct list_head list;/* ELEM */ char unit[UNIT_MAX_LEN +1 ];double scale; +bool per_pkg; };struct perf_pmu *perf_pmu__find (const char *name);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 12/12 perf tools: Add snapshot format file parsing
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
The .snapshot file indicates that the provided event value is a snapshot value and we have to bypass the delta computation logic.
Adding support to check up this file and set event flag accordingly.
--- tools/perf/util/evsel.h | 1 + tools/perf/util/parse-events.c | 1 + tools/perf/util/pmu.c | 47 ++++++++++++++++++++++++++++++++---------- tools/perf/util/pmu.h | 2 ++ 4 files changed, 40 insertions(+), 11 deletions(-)
tools/perf/util/evsel.h +1 -0
@@ -73,6 +73,7 @@ struct perf_evsel {char *name;double scale;const char *unit; +bool snapshot;struct event_format *tp_format;union {void *priv;
tools/perf/util/parse-events.c +1 -0
@@ -682,6 +682,7 @@ int parse_events_add_pmu(struct list_head *list, int *idx, evsel->unit = info.unit; evsel->scale = info.scale; evsel->per_pkg = info.per_pkg; + evsel->snapshot = info.snapshot; }return evsel ?0 : -ENOMEM ;
tools/perf/util/pmu.c +36 -11
92 lines not on this page · raw message
tools/perf/util/pmu.h +2 -0
@@ -30,6 +30,7 @@ struct perf_pmu_info {const char *unit;double scale;bool per_pkg; +bool snapshot; };#define UNIT_MAX_LEN 31/* max length for event unit name */
@@ -41,6 +42,7 @@ struct perf_pmu_alias {char unit[UNIT_MAX_LEN +1 ];double scale;bool per_pkg; +bool snapshot; };struct perf_pmu *perf_pmu__find (const char *name);
Signature · 1 line
1.9.3