perf/core improvements and fixes
Subsystems (2)
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit 3a99e6db539e53cc9c79282e80f8362b0cb96ac8:
perf bench mem: Prepare the x86-64 build for upstream memcpy_mcsafe() changes (2016-03-09 10:40: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-20160310
for you to fetch changes up to 206cab651d07563d766c7f4cb73f858c5df3dec5:
perf stat: Add --metric-only support for -A (2016-03-10 16:50:47 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Implement 'perf stat --metric-only' (Andi Kleen)
- Fix perf script python database export crash (Chris Phlipot)
Infrastructure:
- perf top/report --hierarchy assorted fixes for problems introduced in this perf/core cycle (Namhyung Kim)
- Support '~' operation in libtraceevent (Steven Rosted)
Build fixes:
- Fix bulding of jitdump on opensuse on ubuntu systems when the DWARF devel files are not installed (Arnaldo Carvalho de Melo)
- Do not try building jitdump on unsupported arches (Jiri Olsa)
----------------------------------------------------------------
Andi Kleen (3):
perf stat: Document CSV format in manpage
perf stat: Implement --metric-only mode
perf stat: Add --metric-only support for -A
Arnaldo Carvalho de Melo (1):
perf jitdump: DWARF is also needed
Chris Phlipot (1):
perf tools: Fix perf script python database export crash
Jiri Olsa (3):
perf tools: Pass perf_hpp_list all the way through setup_sort_list perf tools: Omit unnecessary cast in perf_pmu__parse_scale perf jitdump: Build only on supported archs
Namhyung Kim (10):
perf tools: Fix hist_entry__filter() for hierarchy
perf tools: Add more sort entry check functions
perf tools: Fix command line filters in hierarchy mode perf tools: Remove hist_entry->fmt field
perf hists browser: Cleanup hist_browser__fprintf_hierarchy_entry() perf tools: Remove nr_sort_keys field
perf tools: Recalc total periods using top-level entries in hierarchy perf tools: Add sort__has_comm variable
perf hists browser: Allow thread filtering for comm sort key perf hists browser: Check sort keys before hot key actions
Steven Rostedt (1):
tools lib traceevent: Add '~' operation within arg_num_eval()
tools/lib/traceevent/event-parse.c | 6 + tools/perf/Documentation/perf-stat.txt | 27 ++++ tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm64/Makefile | 1 + tools/perf/arch/powerpc/Makefile | 1 + tools/perf/arch/x86/Makefile | 1 + tools/perf/builtin-inject.c | 12 +- tools/perf/builtin-stat.c | 244 +++++++++++++++++++++++++++++++-- tools/perf/config/Makefile | 7 + tools/perf/ui/browsers/hists.c | 73 ++++++---- tools/perf/ui/hist.c | 3 - tools/perf/util/Build | 3 + tools/perf/util/evsel.h | 6 +- tools/perf/util/hist.c | 144 +++++++++++++++++-- tools/perf/util/hist.h | 6 +- tools/perf/util/pmu.c | 4 +- tools/perf/util/sort.c | 147 +++++++++----------- tools/perf/util/sort.h | 2 +- 18 files changed, 542 insertions(+), 146 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/19 perf jitdump: DWARF is also needed
From: Arnaldo Carvalho de Melo <[email protected]>
While building on a Docker container for ubuntu and installing package by package one ends up with:
MKDIR /tmp/build/util/
CC /tmp/build/util/genelf.o
util/genelf.c:22:19: fatal error: dwarf.h: No such file or directory
#include <dwarf.h>
^ compilation terminated.
mv: cannot stat '/tmp/build/util/.genelf.o.tmp': No such file or directory
Because the jitdump code needs the DWARF related development packages to be installed. So make it dependent on that so that the build can succeed without jitdump support.
--- tools/perf/builtin-inject.c | 10 +++++----- tools/perf/util/Build | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-)
tools/perf/builtin-inject.c +5 -5
@@ -73,7 +73,7 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } -#ifdef HAVE_LIBELF_SUPPORT +#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT )static int perf_event__drop_oe (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -245,7 +245,7 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,return err; } -#ifdef HAVE_LIBELF_SUPPORT +#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) static int perf_event__jit_repipe_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -283,7 +283,7 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool,return err; } -#ifdef HAVE_LIBELF_SUPPORT +#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -795,7 +795,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)"perf inject [<options>]" , NULL }; -#ifndef HAVE_LIBELF_SUPPORT +#if !defined(HAVE_LIBELF_SUPPORT ) || !defined(HAVE_DWARF_SUPPORT )set_option_nobuild (options,'j' ,"jit" ,"NO_LIBELF=1" , true);#endif argc =parse_options (argc, argv, options, inject_usage,0 );
@@ -833,7 +833,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; } -#ifdef HAVE_LIBELF_SUPPORT +#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT )if (inject.jit_mode) { inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap;
tools/perf/util/Build +3 -0
@@ -107,9 +107,12 @@ libperf-y += scripting-engines/ libperf-$(CONFIG_ZLIB) += zlib.o libperf-$(CONFIG_LZMA) += lzma.o libperf-y += demangle-java.o + +ifdef CONFIG_DWARF libperf-$(CONFIG_LIBELF) += jitdump.o libperf-$(CONFIG_LIBELF) += genelf.o libperf-$(CONFIG_LIBELF) += genelf_debug.o +endif CFLAGS_config.o += -DETC_PERFCONFIG="BUILD_STR($(ETC_PERFCONFIG_SQ))" # avoid compiler warnings in 32-bit mode
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 2/19 perf tools: Fix perf script python database export crash
In reply to Arnaldo Carvalho de MeloFrom: Chris Phlipot <[email protected]>
Remove the union in evsel so that the database id and priv pointer can be used simultainously without conflicting and crashing.
Detailed Description for the fixed bug follows:
perf script crashes with a segmentation fault on user space tool version 4.5.rc7.ge2857b when using the python database export API. It works properly in 4.4 and prior versions.
the crash fist appeared in:
cfc8874a4859 ("perf script: Process cpu/threads maps")
How to reproduce the bug:
Remove any temporary files left over from a previous crash (if you have already attemped to reproduce the bug):
$ rm -r test_db-perf-data $ dropdb test_db
$ perf record timeout 1 yes >/dev/null $ perf script -s scripts/python/export-to-postgresql.py test_db
Stack Trace:
Program received signal SIGSEGV, Segmentation fault. __GI___libc_free (mem=0x1) at malloc.c:2929
2929 malloc.c: No such file or directory.
(gdb) bt
at util/stat.c:122
argv=<optimized out>, prefix=<optimized out>) at builtin-script.c:2231
argc=argc@entry=4, argv=argv@entry=0x7fffffffdf70) at perf.c:390
at perf.c:451--- tools/perf/util/evsel.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
tools/perf/util/evsel.h +2 -4
@@ -93,10 +93,8 @@ struct perf_evsel {const char *unit;struct event_format *tp_format;off_t id_offset; -union { -void *priv; -u64 db_id; - }; +void *priv; +u64 db_id;struct cgroup_sel *cgrp;void *handler;struct cpu_map *cpus;
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 3/19 perf tools: Pass perf_hpp_list all the way through setup_sort_list
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Pass perf_hpp_list all the way through setup_sort_list so that the sort entry can be added on the arbitrary list.
--- tools/perf/util/sort.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-)
tools/perf/util/sort.c +26 -18
@@ -1614,19 +1614,21 @@ int hist_entry__filter(struct hist_entry *he, int type, const void *arg)return hse->se->se_filter (he, type, arg); } -static int __sort_dimension__add_hpp_sort (struct sort_dimension *sd,int level) +static int __sort_dimension__add_hpp_sort (struct sort_dimension *sd, +struct perf_hpp_list *list, +int level) {struct hpp_sort_entry *hse =__sort_dimension__alloc_hpp (sd, level);if (hse ==NULL )return -1 ; -perf_hpp__register_sort_field (&hse->hpp); +perf_hpp_list__register_sort_field (list, &hse->hpp);return 0 ; } -static int __sort_dimension__add_hpp_output (struct perf_hpp_list *list, -struct sort_dimension *sd) +static int __sort_dimension__add_hpp_output (struct sort_dimension *sd, +struct perf_hpp_list *list) {struct hpp_sort_entry *hse =__sort_dimension__alloc_hpp (sd,0 );
@@ -2147,12 +2149,14 @@ out:return ret; } -static int __sort_dimension__add (struct sort_dimension *sd,int level) +static int __sort_dimension__add (struct sort_dimension *sd, +struct perf_hpp_list *list, +int level) {if (sd->taken)return 0 ; -if (__sort_dimension__add_hpp_sort (sd, level) <0 ) +if (__sort_dimension__add_hpp_sort (sd, list, level) <0 )return -1 ;if (sd->entry->se_collapse)
@@ -2163,7 +2167,9 @@ static int __sort_dimension__add(struct sort_dimension *sd, int level)return 0 ; } -static int __hpp_dimension__add (struct hpp_dimension *hd,int level) +static int __hpp_dimension__add (struct hpp_dimension *hd, +struct perf_hpp_list *list, +int level) {struct perf_hpp_fmt *fmt;
@@ -2175,7 +2181,7 @@ static int __hpp_dimension__add(struct hpp_dimension *hd, int level)return -1 ; hd->taken =1 ; -perf_hpp__register_sort_field (fmt); +perf_hpp_list__register_sort_field (list, fmt);return 0 ; }
@@ -2185,7 +2191,7 @@ static int __sort_dimension__add_output(struct perf_hpp_list *list,if (sd->taken)return 0 ; -if (__sort_dimension__add_hpp_output (list, sd) <0 ) +if (__sort_dimension__add_hpp_output (sd, list) <0 )return -1 ; sd->taken =1 ;
@@ -2215,7 +2221,8 @@ int hpp_dimension__add_output(unsigned col)return __hpp_dimension__add_output (&perf_hpp_list, &hpp_sort_dimensions[col]); } -static int sort_dimension__add (const char *tok,struct perf_evlist *evlist, +static int sort_dimension__add (struct perf_hpp_list *list,const char *tok, +struct perf_evlist *evlist__maybe_unused ,int level) {unsigned int i;
@@ -2255,7 +2262,7 @@ static int sort_dimension__add(const char *tok, struct perf_evlist *evlist, sort__has_thread =1 ; } -return __sort_dimension__add (sd, level); +return __sort_dimension__add (sd, list, level); }for (i =0 ; i <ARRAY_SIZE (hpp_sort_dimensions); i++) {
@@ -2264,7 +2271,7 @@ static int sort_dimension__add(const char *tok, struct perf_evlist *evlist,if (strncasecmp (tok, hd->name,strlen (tok)))continue ; -return __hpp_dimension__add (hd, level); +return __hpp_dimension__add (hd, list, level); }for (i =0 ; i <ARRAY_SIZE (bstack_sort_dimensions); i++) {
@@ -2279,7 +2286,7 @@ static int sort_dimension__add(const char *tok, struct perf_evlist *evlist,if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) sort__has_sym =1 ; -__sort_dimension__add (sd, level); +__sort_dimension__add (sd, list, level);return 0 ; }
@@ -2295,7 +2302,7 @@ static int sort_dimension__add(const char *tok, struct perf_evlist *evlist,if (sd->entry == &sort_mem_daddr_sym) sort__has_sym =1 ; -__sort_dimension__add (sd, level); +__sort_dimension__add (sd, list, level);return 0 ; }
@@ -2305,7 +2312,8 @@ static int sort_dimension__add(const char *tok, struct perf_evlist *evlist,return -ESRCH ; } -static int setup_sort_list (char *str,struct perf_evlist *evlist) +static int setup_sort_list (struct perf_hpp_list *list,char *str, +struct perf_evlist *evlist) {char *tmp, *tok;int ret =0 ;
@@ -2332,7 +2340,7 @@ static int setup_sort_list(char *str, struct perf_evlist *evlist) }if (*tok) { - ret =sort_dimension__add (tok, evlist, level); + ret =sort_dimension__add (list, tok, evlist, level);if (ret == -EINVAL ) {error ("Invalid --sort key: `%s'" , tok);break ;
@@ -2480,7 +2488,7 @@ static int __setup_sorting(struct perf_evlist *evlist) } } - ret =setup_sort_list (str, evlist); + ret =setup_sort_list (&perf_hpp_list, str, evlist);free (str);return ret;
@@ -2725,7 +2733,7 @@ int setup_sorting(struct perf_evlist *evlist)return err;if (parent_pattern != default_parent_pattern) { - err =sort_dimension__add ("parent" , evlist,-1 ); + err =sort_dimension__add (&perf_hpp_list,"parent" , evlist,-1 );if (err <0 )return err; }
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 4/19 perf tools: Omit unnecessary cast in perf_pmu__parse_scale
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
There's no need to use a const char pointer, we can used char pointer from the beginning and omit the unnecessary cast.
--- tools/perf/util/pmu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/util/pmu.c +2 -2
@@ -98,7 +98,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char *char scale[128 ];int fd, ret =-1 ;char path[PATH_MAX ]; -const char *lc; +char *lc;snprintf (path,PATH_MAX ,"%s/%s.scale" , dir, name);
@@ -146,7 +146,7 @@ static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, char *dir, char */* restore locale */ setlocale (LC_NUMERIC , lc); -free ((char *) lc); +free (lc); ret =0 ; error:
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 5/19 tools lib traceevent: Add '~' operation within arg_num_eval()
In reply to Arnaldo Carvalho de MeloFrom: Steven Rostedt <[email protected]>
When evaluating values for print flags, if the value included a '~' operator, the parsing would fail. This broke kmalloc's parsing of:
__print_flags(REC->gfp_flags, "|", {(unsigned long)((((((( gfp_t)(0x400000u|0x2000000u)) | (( gfp_t)0x40u) | (( gfp_t)0x80u) | (( gfp_t)0x20000u)) | (( gfp_t)0x02u)) | (( gfp_t)0x08u)) | (( gfp_t)0x4000u) | (( gfp_t)0x10000u) | (( gfp_t)0x1000u) | (( gfp_t)0x200u)) & ~(( gfp_t)0x2000000u))
^
|
here--- tools/lib/traceevent/event-parse.c | 6 ++++++ 1 file changed, 6 insertions(+)
tools/lib/traceevent/event-parse.c +6 -0
@@ -2398,6 +2398,12 @@ static int arg_num_eval(struct print_arg *arg, long long *val)break ; *val = left + right;break ; +case '~' : + ret =arg_num_eval (arg->op.right, &right); +if (!ret) +break ; + *val = ~right; +break ;default :do_warning ("unknown op '%s'" , arg->op.op); ret =0 ;
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 6/19 perf jitdump: Build only on supported archs
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Build jitdump only on architectures defined in util/genelf.h file, to avoid breaking the build on such arches.
--- tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm64/Makefile | 1 + tools/perf/arch/powerpc/Makefile | 1 + tools/perf/arch/x86/Makefile | 1 + tools/perf/builtin-inject.c | 12 +++++++----- tools/perf/config/Makefile | 7 +++++++ tools/perf/util/Build | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-)
tools/perf/arch/arm/Makefile +1 -0
@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1
tools/perf/arch/arm64/Makefile +1 -0
@@ -1,3 +1,4 @@ ifndef NO_DWARF PERF_HAVE_DWARF_REGS := 1 endif +PERF_HAVE_JITDUMP := 1
tools/perf/arch/powerpc/Makefile +1 -0
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 +PERF_HAVE_JITDUMP := 1
tools/perf/arch/x86/Makefile +1 -0
@@ -3,3 +3,4 @@ PERF_HAVE_DWARF_REGS := 1 endif HAVE_KVM_STAT_SUPPORT := 1 PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 +PERF_HAVE_JITDUMP := 1
tools/perf/builtin-inject.c +7 -5
@@ -73,7 +73,7 @@ static int perf_event__repipe_oe_synth(struct perf_tool *tool,return perf_event__repipe_synth (tool, event); } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__drop_oe (struct perf_tool *tool__maybe_unused ,union perf_event *event__maybe_unused ,struct ordered_events *oe__maybe_unused )
@@ -245,7 +245,7 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__jit_repipe_mmap(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -283,7 +283,7 @@ static int perf_event__repipe_mmap2(struct perf_tool *tool,return err; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample,
@@ -778,7 +778,9 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, "Merge sched-stat and sched-switch for getting events " "where and how long tasks slept"), +#ifdef HAVE_JITDUMP OPT_BOOLEAN ('j' ,"jit" , &inject.jit_mode,"merge jitdump files into perf.data file" ), +#endifOPT_INCR ('v' ,"verbose" , &verbose,"be more verbose (show build ids, etc)" ), OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
@@ -795,7 +797,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)"perf inject [<options>]" , NULL }; -#if !defined(HAVE_LIBELF_SUPPORT ) || !defined(HAVE_DWARF_SUPPORT ) +#ifndef HAVE_JITDUMP set_option_nobuild (options,'j' ,"jit" ,"NO_LIBELF=1" , true);#endif argc =parse_options (argc, argv, options, inject_usage,0 );
@@ -833,7 +835,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) inject.tool.ordered_events = true; inject.tool.ordering_requires_timestamps = true; } -#if defined(HAVE_LIBELF_SUPPORT ) && defined(HAVE_DWARF_SUPPORT ) +#ifdef HAVE_JITDUMP if (inject.jit_mode) { inject.tool.mmap2 = perf_event__jit_repipe_mmap2; inject.tool.mmap = perf_event__jit_repipe_mmap;
tools/perf/config/Makefile +7 -0
@@ -328,6 +328,13 @@ ifndef NO_LIBELF endif # NO_LIBBPF endif # NO_LIBELF +ifdef PERF_HAVE_JITDUMP + ifndef NO_DWARF + $(call detected,CONFIG_JITDUMP) + CFLAGS += -DHAVE_JITDUMP + endif +endif + ifeq ($(ARCH),powerpc) ifndef NO_DWARF CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
tools/perf/util/Build +1 -1
@@ -108,7 +108,7 @@ libperf-$(CONFIG_ZLIB) += zlib.o libperf-$(CONFIG_LZMA) += lzma.o libperf-y += demangle-java.o -ifdef CONFIG_DWARF +ifdef CONFIG_JITDUMP libperf-$(CONFIG_LIBELF) += jitdump.o libperf-$(CONFIG_LIBELF) += genelf.o libperf-$(CONFIG_LIBELF) += genelf_debug.o
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 7/19 perf tools: Fix hist_entry__filter() for hierarchy
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When hierarchy mode is enabled each output format is in a separate hpp list. So when applying a filter it should check all formats in the list. Currently it only checks a single ->fmt field which was not set properly.
--- tools/perf/util/sort.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
tools/perf/util/sort.c +21 -7
@@ -1602,16 +1602,30 @@ int hist_entry__filter(struct hist_entry *he, int type, const void *arg) {struct perf_hpp_fmt *fmt;struct hpp_sort_entry *hse; +int ret =-1 ; +int r; - fmt = he->fmt; -if (fmt ==NULL || !perf_hpp__is_sort_entry (fmt)) -return -1 ; +perf_hpp_list__for_each_format (he->hpp_list, fmt) { +if (!perf_hpp__is_sort_entry (fmt)) +continue ; - hse = container_of(fmt, struct hpp_sort_entry, hpp); -if (hse->se->se_filter ==NULL ) -return -1 ; + hse = container_of(fmt, struct hpp_sort_entry, hpp); +if (hse->se->se_filter ==NULL ) +continue ; -return hse->se->se_filter (he, type, arg); +/* +* hist entry is filtered if any of sort key in the hpp list +* is applied. But it should skip non-matched filter types. +*/ + r = hse->se->se_filter (he, type, arg); +if (r >=0 ) { +if (ret <0 ) + ret =0 ; + ret |= r; + } + } + +return ret; } static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd,
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 8/19 perf tools: Add more sort entry check functions
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Those functions are for checkinf if a given perf_hpp_fmt is a filter-related sort entry. With hierarchy mode, it needs to check filters on the hist entries with its own hpp format list.
--- tools/perf/util/hist.h | 4 ++++ tools/perf/util/sort.c | 50 +++++++++++++++++++------------------------------- 2 files changed, 23 insertions(+), 31 deletions(-)
tools/perf/util/hist.h +4 -0
@@ -318,6 +318,10 @@ bool perf_hpp__defined_dynamic_entry(struct perf_hpp_fmt *fmt, struct hists *hisbool perf_hpp__is_trace_entry (struct perf_hpp_fmt *fmt);bool perf_hpp__is_srcline_entry (struct perf_hpp_fmt *fmt);bool perf_hpp__is_srcfile_entry (struct perf_hpp_fmt *fmt); +bool perf_hpp__is_thread_entry (struct perf_hpp_fmt *fmt); +bool perf_hpp__is_comm_entry (struct perf_hpp_fmt *fmt); +bool perf_hpp__is_dso_entry (struct perf_hpp_fmt *fmt); +bool perf_hpp__is_sym_entry (struct perf_hpp_fmt *fmt);struct perf_hpp_fmt *perf_hpp_fmt__dup (struct perf_hpp_fmt *fmt);
tools/perf/util/sort.c +19 -31
57 lines not on this page · raw message
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 9/19 perf tools: Fix command line filters in hierarchy mode
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When a command-line filter is applied in hierarchy mode, output is broken especially when filtering on lower level. The higher level entries doesn't show up so it's hard to see the results.
Also it needs to handle multi sort keys in a single hierarchy level.
Before:
$ perf report --hierarchy -s 'cpu,{dso,comm}' --comms swapper --stdio
...
# Overhead CPU / Shared Object+Command
# ........... ...........................
#
13.79% [kernel.vmlinux] swapper
31.71% 000
13.80% [kernel.vmlinux] swapper
0.43% [e1000e] swapper
11.89% [kernel.vmlinux] swapper
9.18% [kernel.vmlinux] swapperAfter:
# Overhead CPU / Shared Object+Command
# ........... ...............................
#
33.09% 003
13.79% [kernel.vmlinux] swapper
31.71% 000
13.80% [kernel.vmlinux] swapper
0.43% [e1000e] swapper
21.90% 002
11.89% [kernel.vmlinux] swapper
13.30% 001
9.18% [kernel.vmlinux] swapper--- tools/perf/util/hist.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 3 deletions(-)
tools/perf/util/hist.c +97 -3
@@ -1087,10 +1087,103 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,*/ static void hists__apply_filters (struct hists *hists,struct hist_entry *he); +static void hists__remove_entry_filter (struct hists *hists,struct hist_entry *he, +enum hist_filter type); + +typedef bool (*fmt_chk_fn )(struct perf_hpp_fmt *fmt); + +static bool check_thread_entry (struct perf_hpp_fmt *fmt) +{ +return perf_hpp__is_thread_entry (fmt) ||perf_hpp__is_comm_entry (fmt); +} + +static void hist_entry__check_and_remove_filter (struct hist_entry *he, +enum hist_filter type, +fmt_chk_fn check) +{ +struct perf_hpp_fmt *fmt; +bool type_match = false; +struct hist_entry *parent = he->parent_he; + +switch (type) { +case HIST_FILTER__THREAD : +if (symbol_conf.comm_list ==NULL && + symbol_conf.pid_list ==NULL && + symbol_conf.tid_list ==NULL ) +return ; +break ; +case HIST_FILTER__DSO : +if (symbol_conf.dso_list ==NULL ) +return ; +break ; +case HIST_FILTER__SYMBOL : +if (symbol_conf.sym_list ==NULL ) +return ; +break ; +case HIST_FILTER__PARENT : +case HIST_FILTER__GUEST : +case HIST_FILTER__HOST : +case HIST_FILTER__SOCKET : +default : +return ; + } + +/* if it's filtered by own fmt, it has to have filter bits */ +perf_hpp_list__for_each_format (he->hpp_list, fmt) { +if (check (fmt)) { + type_match = true; +break ; + } + } + +if (type_match) { +/* +* If the filter is for current level entry, propagate +* filter marker to parents. The marker bit was +* already set by default so it only needs to clear +* non-filtered entries. +*/ +if (!(he->filtered & (1 << type))) { +while (parent) { + parent->filtered &= ~(1 << type); + parent = parent->parent_he; + } + } + }else { +/* +* If current entry doesn't have matching formats, set +* filter marker for upper level entries. it will be +* cleared if its lower level entries is not filtered. +* +* For lower-level entries, it inherits parent's +* filter bit so that lower level entries of a +* non-filtered entry won't set the filter marker. +*/ +if (parent ==NULL ) + he->filtered |= (1 << type); +else + he->filtered |= (parent->filtered & (1 << type)); + } +} + +static void hist_entry__apply_hierarchy_filters (struct hist_entry *he) +{ +hist_entry__check_and_remove_filter (he,HIST_FILTER__THREAD , + check_thread_entry); + +hist_entry__check_and_remove_filter (he,HIST_FILTER__DSO , + perf_hpp__is_dso_entry); + +hist_entry__check_and_remove_filter (he,HIST_FILTER__SYMBOL , + perf_hpp__is_sym_entry); + +hists__apply_filters (he->hists, he); +}static struct hist_entry *hierarchy_insert_entry (struct hists *hists,struct rb_root *root,struct hist_entry *he, +struct hist_entry *parent_he,struct perf_hpp_list *hpp_list) {struct rb_node **p = &root->rb_node;
@@ -1125,11 +1218,13 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists,if (new ==NULL )return NULL ; -hists__apply_filters (hists, new); hists->nr_entries++;/* save related format list for output */ new->hpp_list = hpp_list; + new->parent_he = parent_he; + +hist_entry__apply_hierarchy_filters (new);/* some fields are now passed to 'new' */ perf_hpp_list__for_each_sort_list (hpp_list, fmt) {
@@ -1170,14 +1265,13 @@ static int hists__hierarchy_insert_entry(struct hists *hists,continue ;/* insert copy of 'he' for each fmt into the hierarchy */ - new_he =hierarchy_insert_entry (hists, root, he, &node->hpp); + new_he =hierarchy_insert_entry (hists, root, he, parent, &node->hpp);if (new_he ==NULL ) { ret =-1 ;break ; } root = &new_he->hroot_in; - new_he->parent_he = parent; new_he->depth = depth++; parent = new_he; }
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 10/19 perf tools: Remove hist_entry->fmt field
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
It's not used anymore and the output format is accessed by the hpp_list pointer instead when hierarchy is enabled. Let's get rid of it.
--- tools/perf/util/sort.h | 1 - 1 file changed, 1 deletion(-)
tools/perf/util/sort.h +0 -1
@@ -129,7 +129,6 @@ struct hist_entry {void *raw_data;u32 raw_size;void *trace_output; -struct perf_hpp_fmt *fmt;struct perf_hpp_list *hpp_list;struct hist_entry *parent_he;union {
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 11/19 perf hists browser: Cleanup hist_browser__fprintf_hierarchy_entry()
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The hist_browser__fprintf_hierarchy_entry() if to dump current output into a file so it needs to be sync-ed with the corresponding function hist_browser__show_hierarchy_entry(). So use hists->nr_hpp_node to indent width and use first fmt_node to print overhead columns instead of checking whether it's a sort entry (or dynamic entry).
--- tools/perf/ui/browsers/hists.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-)
tools/perf/ui/browsers/hists.c +8 -14
@@ -1928,8 +1928,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,static int hist_browser__fprintf_hierarchy_entry (struct hist_browser *browser,struct hist_entry *he, -FILE *fp,int level, -int nr_sort_keys) +FILE *fp,int level) {char s[8192 ];int printed =0 ;
@@ -1939,23 +1938,20 @@ static int hist_browser__fprintf_hierarchy_entry(struct hist_browser *browser, .size = sizeof(s), };struct perf_hpp_fmt *fmt; +struct perf_hpp_list_node *fmt_node;bool first = true;int ret; -int hierarchy_indent = nr_sort_keys *HIERARCHY_INDENT ; +int hierarchy_indent = (he->hists->nr_hpp_node -2 ) *HIERARCHY_INDENT ; printed =fprintf (fp,"%*s" , level *HIERARCHY_INDENT ,"" ); folded_sign =hist_entry__folded (he); printed +=fprintf (fp,"%c" , folded_sign); -hists__for_each_format (he->hists, fmt) { -if (perf_hpp__should_skip (fmt, he->hists)) -continue ; - -if (perf_hpp__is_sort_entry (fmt) || -perf_hpp__is_dynamic_entry (fmt)) -break ; - +/* the first hpp_list_node is for overhead columns */ + fmt_node =list_first_entry (&he->hists->hpp_formats, + struct perf_hpp_list_node, list); +perf_hpp_list__for_each_format (&fmt_node->hpp, fmt) {if (!first) { ret =scnprintf (hpp.buf, hpp.size," " );advance_hpp (&hpp, ret);
@@ -1992,7 +1988,6 @@ static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp)struct rb_node *nd =hists__filter_entries (rb_first (browser->b.entries), browser->min_pcnt);int printed =0 ; -int nr_sort = browser->hists->nr_sort_keys;while (nd) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
@@ -2000,8 +1995,7 @@ static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp)if (symbol_conf.report_hierarchy) { printed +=hist_browser__fprintf_hierarchy_entry (browser, h, fp, - h->depth, - nr_sort); + h->depth); }else { printed +=hist_browser__fprintf_entry (browser, h, fp); }
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 12/19 perf tools: Remove nr_sort_keys field
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The nr_sort_keys field is to carry the number of sort entries in a hpp_list or hists to determine the depth of indentation of a hist entry. As it's only used in hierarchy mode and now we have used nr_hpp_node for this reason, there's no need to keep it anymore. Let's get rid of it.
--- tools/perf/ui/hist.c | 3 --- tools/perf/util/hist.h | 2 -- tools/perf/util/sort.c | 26 -------------------------- 3 files changed, 31 deletions(-)
tools/perf/ui/hist.c +0 -3
@@ -515,9 +515,6 @@ void perf_hpp_list__column_register(struct perf_hpp_list *list,void perf_hpp_list__register_sort_field (struct perf_hpp_list *list,struct perf_hpp_fmt *format) { -if (perf_hpp__is_sort_entry (format) ||perf_hpp__is_dynamic_entry (format)) - list->nr_sort_keys++; -list_add_tail (&format->sort_list, &list->sorts); }
tools/perf/util/hist.h +0 -2
@@ -79,7 +79,6 @@ struct hists {int socket_filter;struct perf_hpp_list *hpp_list;struct list_head hpp_formats; -int nr_sort_keys;int nr_hpp_node; };
@@ -241,7 +240,6 @@ struct perf_hpp_fmt {struct perf_hpp_list {struct list_head fields;struct list_head sorts; -int nr_sort_keys; };extern struct perf_hpp_list perf_hpp_list;
tools/perf/util/sort.c +0 -26
@@ -2703,29 +2703,6 @@ out:return ret; } -static void evlist__set_hists_nr_sort_keys (struct perf_evlist *evlist) -{ -struct perf_evsel *evsel; - -evlist__for_each (evlist, evsel) { -struct perf_hpp_fmt *fmt; -struct hists *hists =evsel__hists (evsel); - - hists->nr_sort_keys = perf_hpp_list.nr_sort_keys; - -/* -* If dynamic entries were used, it might add multiple -* entries to each evsel for a single field name. Set -* actual number of sort keys for each hists. -*/ -perf_hpp_list__for_each_sort_list (&perf_hpp_list, fmt) { -if (perf_hpp__is_dynamic_entry (fmt) && - !perf_hpp__defined_dynamic_entry (fmt, hists)) - hists->nr_sort_keys--; - } - } -} -int setup_sorting (struct perf_evlist *evlist) {int err;
@@ -2740,9 +2717,6 @@ int setup_sorting(struct perf_evlist *evlist)return err; } -if (evlist !=NULL ) -evlist__set_hists_nr_sort_keys (evlist); -reset_dimensions ();/*
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 13/19 perf tools: Recalc total periods using top-level entries in hierarchy
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When hierarchy mode is enabled, each entry in a hierarchy level shares the period. IOW an upper level entry's period is the sum of lower level entries. Thus perf uses only one of them to calculate the total period of hists. It was lowest-level (leaf) entries but it has a problem when it comes to filters.
If a filter is applied, entries in the same level will be filtered or not. But upper level entries still have period of their sum including filtered one. So total sum of upper level entries will not be same as sum of lower level entries.
This resulted in entries having more than 100% of overhead and it can be produced using perf top with filter(s).
--- tools/perf/util/hist.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-)
tools/perf/util/hist.c +34 -10
@@ -1453,6 +1453,31 @@ void hists__inc_stats(struct hists *hists, struct hist_entry *h) hists->stats.total_period += h->stat.period; } +static void hierarchy_recalc_total_periods (struct hists *hists) +{ +struct rb_node *node; +struct hist_entry *he; + + node =rb_first (&hists->entries); + + hists->stats.total_period =0 ; + hists->stats.total_non_filtered_period =0 ; + +/* +* recalculate total period using top-level entries only +* since lower level entries only see non-filtered entries +* but upper level entries have sum of both entries. +*/ +while (node) { + he = rb_entry(node, struct hist_entry, rb_node); + node =rb_next (node); + + hists->stats.total_period += he->stat.period; +if (!he->filtered) + hists->stats.total_non_filtered_period += he->stat.period; + } +} +static void hierarchy_insert_output_entry (struct rb_root *root,struct hist_entry *he) {
@@ -1518,11 +1543,6 @@ static void hists__hierarchy_output_resort(struct hists *hists,continue ; } -/* only update stat for leaf entries to avoid duplication */ -hists__inc_stats (hists, he); -if (!he->filtered) -hists__calc_col_len (hists, he); -if (!use_callchain)continue ;
@@ -1602,11 +1622,13 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,hists__reset_col_len (hists);if (symbol_conf.report_hierarchy) { -return hists__hierarchy_output_resort (hists, prog, - &hists->entries_collapsed, - &hists->entries, - min_callchain_hits, - use_callchain); +hists__hierarchy_output_resort (hists, prog, + &hists->entries_collapsed, + &hists->entries, + min_callchain_hits, + use_callchain); +hierarchy_recalc_total_periods (hists); +return ; }if (sort__need_collapse)
@@ -1927,6 +1949,8 @@ static void hists__filter_hierarchy(struct hists *hists, int type, const void *a } } +hierarchy_recalc_total_periods (hists); +/* * resort output after applying a new filter since filter in a lower * hierarchy can change periods in a upper hierarchy.
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 14/19 perf tools: Add sort__has_comm variable
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The sort__has_comm variable is to check whether the comm sort key is given. This is necessary to support thread filtering in the TUI hists browser later.
--- tools/perf/util/sort.c | 3 +++ tools/perf/util/sort.h | 1 + 2 files changed, 4 insertions(+)
tools/perf/util/sort.c +3 -0
@@ -27,6 +27,7 @@ int sort__has_sym = 0;int sort__has_dso =0 ;int sort__has_socket =0 ;int sort__has_thread =0 ; +int sort__has_comm =0 ;enum sort_mode sort__mode =SORT_MODE__NORMAL ;/*
@@ -2262,6 +2263,8 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, sort__has_socket =1 ; }else if (sd->entry == &sort_thread) { sort__has_thread =1 ; + }else if (sd->entry == &sort_comm) { + sort__has_comm =1 ; }return __sort_dimension__add (sd, list, level);
tools/perf/util/sort.h +1 -0
@@ -37,6 +37,7 @@ extern int sort__has_parent;extern int sort__has_sym;extern int sort__has_socket;extern int sort__has_thread; +extern int sort__has_comm;extern enum sort_mode sort__mode;extern struct sort_entry sort_comm;extern struct sort_entry sort_dso;
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 15/19 perf hists browser: Allow thread filtering for comm sort key
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The commit 2eafd410e669 ("perf hists browser: Only 'Zoom into thread' only when sort order has 'pid'") disabled thread filtering in hist browser for the default sort key. However the he->thread is still valid even if 'pid' sort key is not given. Only thing it should not use is the pid (or tid) of the thread. So allow to filter by thread when 'comm' sort key is given and show pid only if 'pid' sort key is given.
--- tools/perf/ui/browsers/hists.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-)
tools/perf/ui/browsers/hists.c +32 -10
@@ -2136,11 +2136,18 @@ static int hists__browser_title(struct hists *hists,if (hists->uid_filter_str) printed +=snprintf (bf + printed, size - printed,", UID: %s" , hists->uid_filter_str); -if (thread) - printed +=scnprintf (bf + printed, size - printed, +if (thread) { +if (sort__has_thread) { + printed +=scnprintf (bf + printed, size - printed,", Thread: %s(%d)" , (thread->comm_set ?thread__comm_str (thread) :"" ), thread->tid); + }else { + printed +=scnprintf (bf + printed, size - printed, +", Thread: %s" , + (thread->comm_set ?thread__comm_str (thread) :"" )); + } + }if (dso) printed +=scnprintf (bf + printed, size - printed,", DSO: %s" , dso->short_name);
@@ -2321,9 +2328,15 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act)thread__zput (browser->hists->thread_filter);ui_helpline__pop (); }else { -ui_helpline__fpush ("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"" , - thread->comm_set ?thread__comm_str (thread) :"" , - thread->tid); +if (sort__has_thread) { +ui_helpline__fpush ("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"" , + thread->comm_set ?thread__comm_str (thread) :"" , + thread->tid); + }else { +ui_helpline__fpush ("To zoom out press ESC or ENTER + \"Zoom out of %s thread\"" , + thread->comm_set ?thread__comm_str (thread) :"" ); + } + browser->hists->thread_filter =thread__get (thread);perf_hpp__set_elide (HISTC_THREAD , false);pstack__push (browser->pstack, &browser->hists->thread_filter);
@@ -2338,13 +2351,22 @@ static int add_thread_opt(struct hist_browser *browser, struct popup_action *act, char **optstr, struct thread *thread) { - if (!sort__has_thread || thread == NULL) + int ret; + +if ((!sort__has_thread && !sort__has_comm) || thread ==NULL )return 0 ; - if (asprintf(optstr, "Zoom %s %s(%d) thread", - browser->hists->thread_filter ? "out of" : "into", - thread->comm_set ? thread__comm_str(thread) : "", - thread->tid) < 0) +if (sort__has_thread) { + ret =asprintf (optstr,"Zoom %s %s(%d) thread" , + browser->hists->thread_filter ?"out of" :"into" , + thread->comm_set ?thread__comm_str (thread) :"" , + thread->tid); + }else { + ret =asprintf (optstr,"Zoom %s %s thread" , + browser->hists->thread_filter ?"out of" :"into" , + thread->comm_set ?thread__comm_str (thread) :"" ); + } +if (ret <0 )return 0 ; act->thread = thread;
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 16/19 perf hists browser: Check sort keys before hot key actions
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The context menu in TUI hists browser checks corresponding sort keys when creating the menu item. But hotkey actions lacks these checks so it can filter using incorrect info.
For example, default sort key of 'perf top' doesn't contain 'comm' or 'pid' sort key so each hist entry's thread info is not reliable. Thus it should prohibit using thread filter on 't' key.
--- tools/perf/ui/browsers/hists.c | 9 +++++++++ 1 file changed, 9 insertions(+)
tools/perf/ui/browsers/hists.c +9 -0
@@ -2322,6 +2322,9 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act) {struct thread *thread = act->thread; +if ((!sort__has_thread && !sort__has_comm) || thread ==NULL ) +return 0 ; +if (browser->hists->thread_filter) {pstack__remove (browser->pstack, &browser->hists->thread_filter);perf_hpp__set_elide (HISTC_THREAD , false);
@@ -2379,6 +2382,9 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act) {struct map *map = act->ms.map; +if (!sort__has_dso || map ==NULL ) +return 0 ; +if (browser->hists->dso_filter) {pstack__remove (browser->pstack, &browser->hists->dso_filter);perf_hpp__set_elide (HISTC_DSO , false);
@@ -2530,6 +2536,9 @@ add_exit_opt(struct hist_browser *browser __maybe_unused,static int do_zoom_socket (struct hist_browser *browser,struct popup_action *act) { +if (!sort__has_socket || act->socket <0 ) +return 0 ; +if (browser->hists->socket_filter >-1 ) {pstack__remove (browser->pstack, &browser->hists->socket_filter); browser->hists->socket_filter =-1 ;
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 17/19 perf stat: Document CSV format in manpage
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
With all the recently added fields in the perf stat CSV output we should finally document them in the man page. Do this here.
v2: Fix fields in documentation (Jiri)
v3: fix order of fields again (Jiri)
v4: Change order again.
v5: Document more fields (Jiri)
v6: Move time stamp first
v7: More fixes (Jiri)
--- tools/perf/Documentation/perf-stat.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
tools/perf/Documentation/perf-stat.txt +23 -0
@@ -219,6 +219,29 @@ $ perf stat -- make -j Wall-clock time elapsed: 719.554352 msecs +CSV FORMAT +---------- + +With -x, perf stat is able to output a not-quite-CSV format output +Commas in the output are not put into "". To make it easy to parse +it is recommended to use a different character like -x \; + +The fields are in this order: + + - optional usec time stamp in fractions of second (with -I xxx) + - optional CPU, core, or socket identifier + - optional number of logical CPUs aggregated + - counter value + - unit of the counter value or empty + - event name + - run time of counter + - percentage of measurement time the counter was running + - optional variance if multiple values are collected with -r + - optional metric value + - optional unit of metric + +Additional metrics may be printed with all earlier fields being empty. + SEE ALSO -------- linkperf:perf-top[1], linkperf:perf-list[1]
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 18/19 perf stat: Implement --metric-only mode
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Add a new mode to only print metrics. Sometimes we don't care about the raw values, just want the computed metrics. This allows more compact printing, so with -I each sample is only a single line. This also allows easier plotting and processing with other tools.
The main target is with using --topdown, but it also works with -T and standard perf stat. A few metrics are not supported.
To avoiding having to hardcode all the metrics in the code it uses a two pass approach: first compute dummy metrics and only print the headers in the print_metric callback. Then use the callback to print the actual values.
There are some additional changes in the stat printout code to handle all metrics being on a single line.
One issue is that the column code doesn't know in advance what events are not supported by the CPU, and it would be hard to find out as this could change based on dynamic conditions. That causes empty columns in some cases.
The output can be fairly wide, often you may need more than 80 columns.
Example:
% perf stat -a -I 1000 --metric-only
1.001452803 frontend cycles idle insn per cycle stalled cycles per insn branch-misses of all branches
1.001452803 158.91% 0.66 2.39 2.92%
2.002192321 180.63% 0.76 2.08 2.96%
3.003088282 150.59% 0.62 2.57 2.84%
4.004369835 196.20% 0.98 1.62 3.79%
5.005227314 231.98% 0.84 1.90 4.71%v2: Lots of updates.
v3: Use slightly narrower columns
v4: Add comment
--- tools/perf/Documentation/perf-stat.txt | 4 + tools/perf/builtin-stat.c | 211 +++++++++++++++++++++++++++++++-- 2 files changed, 205 insertions(+), 10 deletions(-)
tools/perf/Documentation/perf-stat.txt +4 -0
@@ -147,6 +147,10 @@ Print count deltas every N milliseconds (minimum: 10ms) The overhead percentage could be high in some cases, for instance with small, sub 100ms intervals. Use with caution. example: 'perf stat -I 1000 -e cycles -a sleep 5' +--metric-only:: +Only print computed metrics. Print them in a single line. +Don't show any raw values. Not supported with -A or --per-thread. + --per-socket:: Aggregate counts per processor socket for system-wide mode measurements. This is a useful mode to detect imbalance between sockets. To enable this mode,
tools/perf/builtin-stat.c +201 -10
325 lines not on this page · raw message
Signature · 1 line
2.5.0
Arnaldo Carvalho de Melo
maintainerPATCH 19/19 perf stat: Add --metric-only support for -A
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Add metric only support for -A too. This requires a new print function that prints the metrics in the right order.
v2: Fix manpage
v3: Simplify nrcpus computation
--- tools/perf/Documentation/perf-stat.txt | 2 +- tools/perf/builtin-stat.c | 45 ++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 9 deletions(-)
tools/perf/Documentation/perf-stat.txt +1 -1
@@ -149,7 +149,7 @@ The overhead percentage could be high in some cases, for instance with small, su --metric-only:: Only print computed metrics. Print them in a single line. -Don't show any raw values. Not supported with -A or --per-thread. +Don't show any raw values. Not supported with --per-thread. --per-socket:: Aggregate counts per processor socket for system-wide mode measurements. This
tools/perf/builtin-stat.c +37 -8
66 lines not on this page · raw message
Signature · 1 line
2.5.0
Quoted 86 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
3a99e6db539e53cc9c79282e80f8362b0cb96ac8:perf bench mem: Prepare the x86-64 build for upstream
memcpy_mcsafe()changes (2016-03-09 10:40:01 +0100)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-20160310for you to fetch changes up to
206cab651d07563d766c7f4cb73f858c5df3dec5:perf stat: Add --metric-only support for -A (2016-03-10 16:50:47 -0300)----------------------------------------------------------------
perf/core improvements and fixes:User visible:
- Implement 'perf stat --metric-only' (Andi Kleen)
- Fix perf script python database export crash (Chris Phlipot)
Infrastructure:
- perf top/report --hierarchy assorted fixes for problems introduced in this perf/core cycle (Namhyung Kim)
- Support '~' operation in libtraceevent (Steven Rosted)
Build fixes:
- Fix bulding of jitdump on opensuse on ubuntu systems when the DWARF devel files are not installed (Arnaldo Carvalho de Melo)
- Do not try building jitdump on unsupported arches (Jiri Olsa)
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Andi Kleen (3):
perf stat: Document CSV format in manpage
perf stat: Implement --metric-only mode
perf stat: Add --metric-only support for -AArnaldo Carvalho de Melo (1):
perf jitdump: DWARF is also neededChris Phlipot (1):
perf tools: Fix perf script python database export crashJiri Olsa (3):
perf tools: Passperf_hpp_listall the way throughsetup_sort_listperf tools: Omit unnecessary cast inperf_pmu__parse_scaleperf jitdump: Build only on supported archsNamhyung Kim (10):
perf tools: Fixhist_entry__filter()for hierarchy
perf tools: Add more sort entry check functions
perf tools: Fix command line filters in hierarchy mode perf tools: Removehist_entry->fmtfield
perf hists browser: Cleanuphist_browser__fprintf_hierarchy_entry()perf tools: Removenr_sort_keysfield
perf tools: Recalc total periods using top-level entries in hierarchy perf tools: Addsort__has_commvariable
perf hists browser: Allow thread filtering for comm sort key perf hists browser: Check sort keys before hot key actionsSteven Rostedt (1):
tools lib traceevent: Add '~' operation withinarg_num_eval()tools/lib/traceevent/event-parse.c | 6 + tools/perf/Documentation/perf-stat.txt | 27 ++++ tools/perf/arch/arm/Makefile | 1 + tools/perf/arch/arm64/Makefile | 1 + tools/perf/arch/powerpc/Makefile | 1 + tools/perf/arch/x86/Makefile | 1 + tools/perf/builtin-inject.c | 12 +- tools/perf/builtin-stat.c | 244 +++++++++++++++++++++++++++++++-- tools/perf/config/Makefile | 7 + tools/perf/ui/browsers/hists.c | 73 ++++++---- tools/perf/ui/hist.c | 3 -
Quoted 8 lines
tools/perf/util/Build | 3 + tools/perf/util/evsel.h | 6 +- tools/perf/util/hist.c | 144 +++++++++++++++++-- tools/perf/util/hist.h | 6 +- tools/perf/util/pmu.c | 4 +- tools/perf/util/sort.c | 147 +++++++++----------- tools/perf/util/sort.h | 2 +- 18 files changed, 542 insertions(+), 146 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo