perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit b130a699c07155a1d6ef7d971a5f3bf0e3818d5a:
Merge tag 'perf-urgent-for-mingo-4.14-20170912' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent (2017-09-13 09:25:10 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-4.15-20170922
for you to fetch changes up to 0a7c74eae307894c6c95316c382f118aef8481e8:
perf tools: Provide mutex wrappers for pthreads rwlocks (2017-09-21 13:28:06 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
- Support direct --user-regs arguments in 'perf record', previously the only way to sample PERF_SAMPLE_REGS_USER was implicitly selecting it when recording callchains (Andi Kleen)
- Support showing sampled user regs in 'perf script' (Andi Kleen)
- Introduce the concept of weak groups in 'perf stat': try to set up a group, but if it's not schedulable fallback to not using a group. That gives us the best of both worlds: groups if they work, but still a usable fallback if they don't. E.g: (Andi Kleen)
% perf stat -e '{branches,branch-misses,l1d.replacement,l2_lines_in.all,l2_rqsts.all_code_rd}:W' -a sleep 1
125,366,055 branches (80.02%)
9,208,402 branch-misses # 7.35% of all branches (80.01%)
24,560,249 l1d.replacement (80.00%)
43,174,971 l2_lines_in.all (80.05%)
31,891,457 l2_rqsts.all_code_rd (79.92%)- Support metrics in 'stat' and 'list'. A metric is a formula that uses multiple events to compute a higher level result (e.g. IPC). (Andi Kleen)
- Add Intel processors vendor event metrics JSON files (Andi Kleen)
- Add 'pid' and 'tid' options to 'perf sched timehist' (David Ahern)
- Generate 'behavior' string table from kernel headers, helps getting new parameters when synchronizing kernel headers, like MADV_WIPEONFORK and MADV_KEEPONFORK, that are now beautied (Arnaldo Carvalho de Melo)
- Improve TUI progress bar by showing how many bytes from a total were processed (Jiri Olsa)
- Use scandir() to replace readdir(), prep work to have the synthesizing of PERF_RECORD_ entries for existing threads be multithreaded, making 'perf top' bearable on high core count systems such as Intel's Knights Landing/Mill (Kan Liang)
- Allow creating a ~/.perfconfig file when setting a variable to its default value, previously it would bail out and not write such a file (Taeung Song)
- Introduce wrapper for allowing purely single threaded apps to avoid the costs of locking (Arnaldo Carvalho de Melo)
- Introduce hashtable to reduce the cost of thread lookup
- Fix build C++ build wrt poison.h using void pointer arithmetic, affects only the embedded clang/llvm case, that is disabled by default (Arnaldo Carvalho de Melo)
- Fix leaking rec_argv in error cases (Martin Kepplinger)
- Remove Intel CQM perf test, that infrastructure was nuked (Xiaochen Shen)
----------------------------------------------------------------
Andi Kleen (27):
perf tools: Support weak groups in 'perf stat'
perf vendor events: Support metric_group and no event name in JSON parser perf stat: Factor out generic metric printing
perf stat: Print generic metric header even for failed expressions perf pmu: Extract function to get JSON alias map
perf stat: Support JSON metrics in perf stat
perf list: Add metric groups to perf list
perf stat: Don't use ctx for saved values lookup
perf stat: Support duration_time for metrics
perf stat: Hide internal duration_time counter
perf stat: Update walltime_nsecs_stats in interval mode
perf record: Support direct --user-regs arguments
perf script: Support user regs
perf stat: Fall weak group back even for EBADF
perf vendor events: Add JSON metrics for Broadwell
perf vendor events: Add JSON metrics for Skylake
perf vendor events: Add JSON metrics for Sandy Bridge
perf vendor events: Add JSON metrics for Sandy Bridge EP perf vendor events: Add JSON metrics for Ivy Bridge
perf vendor events: Add JSON metrics for Haswell
perf vendor events: Add JSON metrics for Ivy Town
perf vendor events: Add JSON metrics for Haswell EP
perf vendor events: Add JSON metrics for Broadwell Server perf vendor events: Add JSON metrics for Broadwell DE
perf vendor events: Add JSON metrics for Skylake server
perf pmu: Improve error messages for missing PMUs
perf stat: Fix adding multiple event groups
Arnaldo Carvalho de Melo (7):
perf tools: Make copyfile_offset() static
perf machine: Optimize a bit the machine__findnew_thread() methods perf trace beauty madvise: Generate 'behavior' string table from kernel headers
tools: Update asm-generic/mman-common.h copy from the kernel
perf tools: Get all of tools/{arch,include}/ in the MANIFEST tools include: Do not use poison with C++
perf tools: Provide mutex wrappers for pthreads rwlocks
David Ahern (1):
perf sched timehist: Add pid and tid options
Jiri Olsa (3):
perf tools: Add python-clean target
perf ui progress: Add ui specific init function perf ui progress: Add size info into progress bar
Kan Liang (2):
perf tools: Use scandir() to replace readdir() perf machine: Use hashtable for machine threads
Martin Kepplinger (1):
perf tools: Fix leaking rec_argv in error cases
Taeung Song (2):
perf config: Write a config file just once
perf config: Allow creating empty config set for config file autogeneration
Xiaochen Shen (1):
perf tests: Remove Intel CQM perf test
tools/include/linux/poison.h | 5 + tools/include/uapi/asm-generic/mman-common.h | 14 +- tools/perf/Documentation/perf-list.txt | 9 +- tools/perf/Documentation/perf-record.txt | 2 + tools/perf/Documentation/perf-sched.txt | 8 + tools/perf/Documentation/perf-script.txt | 4 +- tools/perf/Documentation/perf-stat.txt | 7 + tools/perf/MANIFEST | 87 +--- tools/perf/Makefile.perf | 17 +- tools/perf/arch/x86/include/arch-tests.h | 1 - tools/perf/arch/x86/tests/Build | 1 - tools/perf/arch/x86/tests/arch-tests.c | 4 - tools/perf/arch/x86/tests/intel-cqm.c | 127 ------ tools/perf/builtin-c2c.c | 1 + tools/perf/builtin-config.c | 22 +- tools/perf/builtin-kvm.c | 1 - tools/perf/builtin-list.c | 7 + tools/perf/builtin-mem.c | 1 + tools/perf/builtin-record.c | 3 + tools/perf/builtin-sched.c | 4 + tools/perf/builtin-script.c | 32 +- tools/perf/builtin-stat.c | 82 +++- tools/perf/builtin-timechart.c | 4 +- tools/perf/builtin-trace.c | 20 +- tools/perf/perf.h | 1 + .../pmu-events/arch/x86/broadwell/bdw-metrics.json | 164 +++++++ .../arch/x86/broadwellde/bdwde-metrics.json | 164 +++++++ .../arch/x86/broadwellx/bdx-metrics.json | 164 +++++++ .../pmu-events/arch/x86/haswell/hsw-metrics.json | 158 +++++++ .../pmu-events/arch/x86/haswellx/hsx-metrics.json | 158 +++++++ .../pmu-events/arch/x86/ivybridge/ivb-metrics.json | 164 +++++++ .../pmu-events/arch/x86/ivytown/ivt-metrics.json | 164 +++++++ .../pmu-events/arch/x86/jaketown/jkt-metrics.json | 140 ++++++ .../arch/x86/sandybridge/snb-metrics.json | 140 ++++++ .../pmu-events/arch/x86/skylake/skl-metrics.json | 164 +++++++ .../pmu-events/arch/x86/skylakex/skx-metrics.json | 182 ++++++++ tools/perf/pmu-events/jevents.c | 24 +- tools/perf/pmu-events/jevents.h | 2 +- tools/perf/pmu-events/pmu-events.h | 1 + tools/perf/tests/builtin-test.c | 1 + tools/perf/trace/beauty/madvise_behavior.sh | 10 + tools/perf/trace/beauty/mmap.c | 38 +- tools/perf/ui/progress.c | 6 +- tools/perf/ui/progress.h | 12 +- tools/perf/ui/tui/progress.c | 32 +- tools/perf/util/Build | 2 + tools/perf/util/config.c | 5 +- tools/perf/util/data.c | 1 + tools/perf/util/dso.c | 13 +- tools/perf/util/dso.h | 4 +- tools/perf/util/event.c | 46 +- tools/perf/util/evlist.h | 1 + tools/perf/util/evsel.c | 7 +- tools/perf/util/evsel.h | 1 + tools/perf/util/machine.c | 155 ++++--- tools/perf/util/machine.h | 24 +- tools/perf/util/map.c | 34 +- tools/perf/util/map.h | 3 +- tools/perf/util/metricgroup.c | 490 +++++++++++++++++++++ tools/perf/util/metricgroup.h | 31 ++ tools/perf/util/namespaces.c | 1 + tools/perf/util/parse-events.c | 29 +- tools/perf/util/parse-events.h | 3 + tools/perf/util/parse-events.l | 3 +- tools/perf/util/pmu.c | 55 ++- tools/perf/util/pmu.h | 2 + tools/perf/util/probe-file.c | 1 + tools/perf/util/rb_resort.h | 5 +- tools/perf/util/rwsem.c | 32 ++ tools/perf/util/rwsem.h | 19 + tools/perf/util/session.c | 2 +- tools/perf/util/stat-shadow.c | 110 +++-- tools/perf/util/stat.h | 4 +- tools/perf/util/symbol.c | 8 +- tools/perf/util/thread.c | 4 +- tools/perf/util/trace-event-info.c | 1 - tools/perf/util/trace-event-read.c | 1 - tools/perf/util/util.c | 16 +- tools/perf/util/util.h | 7 +- tools/perf/util/vdso.c | 4 +- tools/perf/util/zlib.c | 1 + 81 files changed, 2988 insertions(+), 489 deletions(-) delete mode 100644 tools/perf/arch/x86/tests/intel-cqm.c create mode 100644 tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json create mode 100755 tools/perf/trace/beauty/madvise_behavior.sh create mode 100644 tools/perf/util/metricgroup.c create mode 100644 tools/perf/util/metricgroup.h create mode 100644 tools/perf/util/rwsem.c create mode 100644 tools/perf/util/rwsem.h
Arnaldo Carvalho de Melo
maintainerPATCH 1/44 perf sched timehist: Add pid and tid options
From: David Ahern <[email protected]>
Add options to only show event for specific pid(s) and tid(s).
--- tools/perf/Documentation/perf-sched.txt | 8 ++++++++ tools/perf/builtin-sched.c | 4 ++++ 2 files changed, 12 insertions(+)
tools/perf/Documentation/perf-sched.txt +8 -0
@@ -106,6 +106,14 @@ OPTIONS for 'perf sched timehist' --max-stack:: Maximum number of functions to display in backtrace, default 5. +-p=:: +--pid=:: + Only show events for given process ID (comma separated list). + +-t=:: +--tid=:: + Only show events for given thread ID (comma separated list). + -s:: --summary:: Show only a summary of scheduling by thread with min, max, and average
tools/perf/builtin-sched.c +4 -0
@@ -3363,6 +3363,10 @@ int cmd_sched(int argc, const char **argv)OPT_STRING (0 ,"time" , &sched.time_str,"str" ,"Time span for analysis (start,stop)" ),OPT_BOOLEAN (0 ,"state" , &sched.show_state,"Show task state when sched-out" ), +OPT_STRING ('p' ,"pid" , &symbol_conf.pid_list_str,"pid[,pid...]" , +"analyze events only for given process id(s)" ), +OPT_STRING ('t' ,"tid" , &symbol_conf.tid_list_str,"tid[,tid...]" , +"analyze events only for given thread id(s)" ), OPT_PARENT(sched_options) };
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 2/44 perf tools: Support weak groups in 'perf stat'
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Setting up groups can be complicated due to the complicated scheduling restrictions of different PMUs.
User tools usually don't understand all these restrictions.
Still in many cases it is useful to set up groups and they work most of the time. However if the group is set up wrong some members will not report any value because they never get scheduled.
Add a concept of a 'weak group': try to set up a group, but if it's not schedulable fallback to not using a group. That gives us the best of both worlds: groups if they work, but still a usable fallback if they don't.
In theory it would be possible to have more complex fallback strategies (e.g. try to split the group in half), but the simple fallback of not using a group seems to work for now.
So far the weak group is only implemented for perf stat, not for record.
Here's an unschedulable group (on IvyBridge with SMT on)
% perf stat -e '{branches,branch-misses,l1d.replacement,l2_lines_in.all,l2_rqsts.all_code_rd}' -a sleep 1
73,806,067 branches
4,848,144 branch-misses # 6.57% of all branches
14,754,458 l1d.replacement
24,905,558 l2_lines_in.all
<not supported> l2_rqsts.all_code_rd <------- will never report anythingWith the weak group:
% perf stat -e '{branches,branch-misses,l1d.replacement,l2_lines_in.all,l2_rqsts.all_code_rd}:W' -a sleep 1
125,366,055 branches (80.02%)
9,208,402 branch-misses # 7.35% of all branches (80.01%)
24,560,249 l1d.replacement (80.00%)
43,174,971 l2_lines_in.all (80.05%)
31,891,457 l2_rqsts.all_code_rd (79.92%)The extra event scheduled with some extra multiplexing
v2: Move fallback code to separate function.
Add comment on for_each_group_member
Adjust to new perf_evsel__close interface
v3: Fix debug print out.
Committer testing:
Before:
# perf stat -e '{branches,branch-misses,l1d.replacement,l2_lines_in.all,l2_rqsts.all_code_rd}' -a sleep 1Performance counter stats for 'system wide':
<not counted> branches
<not counted> branch-misses
<not counted> l1d.replacement
<not counted> l2_lines_in.all
<not supported> l2_rqsts.all_code_rd1.002147212 seconds time elapsed
# perf stat -e '{branches,l1d.replacement,l2_lines_in.all,l2_rqsts.all_code_rd}' -a sleep 1Performance counter stats for 'system wide':
83,207,892 branches
11,065,444 l1d.replacement
28,484,024 l2_lines_in.all
12,186,179 l2_rqsts.all_code_rd1.001739493 seconds time elapsed
After:
# perf stat -e '{branches,branch-misses,l1d.replacement,l2_lines_in.all,l2_rqsts.all_code_rd}':W -a sleep 1Performance counter stats for 'system wide':
543,323,909 branches (80.01%)
27,100,512 branch-misses # 4.99% of all branches (80.02%)
50,402,905 l1d.replacement (80.03%)
67,385,892 l2_lines_in.all (80.01%)
21,352,885 l2_rqsts.all_code_rd (79.94%)1.001086658 seconds time elapsed
#
--- tools/perf/Documentation/perf-list.txt | 2 ++ tools/perf/builtin-stat.c | 35 ++++++++++++++++++++++++++++++++++ tools/perf/util/evsel.h | 1 + tools/perf/util/parse-events.c | 8 +++++++- tools/perf/util/parse-events.l | 2 +- 5 files changed, 46 insertions(+), 2 deletions(-)
tools/perf/Documentation/perf-list.txt +2 -0
@@ -47,6 +47,8 @@ counted. The following modifiers exist: P - use maximum detected precise level S - read sample value (PERF_SAMPLE_READ) D - pin the event to the PMU + W - group is weak and will fallback to non-group if not schedulable, + only supported in 'perf stat' for now. The 'p' modifier can be used for specifying how precise the instruction address should be. The 'p' modifier can be specified multiple times:
tools/perf/builtin-stat.c +35 -0
@@ -582,6 +582,32 @@ static bool perf_evsel__should_store_id(struct perf_evsel *counter)return STAT_RECORD || counter->attr.read_format &PERF_FORMAT_ID ; } +static struct perf_evsel *perf_evsel__reset_weak_group (struct perf_evsel *evsel) +{ +struct perf_evsel *c2, *leader; +bool is_open = true; + + leader = evsel->leader; +pr_debug ("Weak group for %s/%d failed\n" , + leader->name, leader->nr_members); + +/* +* for_each_group_member doesn't work here because it doesn't +* include the first entry. +*/ +evlist__for_each_entry (evsel_list, c2) { +if (c2 == evsel) + is_open = false; +if (c2->leader == leader) { +if (is_open) +perf_evsel__close (c2); + c2->leader = c2; + c2->nr_members =0 ; + } + } +return leader; +} +static int __run_perf_stat (int argc,const char **argv) {int interval = stat_config.interval;
@@ -618,6 +644,15 @@ static int __run_perf_stat(int argc, const char **argv)evlist__for_each_entry (evsel_list, counter) { try_again:if (create_perf_stat_counter (counter) <0 ) { + +/* Weak group failed. Reset the group. */ +if (errno ==EINVAL && + counter->leader != counter && + counter->weak_group) { + counter =perf_evsel__reset_weak_group (counter); + goto try_again; + } +/* * PPC returns ENXIO for HW counters until 2.6.37 * (behavior changed with commit b0a873e).
tools/perf/util/evsel.h +1 -0
@@ -137,6 +137,7 @@ struct perf_evsel {const char * metric_name;struct perf_evsel **metric_events;bool collect_stat; +bool weak_group; };union u64_swap {
tools/perf/util/parse-events.c +7 -1
@@ -1366,6 +1366,7 @@ struct event_modifier {int exclude_GH;int sample_read;int pinned; +int weak; }; static int get_event_modifier(struct event_modifier *mod, char *str,
@@ -1384,6 +1385,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str,int exclude = eu | ek | eh;int exclude_GH = evsel ? evsel->exclude_GH :0 ; +int weak =0 ;memset (mod,0 ,sizeof (*mod));
@@ -1421,6 +1423,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str, sample_read =1 ; }else if (*str =='D' ) { pinned =1 ; + }else if (*str =='W' ) { + weak =1 ; }else break ;
@@ -1451,6 +1455,7 @@ static int get_event_modifier(struct event_modifier *mod, char *str, mod->exclude_GH = exclude_GH; mod->sample_read = sample_read; mod->pinned = pinned; + mod->weak = weak;return 0 ; }
@@ -1464,7 +1469,7 @@ static int check_modifier(char *str)char *p = str;/* The sizeof includes 0 byte as well. */ -if (strlen (str) > (sizeof ("ukhGHpppPSDI" ) -1 )) +if (strlen (str) > (sizeof ("ukhGHpppPSDIW" ) -1 ))return -1 ;while (*p) {
@@ -1504,6 +1509,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add) evsel->exclude_GH = mod.exclude_GH; evsel->sample_read = mod.sample_read; evsel->precise_max = mod.precise_max; + evsel->weak_group = mod.weak;if (perf_evsel__is_group_leader (evsel)) evsel->attr.pinned = mod.pinned;
tools/perf/util/parse-events.l +1 -1
@@ -161,7 +161,7 @@ name [a-zA-Z_*?][a-zA-Z0-9_*?.]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)? /* If you add a modifier you need to update check_modifier() */ -modifier_event [ukhpPGHSDI]+ +modifier_event [ukhpPGHSDIW]+ modifier_bp [rwx]{1,3} %%
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 3/44 perf vendor events: Support metric_group and no event name in JSON parser
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Some enhancements to the JSON parser to prepare for metrics support
- Parse the new MetricGroup field
- Support JSON events with no event name, that have only MetricName.
--- tools/perf/pmu-events/jevents.c | 24 ++++++++++++++++++------ tools/perf/pmu-events/jevents.h | 2 +- tools/perf/pmu-events/pmu-events.h | 1 + 3 files changed, 20 insertions(+), 7 deletions(-)
tools/perf/pmu-events/jevents.c +18 -6
@@ -292,7 +292,7 @@ static int print_events_table_entry(void *data, char *name, char *event, char *desc, char *long_desc, char *pmu, char *unit, char *perpkg, char *metric_expr, - char *metric_name) + char *metric_name, char *metric_group) { struct perf_entry_data *pd = data;FILE *outfp = pd->outfp;
@@ -304,8 +304,10 @@ static int print_events_table_entry(void *data, char *name, char *event,*/ fprintf (outfp,"{\n" ); -fprintf (outfp,"\t.name = \"%s\",\n" , name); -fprintf (outfp,"\t.event = \"%s\",\n" , event); +if (name) +fprintf (outfp,"\t.name = \"%s\",\n" , name); +if (event) +fprintf (outfp,"\t.event = \"%s\",\n" , event);fprintf (outfp,"\t.desc = \"%s\",\n" , desc);fprintf (outfp,"\t.topic = \"%s\",\n" , topic);if (long_desc && long_desc[0 ])
@@ -320,6 +322,8 @@ static int print_events_table_entry(void *data, char *name, char *event,fprintf (outfp,"\t.metric_expr = \"%s\",\n" , metric_expr);if (metric_name)fprintf (outfp,"\t.metric_name = \"%s\",\n" , metric_name); +if (metric_group) +fprintf (outfp,"\t.metric_group = \"%s\",\n" , metric_group);fprintf (outfp,"},\n" );return 0 ;
@@ -357,6 +361,9 @@ static char *real_event(const char *name, char *event) {int i; +if (!name) +return NULL ; +for (i =0 ; fixed[i].name; i++)if (!strcasecmp (name, fixed[i].name))return (char *)fixed[i].event;
@@ -369,7 +376,7 @@ int json_events(const char *fn,char *long_desc, char *pmu, char *unit, char *perpkg, char *metric_expr, - char *metric_name), + char *metric_name, char *metric_group), void *data) { int err = -EIO;
@@ -397,6 +404,7 @@ int json_events(const char *fn,char *unit =NULL ;char *metric_expr =NULL ;char *metric_name =NULL ; +char *metric_group =NULL ;unsigned long long eventcode =0 ;struct msrmap *msr =NULL ;jsmntok_t *msrval =NULL ;
@@ -476,6 +484,8 @@ int json_events(const char *fn,addfield (map, &perpkg,"" ,"" , val); }else if (json_streq (map, field,"MetricName" )) {addfield (map, &metric_name,"" ,"" , val); + }else if (json_streq (map, field,"MetricGroup" )) { +addfield (map, &metric_group,"" ,"" , val); }else if (json_streq (map, field,"MetricExpr" )) {addfield (map, &metric_expr,"" ,"" , val);for (s = metric_expr; *s; s++)
@@ -501,10 +511,11 @@ int json_events(const char *fn,addfield (map, &event,"," , filter,NULL );if (msr !=NULL )addfield (map, &event,"," , msr->pname, msrval); -fixname (name); +if (name) +fixname (name); err =func (data, name,real_event (name, event), desc, long_desc, - pmu, unit, perpkg, metric_expr, metric_name); + pmu, unit, perpkg, metric_expr, metric_name, metric_group);free (event);free (desc);free (name);
@@ -516,6 +527,7 @@ int json_events(const char *fn,free (unit);free (metric_expr);free (metric_name); +free (metric_group);if (err)break ; tok += j;
tools/perf/pmu-events/jevents.h +1 -1
@@ -6,7 +6,7 @@ int json_events(const char *fn,char *long_desc, char *pmu, char *unit, char *perpkg, char *metric_expr, - char *metric_name), + char *metric_name, char *metric_group), void *data);char *get_cpu_str (void );
tools/perf/pmu-events/pmu-events.h +1 -0
@@ -15,6 +15,7 @@ struct pmu_event {const char *perpkg;const char *metric_expr;const char *metric_name; +const char *metric_group; };/*
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 4/44 perf stat: Factor out generic metric printing
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
The 'perf stat' shadow metric printing already supports generic metrics. Factor out the code doing that into a separate function that can be re-used in a later patch.
No behavior changes.
v2: Fix indentation
--- tools/perf/util/stat-shadow.c | 69 ++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 27 deletions(-)
tools/perf/util/stat-shadow.c +42 -27
@@ -627,6 +627,46 @@ static void print_smi_cost(int cpu, struct perf_evsel *evsel, out->print_metric (out->ctx,NULL ,"%4.0f" ,"SMI#" , smi_num); } +static void generic_metric (const char *metric_expr, +struct perf_evsel **metric_events, +char *name, +const char *metric_name, +double avg, +int cpu, +int ctx, +struct perf_stat_output_ctx *out) +{ +print_metric_t print_metric = out->print_metric; +struct parse_ctx pctx; +double ratio; +int i; +void *ctxp = out->ctx; + +expr__ctx_init (&pctx); +expr__add_id (&pctx, name, avg); +for (i =0 ; metric_events[i]; i++) { +struct saved_value *v; + + v =saved_value_lookup (metric_events[i], cpu, ctx, false); +if (!v) +break ; +expr__add_id (&pctx, metric_events[i]->name,avg_stats (&v->stats)); + } +if (!metric_events[i]) { +const char *p = metric_expr; + +if (expr__parse (&ratio, &pctx, &p) ==0 ) +print_metric (ctxp,NULL ,"%8.1f" , + metric_name ? + metric_name : + out->force_header ? name :"" , + ratio); +else +print_metric (ctxp,NULL ,NULL ,"" ,0 ); + }else +print_metric (ctxp,NULL ,NULL ,"" ,0 ); +} +void perf_stat__print_shadow_stats (struct perf_evsel *evsel,double avg,int cpu,struct perf_stat_output_ctx *out)
@@ -819,33 +859,8 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,else print_metric (ctxp,NULL ,NULL , name,0 ); }else if (evsel->metric_expr) { -struct parse_ctx pctx; -int i; - -expr__ctx_init (&pctx); -expr__add_id (&pctx, evsel->name, avg); -for (i =0 ; evsel->metric_events[i]; i++) { -struct saved_value *v; - - v =saved_value_lookup (evsel->metric_events[i], cpu, ctx, false); -if (!v) -break ; -expr__add_id (&pctx, evsel->metric_events[i]->name, -avg_stats (&v->stats)); - } -if (!evsel->metric_events[i]) { -const char *p = evsel->metric_expr; - -if (expr__parse (&ratio, &pctx, &p) ==0 ) -print_metric (ctxp,NULL ,"%8.1f" , - evsel->metric_name ? - evsel->metric_name : - out->force_header ? evsel->name :"" , - ratio); -else -print_metric (ctxp,NULL ,NULL ,"" ,0 ); - }else -print_metric (ctxp,NULL ,NULL ,"" ,0 ); +generic_metric (evsel->metric_expr, evsel->metric_events, evsel->name, + evsel->metric_name, avg, cpu, ctx, out); }else if (runtime_nsecs_stats[cpu].n !=0 ) {char unit ='M' ;char unit_buf[10 ];
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 5/44 perf stat: Print generic metric header even for failed expressions
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Print the generic metric header even when the expression evaluation failed. Otherwise an expression that fails on the first collections due to division by zero may suddenly reappear later without an header.
--- tools/perf/util/stat-shadow.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/stat-shadow.c +3 -1
@@ -662,7 +662,9 @@ static void generic_metric(const char *metric_expr, out->force_header ? name :"" , ratio); else - print_metric(ctxp, NULL, NULL, "", 0); + print_metric(ctxp, NULL, NULL, + out->force_header ? + (metric_name ? metric_name : name) : "", 0); }else print_metric (ctxp,NULL ,NULL ,"" ,0 ); }
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 6/44 perf pmu: Extract function to get JSON alias map
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Extract the code to get the per cpu JSON alias into a separate function for reuse. No behavior changes.
--- tools/perf/util/pmu.c | 49 +++++++++++++++++++++++++++++++++---------------- tools/perf/util/pmu.h | 2 ++ 2 files changed, 35 insertions(+), 16 deletions(-)
tools/perf/util/pmu.c +33 -16
@@ -516,16 +516,8 @@ char * __weak get_cpuid_str(void)return NULL ; } -/* -* From the pmu_events_map, find the table of PMU events that corresponds -* to the current running CPU. Then, add all PMU events from that table -* as aliases. -*/ -static void pmu_add_cpu_aliases (struct list_head *head,const char *name) +static char *perf_pmu__getcpuid (void ) { -int i; -struct pmu_events_map *map; -struct pmu_event *pe;char *cpuid;static bool printed;
@@ -535,22 +527,50 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)if (!cpuid) cpuid =get_cpuid_str ();if (!cpuid) -return ; +return NULL ;if (!printed) {pr_debug ("Using CPUID %s\n" , cpuid); printed = true; } +return cpuid; +} + +struct pmu_events_map *perf_pmu__find_map (void ) +{ +struct pmu_events_map *map; +char *cpuid =perf_pmu__getcpuid (); +int i; i =0 ; -while (1 ) { +for (;;) { map = &pmu_events_map[i++]; -if (!map->table) - goto out; +if (!map->table) { + map =NULL ; +break ; + }if (!strcmp (map->cpuid, cpuid))break ; } +free (cpuid); +return map; +} + +/* +* From the pmu_events_map, find the table of PMU events that corresponds +* to the current running CPU. Then, add all PMU events from that table +* as aliases. +*/ +static void pmu_add_cpu_aliases (struct list_head *head,const char *name) +{ +int i; +struct pmu_events_map *map; +struct pmu_event *pe; + + map =perf_pmu__find_map (); +if (!map) +return ;/* * Found a matching PMU events table. Create aliases
@@ -575,9 +595,6 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name) (char *)pe->metric_expr, (char *)pe->metric_name); } - -out: -free (cpuid); } struct perf_event_attr * __weak
tools/perf/util/pmu.h +2 -0
@@ -90,4 +90,6 @@ int perf_pmu__test(void);struct perf_event_attr *perf_pmu__get_default_config (struct perf_pmu *pmu); +struct pmu_events_map *perf_pmu__find_map (void ); +#endif /* __PMU_H */
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 7/44 perf stat: Support JSON metrics in perf stat
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Add generic support for standalone metrics specified in JSON files to perf stat. A metric is a formula that uses multiple events to compute a higher level result (e.g. IPC).
Previously metrics were always tied to an event and automatically enabled with that event. But now change it that we can have standalone metrics. They are in the same JSON data structure as events, but don't have an event name.
We also allow to organize the metrics in metric groups, which allows a short cut to select several related metrics at once.
Add a new -M / --metrics option to perf stat that adds the metrics or metric groups specified.
Add the core code to manage and parse the metric groups. They are collected from the JSON data structures into a separate rblist. When computing shadow values look for metrics in that list. Then they are computed using the existing saved values infrastructure in stat-shadow.c
The actual JSON metrics are in a separate pull request.
% perf stat -M Summary --metric-only -a sleep 1
Performance counter stats for 'system wide':
Instructions CLKS CPU_Utilization GFLOPs SMT_2T_Utilization Kernel_Utilization 317614222.0 1392930775.0 0.0 0.0 0.2 0.1
1.001497549 seconds time elapsed
% perf stat -M GFLOPs flops
Performance counter stats for 'flops':
3,999,541,471 fp_comp_ops_exe.sse_scalar_single # 1.2 GFLOPs (66.65%)
14 fp_comp_ops_exe.sse_scalar_double (66.65%)
0 fp_comp_ops_exe.sse_packed_double (66.67%)
0 fp_comp_ops_exe.sse_packed_single (66.70%)
0 simd_fp_256.packed_double (66.70%)
0 simd_fp_256.packed_single (66.67%)
0 duration_time3.238372845 seconds time elapsed
v2: Add missing header file
v3: Move find_map to pmu.c
--- tools/perf/Documentation/perf-stat.txt | 7 + tools/perf/builtin-stat.c | 18 +- tools/perf/util/Build | 1 + tools/perf/util/metricgroup.c | 313 +++++++++++++++++++++++++++++++++ tools/perf/util/metricgroup.h | 31 ++++ tools/perf/util/pmu.c | 5 +- tools/perf/util/stat-shadow.c | 22 ++- tools/perf/util/stat.h | 4 +- 8 files changed, 395 insertions(+), 6 deletions(-) create mode 100644 tools/perf/util/metricgroup.c create mode 100644 tools/perf/util/metricgroup.h
tools/perf/Documentation/perf-stat.txt +7 -0
@@ -199,6 +199,13 @@ Aggregate counts per processor socket for system-wide mode measurements. --per-core:: Aggregate counts per physical processor for system-wide mode measurements. +-M:: +--metrics:: +Print metrics or metricgroups specified in a comma separated list. +For a group all metrics from the group are added. +The events from the metrics are automatically measured. +See perf list output for the possble metrics and metricgroups. + -A:: --no-aggr:: Do not aggregate counts across all monitored CPUs.
tools/perf/builtin-stat.c +16 -2
@@ -65,6 +65,7 @@#include "util/tool.h" #include "util/group.h" #include "util/string2.h" +#include "util/metricgroup.h" #include "asm/bug.h" #include <linux/time64.h>
@@ -133,6 +134,8 @@ static const char *smi_cost_attrs = {static struct perf_evlist *evsel_list; +static struct rblist metric_events; +static struct target target = { .uid =UINT_MAX , };
@@ -1234,7 +1237,7 @@ static void printout(int id, int nr, struct perf_evsel *counter, double uval,perf_stat__print_shadow_stats (counter, uval,first_shadow_cpu (counter, id), - &out); + &out, &metric_events);if (!csv_output && !metric_only) {print_noise (counter, noise);print_running (run, ena);
@@ -1565,7 +1568,8 @@ static void print_metric_headers(const char *prefix, bool no_indent) os.evsel = counter;perf_stat__print_shadow_stats (counter,0 ,0 , - &out); + &out, + &metric_events); }fputc ('\n' , stat_config.output); }
@@ -1789,6 +1793,13 @@ static int enable_metric_only(const struct option *opt __maybe_unused,return 0 ; } +static int parse_metric_groups (const struct option *opt, +const char *str, +int unset__maybe_unused ) +{ +return metricgroup__parse_groups (opt, str, &metric_events); +} +static const struct option stat_options[] = {OPT_BOOLEAN ('T' ,"transaction" , &transaction_run,"hardware transaction statistics" ),
@@ -1854,6 +1865,9 @@ static const struct option stat_options[] = { "measure topdown level 1 statistics"),OPT_BOOLEAN (0 ,"smi-cost" , &smi_cost,"measure SMI cost" ), +OPT_CALLBACK ('M' ,"metrics" , &evsel_list,"metric/metric group list" , +"monitor specified metrics or metric groups (separated by ,)" , + parse_metric_groups), OPT_END() };
tools/perf/util/Build +1 -0
@@ -34,6 +34,7 @@ libperf-y += dso.o libperf-y += symbol.o libperf-y += symbol_fprintf.o libperf-y += color.o +libperf-y += metricgroup.o libperf-y += header.o libperf-y += callchain.o libperf-y += values.o
tools/perf/util/metricgroup.c new file +313 -0
313 lines not on this page · raw message
tools/perf/util/metricgroup.h new file +31 -0
@@ -0,0 +1,31 @@ +#ifndef METRICGROUP_H +#define METRICGROUP_H 1 + +#include "linux/list.h" +#include "rblist.h" +#include <subcmd/parse-options.h> +#include "evlist.h" +#include "strbuf.h" + +struct metric_event { +struct rb_node nd; +struct perf_evsel *evsel; +struct list_head head;/* list of metric_expr */ +}; + +struct metric_expr { +struct list_head nd; +const char *metric_expr; +const char *metric_name; +struct perf_evsel **metric_events; +}; + +struct metric_event *metricgroup__lookup (struct rblist *metric_events, +struct perf_evsel *evsel, +bool create); +int metricgroup__parse_groups (const struct option *opt, +const char *str, +struct rblist *metric_events); + +void metricgroup__print (bool metrics,bool groups,char *filter,bool raw); +#endif
tools/perf/util/pmu.c +4 -1
@@ -580,8 +580,11 @@ static void pmu_add_cpu_aliases(struct list_head *head, const char *name)const char *pname; pe = &map->table[i++]; -if (!pe->name) +if (!pe->name) { +if (pe->metric_group || pe->metric_name) +continue ;break ; + } pname = pe->pmu ? pe->pmu :"cpu" ;if (strncmp (pname, name,strlen (pname)))
tools/perf/util/stat-shadow.c +20 -2
@@ -6,6 +6,7 @@#include "rblist.h" #include "evlist.h" #include "expr.h" +#include "metricgroup.h" enum {CTX_BIT_USER =1 <<0 ,
@@ -671,13 +672,16 @@ static void generic_metric(const char *metric_expr,void perf_stat__print_shadow_stats (struct perf_evsel *evsel,double avg,int cpu, -struct perf_stat_output_ctx *out) +struct perf_stat_output_ctx *out, +struct rblist *metric_events) {void *ctxp = out->ctx;print_metric_t print_metric = out->print_metric;double total, ratio =0.0 , total2;const char *color =NULL ;int ctx =evsel_context (evsel); +struct metric_event *me; +int num =1 ;if (perf_evsel__match (evsel,HARDWARE ,HW_INSTRUCTIONS )) { total =avg_stats (&runtime_cycles_stats[ctx][cpu]);
@@ -880,6 +884,20 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, }else if (perf_stat_evsel__is (evsel,SMI_NUM )) {print_smi_cost (cpu, evsel, out); }else { -print_metric (ctxp,NULL ,NULL ,NULL ,0 ); + num =0 ; } + +if ((me =metricgroup__lookup (metric_events, evsel, false)) !=NULL ) { +struct metric_expr *mexp; + + list_for_each_entry (mexp, &me->head, nd) { +if (num++ >0 ) + out->new_line (ctxp); +generic_metric (mexp->metric_expr, mexp->metric_events, + evsel->name, mexp->metric_name, + avg, cpu, ctx, out); + } + } +if (num ==0 ) +print_metric (ctxp,NULL ,NULL ,NULL ,0 ); }
tools/perf/util/stat.h +3 -1
@@ -91,9 +91,11 @@ struct perf_stat_output_ctx {bool force_header; }; +struct rblist ;void perf_stat__print_shadow_stats (struct perf_evsel *evsel,double avg,int cpu, -struct perf_stat_output_ctx *out); +struct perf_stat_output_ctx *out, +struct rblist *metric_events);void perf_stat__collect_metric_expr (struct perf_evlist *);int perf_evlist__alloc_stats (struct perf_evlist *evlist,bool alloc_raw);
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 8/44 perf list: Add metric groups to perf list
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Add code to perf list to print metric groups, and metrics that don't have an event name. The metricgroup code collects the eventgroups and events into a rblist, and then prints them according to the configured filters.
The metricgroups are printed by default, but can be limited by perf list metric or perf list metricgroup
% perf list metricgroup
..
Metric Groups:
DSB:
DSB_Coverage
[Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)]
FLOPS:
GFLOPs
[Giga Floating Point Operations Per Second]
Frontend:
IFetch_Line_Utilization
[Rough Estimation of fraction of fetched lines bytes that were likely consumed by program instructions]
Frontend_Bandwidth:
DSB_Coverage
[Fraction of Uops delivered by the DSB (aka Decoded Icache; or Uop Cache)]
Memory_BW:
MLP
[Memory-Level-Parallelism (average number of L1 miss demand load when there is at least 1 such miss)]
v2: Check return value of asprintf to fix warning on FC26 Fix key in lookup/addition for the groups list
--- tools/perf/Documentation/perf-list.txt | 7 +- tools/perf/builtin-list.c | 7 ++ tools/perf/util/metricgroup.c | 176 +++++++++++++++++++++++++++++++++ tools/perf/util/parse-events.c | 3 + 4 files changed, 192 insertions(+), 1 deletion(-)
tools/perf/Documentation/perf-list.txt +6 -1
@@ -8,7 +8,8 @@ perf-list - List all symbolic event types SYNOPSIS -------- [verse] -'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|sdt|event_glob] +'perf list' [--no-desc] [--long-desc] + [hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob] DESCRIPTION -----------
@@ -248,6 +249,10 @@ To limit the list use: . 'sdt' to list all Statically Defined Tracepoint events. +. 'metric' to list metrics + +. 'metricgroup' to list metricgroups with metrics. + . If none of the above is matched, it will apply the supplied glob to all events, printing the ones that match.
tools/perf/builtin-list.c +7 -0
@@ -15,6 +15,7 @@#include "util/cache.h" #include "util/pmu.h" #include "util/debug.h" +#include "util/metricgroup.h" #include <subcmd/parse-options.h> static bool desc_flag = true;
@@ -79,6 +80,10 @@ int cmd_list(int argc, const char **argv) long_desc_flag, details_flag); else if (strcmp(argv[i], "sdt") == 0) print_sdt_events(NULL, NULL, raw_dump); + else if (strcmp(argv[i], "metric") == 0) + metricgroup__print(true, false, NULL, raw_dump); + else if (strcmp(argv[i], "metricgroup") == 0) + metricgroup__print(false, true, NULL, raw_dump); else if ((sep = strchr(argv[i], ':')) != NULL) {int sep_idx;
@@ -96,6 +101,7 @@ int cmd_list(int argc, const char **argv) s[sep_idx] ='\0' ;print_tracepoint_events (s, s + sep_idx +1 , raw_dump);print_sdt_events (s, s + sep_idx +1 , raw_dump); +metricgroup__print (true, true, s, raw_dump);free (s); }else {if (asprintf (&s,"*%s*" , argv[i]) <0 ) {
@@ -112,6 +118,7 @@ int cmd_list(int argc, const char **argv) details_flag);print_tracepoint_events (NULL , s, raw_dump);print_sdt_events (NULL , s, raw_dump); +metricgroup__print (true, true,NULL , raw_dump);free (s); } }
tools/perf/util/metricgroup.c +176 -0
182 lines not on this page · raw message
tools/perf/util/parse-events.c +3 -0
@@ -28,6 +28,7 @@#include "probe-file.h" #include "asm/bug.h" #include "util/parse-branch-options.h" +#include "metricgroup.h" #define MAX_NAME_LEN 100
@@ -2380,6 +2381,8 @@ void print_events(const char *event_glob, bool name_only, bool quiet_flag,print_tracepoint_events (NULL ,NULL , name_only);print_sdt_events (NULL ,NULL , name_only); + +metricgroup__print (true, true,NULL , name_only); }int parse_events__is_hardcoded_term (struct parse_events_term *term)
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 9/44 perf stat: Don't use ctx for saved values lookup
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
We don't need to use ctx to look up events for saved values. The context is already part of the evsel pointer, which is the primary key.
--- tools/perf/util/stat-shadow.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-)
tools/perf/util/stat-shadow.c +5 -11
@@ -56,7 +56,6 @@ struct saved_value {struct rb_node rb_node;struct perf_evsel *evsel;int cpu; -int ctx;struct stats stats; };
@@ -67,8 +66,6 @@ static int saved_value_cmp(struct rb_node *rb_node, const void *entry) rb_node);const struct saved_value *b = entry; -if (a->ctx != b->ctx) -return a->ctx - b->ctx;if (a->cpu != b->cpu)return a->cpu - b->cpu;if (a->evsel == b->evsel)
@@ -90,13 +87,12 @@ static struct rb_node *saved_value_new(struct rblist *rblist __maybe_unused, }static struct saved_value *saved_value_lookup (struct perf_evsel *evsel, -int cpu,int ctx, +int cpu,bool create) {struct rb_node *nd;struct saved_value dm = { .cpu = cpu, - .ctx = ctx, .evsel = evsel, }; nd =rblist__find (&runtime_saved_values, &dm);
@@ -232,8 +228,7 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,update_stats (&runtime_aperf_stats[ctx][cpu], count[0 ]);if (counter->collect_stat) { -struct saved_value *v =saved_value_lookup (counter, cpu, ctx, - true); +struct saved_value *v =saved_value_lookup (counter, cpu, true);update_stats (&v->stats, count[0 ]); } }
@@ -634,7 +629,6 @@ static void generic_metric(const char *metric_expr,const char *metric_name, double avg, int cpu, - int ctx, struct perf_stat_output_ctx *out) { print_metric_t print_metric = out->print_metric;
@@ -648,7 +642,7 @@ static void generic_metric(const char *metric_expr,for (i =0 ; metric_events[i]; i++) {struct saved_value *v; - v =saved_value_lookup (metric_events[i], cpu, ctx, false); + v =saved_value_lookup (metric_events[i], cpu, false);if (!v)break ;expr__add_id (&pctx, metric_events[i]->name,avg_stats (&v->stats));
@@ -866,7 +860,7 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,print_metric (ctxp,NULL ,NULL , name,0 ); }else if (evsel->metric_expr) {generic_metric (evsel->metric_expr, evsel->metric_events, evsel->name, - evsel->metric_name, avg, cpu, ctx, out); + evsel->metric_name, avg, cpu, out); }else if (runtime_nsecs_stats[cpu].n !=0 ) {char unit ='M' ;char unit_buf[10 ];
@@ -895,7 +889,7 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel, out->new_line (ctxp);generic_metric (mexp->metric_expr, mexp->metric_events, evsel->name, mexp->metric_name, - avg, cpu, ctx, out); + avg, cpu, out); } }if (num ==0 )
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 10/44 perf stat: Support duration_time for metrics
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Some of the metrics formulas (like GFLOPs) need to know how long the measurement period is. Support an internal event called duration_time, which reports time in second. It maps to the dummy event, but is special cased for statistics to report the walltime duration.
So far it is not printed, but only used internally for metrics.
--- tools/perf/util/parse-events.l | 1 + tools/perf/util/stat-shadow.c | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-)
tools/perf/util/parse-events.l +1 -0
@@ -288,6 +288,7 @@ cpu-migrations|migrations { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COU alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); } emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } +duration_time { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } bpf-output { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); } /*
tools/perf/util/stat-shadow.c +13 -4
@@ -641,11 +641,20 @@ static void generic_metric(const char *metric_expr,expr__add_id (&pctx, name, avg);for (i =0 ; metric_events[i]; i++) {struct saved_value *v; +struct stats *stats; +double scale; - v =saved_value_lookup (metric_events[i], cpu, false); -if (!v) -break ; -expr__add_id (&pctx, metric_events[i]->name,avg_stats (&v->stats)); +if (!strcmp (metric_events[i]->name,"duration_time" )) { + stats = &walltime_nsecs_stats; + scale =1e-9 ; + }else { + v =saved_value_lookup (metric_events[i], cpu, false); +if (!v) +break ; + stats = &v->stats; + scale =1.0 ; + } +expr__add_id (&pctx, metric_events[i]->name,avg_stats (stats)*scale); }if (!metric_events[i]) {const char *p = metric_expr;
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 11/44 perf stat: Hide internal duration_time counter
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Some perf stat metrics use an internal "duration_time" metric. It is not correctly printed however. So hide it during output to avoid confusing users with 0 counts.
--- tools/perf/builtin-stat.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-)
tools/perf/builtin-stat.c +24 -3
@@ -195,6 +195,11 @@ static struct perf_stat_config stat_config = { .scale = true, }; +static bool is_duration_time (struct perf_evsel *evsel) +{ +return !strcmp (evsel->name,"duration_time" ); +} +static inline void diff_timespec (struct timespec *r,struct timespec *a,struct timespec *b) {
@@ -1363,6 +1368,9 @@ static void print_aggr(char *prefix) ad.id = id = aggr_map->map[s]; first = true;evlist__for_each_entry (evsel_list, counter) { +if (is_duration_time (counter)) +continue ; + ad.val = ad.ena = ad.run =0 ; ad.nr =0 ;if (!collect_data (counter, aggr_cb, &ad))
@@ -1506,6 +1514,8 @@ static void print_no_aggr_metric(char *prefix)if (prefix)fputs (prefix, stat_config.output);evlist__for_each_entry (evsel_list, counter) { +if (is_duration_time (counter)) +continue ;if (first) {aggr_printout (counter, cpu,0 ); first = false;
@@ -1560,6 +1570,8 @@ static void print_metric_headers(const char *prefix, bool no_indent)/* Print metrics headers only */ evlist__for_each_entry (evsel_list, counter) { +if (is_duration_time (counter)) +continue ; os.evsel = counter; out.ctx = &os; out.print_metric = print_metric_header;
@@ -1707,12 +1719,18 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)print_aggr (prefix);break ;case AGGR_THREAD : -evlist__for_each_entry (evsel_list, counter) +evlist__for_each_entry (evsel_list, counter) { +if (is_duration_time (counter)) +continue ;print_aggr_thread (counter, prefix); + }break ;case AGGR_GLOBAL : -evlist__for_each_entry (evsel_list, counter) +evlist__for_each_entry (evsel_list, counter) { +if (is_duration_time (counter)) +continue ;print_counter_aggr (counter, prefix); + }if (metric_only)fputc ('\n' , stat_config.output);break ;
@@ -1720,8 +1738,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)if (metric_only)print_no_aggr_metric (prefix);else { -evlist__for_each_entry (evsel_list, counter) +evlist__for_each_entry (evsel_list, counter) { +if (is_duration_time (counter)) +continue ;print_counter (counter, prefix); + } }break ;case AGGR_UNSET :
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 12/44 perf stat: Update walltime_nsecs_stats in interval mode
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Some metrics (like GFLOPs) need walltime_nsecs_stats for each interval. Compute it for each interval instead of only at the end.
Pointed out by Jiri.
--- tools/perf/builtin-stat.c | 2 ++ 1 file changed, 2 insertions(+)
tools/perf/builtin-stat.c +2 -0
@@ -415,6 +415,8 @@ static void process_interval(void)pr_err ("failed to write stat round event\n" ); } +init_stats (&walltime_nsecs_stats); +update_stats (&walltime_nsecs_stats, stat_config.interval *1000000 );print_counters (&rs,0 ,NULL ); }
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 13/44 perf record: Support direct --user-regs arguments
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
USER_REGS can currently only collected implicitely with call graph recording. Sometimes it is useful to see them separately, and filter them. Add a new --user-regs option to record that is similar to --intr-regs, but acts on user regs.
--- tools/perf/Documentation/perf-record.txt | 2 ++ tools/perf/builtin-record.c | 3 +++ tools/perf/perf.h | 1 + tools/perf/util/evsel.c | 7 ++++++- 4 files changed, 12 insertions(+), 1 deletion(-)
tools/perf/Documentation/perf-record.txt +2 -0
@@ -377,6 +377,8 @@ symbolic names, e.g. on x86, ax, si. To list the available registers use --intr-regs=\?. To name registers, pass a comma separated list such as --intr-regs=ax,bx. The list of register is architecture dependent. +--user-regs:: +Capture user registers at sample time. Same arguments as -I. --running-time:: Record running and enabled time for read events (:S)
tools/perf/builtin-record.c +3 -0
@@ -1643,6 +1643,9 @@ static struct option __record_options[] = {OPT_CALLBACK_OPTARG ('I' ,"intr-regs" , &record.opts.sample_intr_regs,NULL ,"any register" ,"sample selected machine registers on interrupt," " use -I ? to list register names" , parse_regs), +OPT_CALLBACK_OPTARG (0 ,"user-regs" , &record.opts.sample_user_regs,NULL ,"any register" , +"sample selected machine registers on interrupt," +" use -I ? to list register names" , parse_regs),OPT_BOOLEAN (0 ,"running-time" , &record.opts.running_time,"Record running/enabled time of read (:S) events" ), OPT_CALLBACK('k', "clockid", &record.opts,
tools/perf/perf.h +1 -0
@@ -65,6 +65,7 @@ struct record_opts {unsigned int user_freq;u64 branch_stack;u64 sample_intr_regs; +u64 sample_user_regs;u64 default_interval;u64 user_interval;size_t auxtrace_snapshot_size;
tools/perf/util/evsel.c +6 -1
@@ -678,7 +678,7 @@ void perf_evsel__config_callchain(struct perf_evsel *evsel,if (!function) {perf_evsel__set_sample_bit (evsel,REGS_USER );perf_evsel__set_sample_bit (evsel,STACK_USER ); - attr->sample_regs_user =PERF_REGS_MASK ; + attr->sample_regs_user |=PERF_REGS_MASK ; attr->sample_stack_user = param->dump_size; attr->exclude_callchain_user =1 ; }else {
@@ -931,6 +931,11 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,perf_evsel__set_sample_bit (evsel,REGS_INTR ); } +if (opts->sample_user_regs) { + attr->sample_regs_user |= opts->sample_user_regs; +perf_evsel__set_sample_bit (evsel,REGS_USER ); + } +if (target__has_cpu (&opts->target) || opts->sample_cpu)perf_evsel__set_sample_bit (evsel,CPU );
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 14/44 perf script: Support user regs
In reply to Arnaldo Carvalho de MeloFrom: Andi Kleen <[email protected]>
Teach perf script to print user regs.
% perf record --user-regs=ip,sp ...
% perf script -F ip,sym,uregs
...
ffffffff9e060c24 native_write_msr ABI:2 SP:0x7ffd0ea06c38 IP:0x7fe77f55b637 ffffffff9e060c24 native_write_msr ABI:2 SP:0x7ffd0ea06c38 IP:0x7fe77f55b637 ffffffff9e060c24 native_write_msr ABI:2 SP:0x7ffd0ea06c38 IP:0x7fe77f55b637 ffffffff9e060c24 native_write_msr ABI:2 SP:0x7ffd0ea06c38 IP:0x7fe77f55b637
ffffffff9e00cc12 intel_pmu_handle_irq ABI:2 SP:0x7ffd0ea06c38 IP:0x7fe77f55b637
v2: Rebased on top of phys-addr patches
--- tools/perf/Documentation/perf-script.txt | 4 ++-- tools/perf/builtin-script.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-script.txt +2 -2
@@ -116,8 +116,8 @@ OPTIONS --fields:: Comma separated list of fields to print. Options are: comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, - srcline, period, iregs, brstack, brstacksym, flags, bpf-output, brstackinsn, brstackoff, - callindent, insn, insnlen, synth, phys_addr. + srcline, period, iregs, uregs, brstack, brstacksym, flags, bpf-output, brstackinsn, + brstackoff, callindent, insn, insnlen, synth, phys_addr. Field list can be prepended with the type, trace, sw or hw, to indicate to which event type the field list applies. e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
tools/perf/builtin-script.c +29 -1
@@ -88,6 +88,7 @@ enum perf_output_field {PERF_OUTPUT_BRSTACKOFF =1U <<24 ,PERF_OUTPUT_SYNTH =1U <<25 ,PERF_OUTPUT_PHYS_ADDR =1U <<26 , + PERF_OUTPUT_UREGS = 1U << 27, }; struct output_option {
@@ -109,6 +110,7 @@ struct output_option { {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, {.str = "period", .field = PERF_OUTPUT_PERIOD}, {.str = "iregs", .field = PERF_OUTPUT_IREGS}, + {.str = "uregs", .field = PERF_OUTPUT_UREGS}, {.str = "brstack", .field = PERF_OUTPUT_BRSTACK}, {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM}, {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
@@ -385,6 +387,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, PERF_OUTPUT_IREGS))return -EINVAL ; +if (PRINT_FIELD (UREGS ) && +perf_evsel__check_stype (evsel,PERF_SAMPLE_REGS_USER ,"UREGS" , +PERF_OUTPUT_UREGS )) +return -EINVAL ; +if (PRINT_FIELD (PHYS_ADDR ) &&perf_evsel__check_stype (evsel,PERF_SAMPLE_PHYS_ADDR ,"PHYS_ADDR" ,PERF_OUTPUT_PHYS_ADDR ))
@@ -509,6 +516,24 @@ static void print_sample_iregs(struct perf_sample *sample, } } +static void print_sample_uregs (struct perf_sample *sample, +struct perf_event_attr *attr) +{ +struct regs_dump *regs = &sample->user_regs; +uint64_t mask = attr->sample_regs_user; +unsigned i =0 , r; + +if (!regs || !regs->regs) +return ; + +printf (" ABI:%" PRIu64" " , regs->abi); + +for_each_set_bit (r, (unsigned long *) &mask,sizeof (mask) *8 ) { +u64 val = regs->regs[i++]; +printf ("%5s:0x%" PRIx64" " ,perf_reg_name (r), val); + } +} +static void print_sample_start (struct perf_sample *sample,struct thread *thread,struct perf_evsel *evsel)
@@ -1444,6 +1469,9 @@ static void process_event(struct perf_script *script,if (PRINT_FIELD (IREGS ))print_sample_iregs (sample, attr); +if (PRINT_FIELD (UREGS )) +print_sample_uregs (sample, attr); +if (PRINT_FIELD (BRSTACK ))print_sample_brstack (sample, thread, attr);else if (PRINT_FIELD (BRSTACKSYM ))
@@ -2739,7 +2767,7 @@ int cmd_script(int argc, const char **argv) "+field to add and -field to remove." "Valid types: hw,sw,trace,raw,synth. " "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," - "addr,symoff,period,iregs,brstack,brstacksym,flags," + "addr,symoff,period,iregs,uregs,brstack,brstacksym,flags," "bpf-output,callindent,insn,insnlen,brstackinsn,synth,phys_addr", parse_output_fields), OPT_BOOLEAN('a', "all-cpus", &system_wide,
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 15/44 perf tools: Add python-clean target
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
To be able to cleanup only python related binaries.
--- tools/perf/Makefile.perf | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
tools/perf/Makefile.perf +5 -3
@@ -173,7 +173,7 @@ AWK = awk # non-config cases config := 1 -NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc install-man install-html install-info install-pdf doc man html info pdf +NON_CONFIG_TARGETS := clean python-clean TAGS tags cscope help install-doc install-man install-html install-info install-pdf doc man html info pdf ifdef MAKECMDGOALS ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
@@ -802,7 +802,10 @@ config-clean: $(call QUIET_CLEAN, config) $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null -clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean +python-clean: + $(python-clean) + +clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean fixdep-clean python-clean $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete $(Q)$(RM) $(OUTPUT).config-detected
@@ -819,7 +822,6 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea $(OUTPUT)$(vhost_virtio_ioctl_array) \ $(OUTPUT)$(perf_ioctl_array) $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean - $(python-clean) # # To provide FEATURE-DUMP into $(FEATURE_DUMP_COPY)
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 16/44 perf ui progress: Add ui specific init function
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Adding ui specific init function allowing to setup the progress bar width based on current screen scales.
Adding TUI init function to get more grained update of the progress bar.
--- tools/perf/ui/progress.c | 2 ++ tools/perf/ui/progress.h | 1 + tools/perf/ui/tui/progress.c | 9 +++++++-- 3 files changed, 10 insertions(+), 2 deletions(-)
tools/perf/ui/progress.c +2 -0
@@ -34,6 +34,8 @@ void ui_progress__init(struct ui_progress *p, u64 total, const char *title) p->total = total; p->title = title; +if (ui_progress__ops->init) + ui_progress__ops->init (p); }void ui_progress__finish (void )
tools/perf/ui/progress.h +1 -0
@@ -14,6 +14,7 @@ void ui_progress__init(struct ui_progress *p, u64 total, const char *title);void ui_progress__update (struct ui_progress *p,u64 adv);struct ui_progress_ops { +void (*init)(struct ui_progress *p);void (*update)(struct ui_progress *p);void (*finish)(void ); };
tools/perf/ui/tui/progress.c +7 -2
@@ -5,6 +5,11 @@#include "tui.h" #include "../browser.h" +static void __tui_progress__init (struct ui_progress *p) +{ + p->next = p->step = p->total / (SLtt_Screen_Cols -2 ) ?:1 ; +} +static void tui_progress__update (struct ui_progress *p) {int bar, y;
@@ -49,8 +54,8 @@ static void tui_progress__finish(void)pthread_mutex_unlock (&ui__lock); } -static struct ui_progress_ops tui_progress__ops = -{ +static struct ui_progress_ops tui_progress__ops = { + .init = __tui_progress__init, .update = tui_progress__update, .finish = tui_progress__finish, };
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 17/44 perf ui progress: Add size info into progress bar
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
Adding the size values '[current/total]' into progress bar, to show more detailed progress of data reading.
Adding new ui_progress__init_size function to specify we want to display the size.
--- tools/perf/ui/progress.c | 4 +++- tools/perf/ui/progress.h | 11 ++++++++++- tools/perf/ui/tui/progress.c | 23 ++++++++++++++++++++++- tools/perf/util/session.c | 2 +- 4 files changed, 36 insertions(+), 4 deletions(-)
tools/perf/ui/progress.c +3 -1
@@ -27,12 +27,14 @@ void ui_progress__update(struct ui_progress *p, u64 adv) } } -void ui_progress__init (struct ui_progress *p,u64 total,const char *title) +void __ui_progress__init (struct ui_progress *p,u64 total, +const char *title,bool size) { p->curr =0 ; p->next = p->step = total /16 ?:1 ; p->total = total; p->title = title; + p->size = size;if (ui_progress__ops->init) ui_progress__ops->init (p);
tools/perf/ui/progress.h +10 -1
@@ -8,9 +8,18 @@ void ui_progress__finish(void);struct ui_progress {const char *title;u64 curr, next, step, total; +bool size; }; -void ui_progress__init (struct ui_progress *p,u64 total,const char *title); +void __ui_progress__init (struct ui_progress *p,u64 total, +const char *title,bool size); + +#define ui_progress__init (p, total, title) \ + __ui_progress__init(p, total, title, false) + +#define ui_progress__init_size (p, total, title) \ + __ui_progress__init(p, total, title, true) +void ui_progress__update (struct ui_progress *p,u64 adv);struct ui_progress_ops {
tools/perf/ui/tui/progress.c +22 -1
@@ -1,8 +1,10 @@ +#include <linux/kernel.h> #include "../cache.h" #include "../progress.h" #include "../libslang.h" #include "../ui.h" #include "tui.h" +#include "units.h" #include "../browser.h" static void __tui_progress__init (struct ui_progress *p)
@@ -10,8 +12,22 @@ static void __tui_progress__init(struct ui_progress *p) p->next = p->step = p->total / (SLtt_Screen_Cols -2 ) ?:1 ; } +static int get_title (struct ui_progress *p,char *buf,size_t size) +{ +char buf_cur[20 ]; +char buf_tot[20 ]; +int ret; + + ret =unit_number__scnprintf (buf_cur,sizeof (buf_cur), p->curr); + ret +=unit_number__scnprintf (buf_tot,sizeof (buf_tot), p->total); + +return ret +scnprintf (buf, size,"%s [%s/%s]" , + p->title, buf_cur, buf_tot); +} +static void tui_progress__update (struct ui_progress *p) { +char buf[100 ], *title = (char *) p->title;int bar, y;/* * FIXME: We should have a per UI backend way of showing progress,
@@ -23,13 +39,18 @@ static void tui_progress__update(struct ui_progress *p)if (p->total ==0 )return ; +if (p->size) { +get_title (p, buf,sizeof (buf)); + title = buf; + } +ui__refresh_dimensions (false);pthread_mutex_lock (&ui__lock); y = SLtt_Screen_Rows /2 -2 ;SLsmg_set_color (0 );SLsmg_draw_box (y,0 ,3 , SLtt_Screen_Cols);SLsmg_gotorc (y++,1 ); -SLsmg_write_string ((char *)p->title); +SLsmg_write_string (title);SLsmg_fill_region (y,1 ,1 , SLtt_Screen_Cols -2 ,' ' );SLsmg_set_color (HE_COLORSET_SELECTED ); bar = ((SLtt_Screen_Cols -2 ) * p->curr) / p->total;
tools/perf/util/session.c +1 -1
@@ -1847,7 +1847,7 @@ static int __perf_session__process_events(struct perf_session *session,if (data_offset + data_size < file_size) file_size = data_offset + data_size; -ui_progress__init (&prog, file_size,"Processing events..." ); +ui_progress__init_size (&prog, file_size,"Processing events..." ); mmap_size =MMAP_SIZE ;if (mmap_size > file_size) {
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 18/44 perf tools: Use scandir() to replace readdir()
In reply to Arnaldo Carvalho de MeloFrom: Kan Liang <[email protected]>
In perf_event__synthesize_threads() perf goes through all proc files serially by readdir.
scandir() does a snapshoot of /proc, which is multithreading friendly.
It's possible that some threads which are added during event synthesize. But the number of lost threads should be small. They should not impact the final analysis.
--- tools/perf/util/event.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-)
tools/perf/util/event.c +25 -20
@@ -683,12 +683,14 @@ int perf_event__synthesize_threads(struct perf_tool *tool,bool mmap_data, unsigned int proc_map_timeout) { - DIR *proc; -char proc_path[PATH_MAX ]; -struct dirent *dirent; union perf_event *comm_event, *mmap_event, *fork_event;union perf_event *namespaces_event; +char proc_path[PATH_MAX ]; +struct dirent **dirent;int err =-1 ; +char *end; +pid_t pid; +int n, i;if (machine__is_default_guest (machine))return 0 ;
@@ -712,29 +714,32 @@ int perf_event__synthesize_threads(struct perf_tool *tool, goto out_free_fork;snprintf (proc_path,sizeof (proc_path),"%s/proc" , machine->root_dir); - proc =opendir (proc_path); + n =scandir (proc_path, &dirent,0 , alphasort); -if (proc ==NULL ) +if (n <0 ) goto out_free_namespaces; -while ((dirent =readdir (proc)) !=NULL ) { -char *end; -pid_t pid =strtol (dirent->d_name, &end,10 ); - -if (*end)/* only interested in proper numerical dirents */ +for (i =0 ; i < n; i++) { +if (!isdigit (dirent[i]->d_name[0 ]))continue ; -/* -* We may race with exiting thread, so don't stop just because -* one thread couldn't be synthesized. -*/ -__event__synthesize_thread (comm_event, mmap_event, fork_event, - namespaces_event, pid,1 , process, - tool, machine, mmap_data, - proc_map_timeout); - } + pid = (pid_t )strtol (dirent[i]->d_name, &end,10 ); +/* only interested in proper numerical dirents */ +if (!*end) { +/* +* We may race with exiting thread, so don't stop just because +* one thread couldn't be synthesized. +*/ +__event__synthesize_thread (comm_event, mmap_event, fork_event, + namespaces_event, pid,1 , process, + tool, machine, mmap_data, + proc_map_timeout); + } +free (dirent[i]); + } +free (dirent); err =0 ; -closedir (proc); + out_free_namespaces:free (namespaces_event); out_free_fork:
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 19/44 perf config: Write a config file just once
In reply to Arnaldo Carvalho de MeloFrom: Taeung Song <[email protected]>
Currently set_config() can be repeatedly called for each input config on the below case:
$ perf config kmem.default=slab report.children=false ...
But it's a waste, so only once write a config file gathering all given config key=value pairs.
--- tools/perf/builtin-config.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
tools/perf/builtin-config.c +16 -6
@@ -34,8 +34,7 @@ static struct option config_options[] = { OPT_END() }; -static int set_config (struct perf_config_set *set,const char *file_name, -const char *var,const char *value) +static int set_config (struct perf_config_set *set,const char *file_name) {struct perf_config_section *section =NULL ;struct perf_config_item *item =NULL ;
@@ -49,7 +48,6 @@ static int set_config(struct perf_config_set *set, const char *file_name,if (!fp)return -1 ; -perf_config_set__collect (set, file_name, var, value);fprintf (fp,"%s\n" , first_line);/* overwrite configvariables */
@@ -161,6 +159,7 @@ int cmd_config(int argc, const char **argv)struct perf_config_set *set;char *user_config =mkpath ("%s/.perfconfig" ,getenv ("HOME" ));const char *config_filename; +bool changed = false; argc =parse_options (argc, argv, config_options, config_usage,PARSE_OPT_STOP_AT_NON_OPTION );
@@ -231,15 +230,26 @@ int cmd_config(int argc, const char **argv) goto out_err; } }else { -if (set_config (set, config_filename, var, value) <0 ) { -pr_err ("Failed to set '%s=%s' on %s\n" , - var, value, config_filename); +if (perf_config_set__collect (set, config_filename, + var, value) <0 ) { +pr_err ("Failed to add '%s=%s'\n" , + var, value);free (arg); goto out_err; } + changed = true; }free (arg); } + +if (!changed) +break ; + +if (set_config (set, config_filename) <0 ) { +pr_err ("Failed to set the configs on %s\n" , + config_filename); + goto out_err; + } } ret =0 ;
Signature · 1 line
2.13.5
Arnaldo Carvalho de Melo
maintainerPATCH 20/44 perf config: Allow creating empty config set for config file autogeneration
In reply to Arnaldo Carvalho de MeloFrom: Taeung Song <[email protected]>
When there isn't a config file (e.g. ~/.perfconfig) or it has nothing, the config set wasn't created.
If the config set does not exist, a config file can't be autogenerated.
So allow creating a empty config set in the above case, then we can support the config file autogeneration.
Before:
$ rm -f ~/.perfconfig $ perf config --user report.children=false
$ cat ~/.perfconfig cat: /root/.perfconfig: No such file or directory
But I think it should work even if there isn't a config file.
After:
$ rm -f ~/.perfconfig $ perf config --user report.children=false
$ cat ~/.perfconfig
# this file is auto-generated.
[report]
children = falseNOTE:
As a result, if perf_config_set__init() fails, it looks as if the config set isn't freed. But it isn't a problem. Because the config set will be freed by perf_config_set__delete() at the end of cmd_config().
--- tools/perf/util/config.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
tools/perf/util/config.c +1 -4
@@ -700,10 +700,7 @@ struct perf_config_set *perf_config_set__new(void)if (set) {INIT_LIST_HEAD (&set->sections); -if (perf_config_set__init (set) <0 ) { -perf_config_set__delete (set); - set =NULL ; - } +perf_config_set__init (set); }return set;
Signature · 1 line
2.13.5
Quoted 231 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
b130a699c07155a1d6ef7d971a5f3bf0e3818d5a:Merge tag 'perf-urgent-for-mingo-4.14-20170912' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxinto perf/urgent (2017-09-13 09:25:10 +0200)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-4.15-20170922for you to fetch changes up to
0a7c74eae307894c6c95316c382f118aef8481e8:perf tools: Provide mutex wrappers for pthreads rwlocks (2017-09-21 13:28:06 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:- Support direct --user-regs arguments in 'perf record', previously the only way to sample
PERF_SAMPLE_REGS_USERwas implicitly selecting it when recording callchains (Andi Kleen)- Support showing sampled user regs in 'perf script' (Andi Kleen)
- Introduce the concept of weak groups in 'perf stat': try to set up a group, but if it's not schedulable fallback to not using a group. That gives us the best of both worlds: groups if they work, but still a usable fallback if they don't. E.g: (Andi Kleen)
% perf stat -e '{branches,branch-misses,l1d.replacement,l2_lines_in.all,l2_rqsts.all_code_rd}:W' -a sleep 1
125,366,055 branches (80.02%) 9,208,402 branch-misses # 7.35% of all branches (80.01%) 24,560,249 l1d.replacement (80.00%) 43,174,971 l2_lines_in.all (80.05%) 31,891,457 l2_rqsts.all_code_rd (79.92%)- Support metrics in 'stat' and 'list'. A metric is a formula that uses multiple events to compute a higher level result (e.g. IPC). (Andi Kleen)
- Add Intel processors vendor event metrics JSON files (Andi Kleen)
- Add 'pid' and 'tid' options to 'perf sched timehist' (David Ahern)
- Generate 'behavior' string table from kernel headers, helps getting new parameters when synchronizing kernel headers, like
MADV_WIPEONFORKandMADV_KEEPONFORK, that are now beautied (Arnaldo Carvalho de Melo)- Improve TUI progress bar by showing how many bytes from a total were processed (Jiri Olsa)
- Use
scandir()to replacereaddir(), prep work to have the synthesizing ofPERF_RECORD_entries for existing threads be multithreaded, making 'perf top' bearable on high core count systems such as Intel's Knights Landing/Mill (Kan Liang)- Allow creating a ~/.perfconfig file when setting a variable to its default value, previously it would bail out and not write such a file (Taeung Song)
- Introduce wrapper for allowing purely single threaded apps to avoid the costs of locking (Arnaldo Carvalho de Melo)
- Introduce hashtable to reduce the cost of thread lookup
- Fix build C++ build wrt
poison.husing void pointer arithmetic, affects only the embedded clang/llvm case, that is disabled by default (Arnaldo Carvalho de Melo)- Fix leaking
rec_argvin error cases (Martin Kepplinger)- Remove Intel CQM perf test, that infrastructure was nuked (Xiaochen Shen)
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Andi Kleen (27):
perf tools: Support weak groups in 'perf stat'
perf vendor events: Supportmetric_groupand no event name in JSON parser perf stat: Factor out generic metric printing
perf stat: Print generic metric header even for failed expressions perf pmu: Extract function to get JSON alias map
perf stat: Support JSON metrics in perf stat
perf list: Add metric groups to perf list
perf stat: Don't use ctx for saved values lookup
perf stat: Supportduration_timefor metrics
perf stat: Hide internalduration_timecounter
perf stat: Updatewalltime_nsecs_statsin interval mode
perf record: Support direct --user-regs arguments
perf script: Support user regs
perf stat: Fall weak group back even for EBADF
perf vendor events: Add JSON metrics for Broadwell
perf vendor events: Add JSON metrics for Skylake
perf vendor events: Add JSON metrics for Sandy Bridge
perf vendor events: Add JSON metrics for Sandy Bridge EP perf vendor events: Add JSON metrics for Ivy Bridge
perf vendor events: Add JSON metrics for Haswell
perf vendor events: Add JSON metrics for Ivy Town
perf vendor events: Add JSON metrics for Haswell EP
perf vendor events: Add JSON metrics for Broadwell Server perf vendor events: Add JSON metrics for Broadwell DE
perf vendor events: Add JSON metrics for Skylake server
perf pmu: Improve error messages for missing PMUs
perf stat: Fix adding multiple event groupsArnaldo Carvalho de Melo (7):
perf tools: Makecopyfile_offset()static
perf machine: Optimize a bit themachine__findnew_thread()methods perf trace beauty madvise: Generate 'behavior' string table from kernel headers
tools: Updateasm-generic/mman-common.hcopy from the kernel
perf tools: Get all oftools/{arch,include}/in the MANIFEST tools include: Do not use poison with C++
perf tools: Provide mutex wrappers for pthreads rwlocksDavid Ahern (1):
perf sched timehist: Add pid and tid optionsJiri Olsa (3):
perf tools: Add python-clean target
perf ui progress: Add ui specific init function perf ui progress: Add size info into progress barKan Liang (2):
perf tools: Usescandir()to replacereaddir()perf machine: Use hashtable for machine threadsMartin Kepplinger (1):
perf tools: Fix leakingrec_argvin error casesTaeung Song (2):
perf config: Write a config file just once
perf config: Allow creating empty config set for config file autogenerationXiaochen Shen (1):
perf tests: Remove Intel CQM perf testtools/include/linux/poison.h | 5 + tools/include/uapi/asm-generic/mman-common.h | 14 +- tools/perf/Documentation/perf-list.txt | 9 +- tools/perf/Documentation/perf-record.txt | 2 + tools/perf/Documentation/perf-sched.txt | 8 + tools/perf/Documentation/perf-script.txt | 4 +- tools/perf/Documentation/perf-stat.txt | 7 + tools/perf/MANIFEST | 87 +--- tools/perf/Makefile.perf | 17 +- tools/perf/arch/x86/include/arch-tests.h | 1 - tools/perf/arch/x86/tests/Build | 1 - tools/perf/arch/x86/tests/arch-tests.c | 4 - tools/perf/arch/x86/tests/intel-cqm.c | 127 ------ tools/perf/builtin-c2c.c | 1 + tools/perf/builtin-config.c | 22 +- tools/perf/builtin-kvm.c | 1 - tools/perf/builtin-list.c | 7 + tools/perf/builtin-mem.c | 1 + tools/perf/builtin-record.c | 3 + tools/perf/builtin-sched.c | 4 + tools/perf/builtin-script.c | 32 +- tools/perf/builtin-stat.c | 82 +++- tools/perf/builtin-timechart.c | 4 +- tools/perf/builtin-trace.c | 20 +- tools/perf/perf.h | 1 + .../pmu-events/arch/x86/broadwell/bdw-metrics.json | 164 +++++++ .../arch/x86/broadwellde/bdwde-metrics.json | 164 +++++++ .../arch/x86/broadwellx/bdx-metrics.json | 164 +++++++ .../pmu-events/arch/x86/haswell/hsw-metrics.json | 158 +++++++ .../pmu-events/arch/x86/haswellx/hsx-metrics.json | 158 +++++++ .../pmu-events/arch/x86/ivybridge/ivb-metrics.json | 164 +++++++ .../pmu-events/arch/x86/ivytown/ivt-metrics.json | 164 +++++++ .../pmu-events/arch/x86/jaketown/jkt-metrics.json | 140 ++++++ .../arch/x86/sandybridge/snb-metrics.json | 140 ++++++ .../pmu-events/arch/x86/skylake/skl-metrics.json | 164 +++++++ .../pmu-events/arch/x86/skylakex/skx-metrics.json | 182 ++++++++ tools/perf/pmu-events/jevents.c | 24 +- tools/perf/pmu-events/jevents.h | 2 +- tools/perf/pmu-events/pmu-events.h | 1 + tools/perf/tests/builtin-test.c | 1 + tools/perf/trace/beauty/madvise_behavior.sh | 10 + tools/perf/trace/beauty/mmap.c | 38 +- tools/perf/ui/progress.c | 6 +- tools/perf/ui/progress.h | 12 +- tools/perf/ui/tui/progress.c | 32 +- tools/perf/util/Build | 2 + tools/perf/util/config.c | 5 +- tools/perf/util/data.c | 1 + tools/perf/util/dso.c | 13 +- tools/perf/util/dso.h | 4 +- tools/perf/util/event.c | 46 +- tools/perf/util/evlist.h | 1 + tools/perf/util/evsel.c | 7 +- tools/perf/util/evsel.h | 1 + tools/perf/util/machine.c | 155 ++++--- tools/perf/util/machine.h | 24 +- tools/perf/util/map.c | 34 +- tools/perf/util/map.h | 3 +- tools/perf/util/metricgroup.c | 490 +++++++++++++++++++++ tools/perf/util/metricgroup.h | 31 ++ tools/perf/util/namespaces.c | 1 + tools/perf/util/parse-events.c | 29 +- tools/perf/util/parse-events.h | 3 + tools/perf/util/parse-events.l | 3 +- tools/perf/util/pmu.c | 55 ++- tools/perf/util/pmu.h | 2 + tools/perf/util/probe-file.c | 1 + tools/perf/util/rb_resort.h | 5 +- tools/perf/util/rwsem.c | 32 ++ tools/perf/util/rwsem.h | 19 + tools/perf/util/session.c | 2 +- tools/perf/util/stat-shadow.c | 110 +++-- tools/perf/util/stat.h | 4 +- tools/perf/util/symbol.c | 8 +- tools/perf/util/thread.c | 4 +- tools/perf/util/trace-event-info.c | 1 - tools/perf/util/trace-event-read.c | 1 - tools/perf/util/util.c | 16 +- tools/perf/util/util.h | 7 +- tools/perf/util/vdso.c | 4 +- tools/perf/util/zlib.c | 1 + 81 files changed, 2988 insertions(+), 489 deletions(-) delete mode 100644 tools/perf/arch/x86/tests/intel-cqm.c create mode 100644 tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json
Quoted 8 lines
create mode 100644 tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json create mode 100644 tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json create mode 100755 tools/perf/trace/beauty/madvise_behavior.sh create mode 100644 tools/perf/util/metricgroup.c create mode 100644 tools/perf/util/metricgroup.h create mode 100644 tools/perf/util/rwsem.c create mode 100644 tools/perf/util/rwsem.h
Pulled, thanks a lot Arnaldo!
Ingo