perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling, it has my latest perf/urgent pull content,
please let me know if you don't want it to be submitted like that, i.e. if you have any problems with my latest perf/urgent pull request and I'll try to address it ASAP.
- Arnaldo
The following changes since commit 25dd9171f51c482eb7c4dc8618766ae733756e2d:
perf probe: Fix probing kretprobes (2015-01-21 10:06:24 -0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
for you to fetch changes up to 3d199b5be53348bef84883013c484b414adf0a2e:
tools lib traceevent: Add support for IP address formats (2015-01-26 12:04:41 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Enable sampling loads and stores simultaneously in 'perf mem' (Stephane Eranian)
- 'perf diff' output improvements (Namhyung Kim)
- Fix error reporting for evsel pgfault constructor (Arnaldo Carvalho de Melo)
Infrastructure:
- Move debugfs sterrno like method to tools/lib/ so that it may be used by other tools, as 'perf probe' will be soon (Arnaldo Carvalho de Melo)
- Introduce function fro deleting/removing hist_entry to avoid code duplication (Arnaldo Carvalho de Melo)
- Support parsing parameterized events (Cody P Schafer)
- Add support for IP address formats in libtraceevent (David Ahern)
- Fix typo in sample-parsing.c 'perf test' entry (Rasmus Villemoes)
- Remove some unused functions from color.c (Rickard Strandqvist)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (9):
perf mem: Move the mem_operations global to struct perf_mem perf tools: Remove EOL whitespaces
perf hists: Rename hist_entry__free to __delete
perf hists: Introduce function for deleting/removing hist_entry tools lib fs: Adopt debugfs open strerrno method
tools lib fs: Pass filename to debugfs__strerror_open
perf trace: Fix error reporting for evsel pgfault constructor tools lib fs debugfs: Introduce debugfs__strerror_open_tp tools lib fs debugfs: Check if debugfs is mounted when handling ENOENT
Cody P Schafer (4):
perf tools: Support parsing parameterized events perf tools: Extend format_alias() to include event parameters perf Documentation: Add event parameters
perf tools: Document parameterized and symbolic events
David Ahern (1):
tools lib traceevent: Add support for IP address formats
Namhyung Kim (9):
perf report: Get rid of report__inc_stat()
perf tools: Allow use of an exclusive option more than once perf diff: Get rid of hists__compute_resort() perf diff: Print diff result more precisely
perf diff: Introduce fmt_to_data_file() helper perf tools: Pass struct perf_hpp_fmt to its callbacks perf diff: Fix output ordering to honor next column perf diff: Fix -o/--order option behavior
perf ui/tui: Show fatal error message only if exists
Rasmus Villemoes (1):
perf tests: Fix typo in sample-parsing.c
Rickard Strandqvist (1):
perf tools: Remove some unused functions from color.c
Stephane Eranian (1):
perf mem: Enable sampling loads and stores simultaneously
.../testing/sysfs-bus-event_source-devices-events | 6 + tools/lib/api/fs/debugfs.c | 43 +++ tools/lib/api/fs/debugfs.h | 3 + tools/lib/traceevent/event-parse.c | 328 +++++++++++++++++++++ tools/perf/Documentation/perf-buildid-cache.txt | 2 +- tools/perf/Documentation/perf-list.txt | 13 + tools/perf/Documentation/perf-mem.txt | 9 +- tools/perf/Documentation/perf-record.txt | 12 + tools/perf/Documentation/perf-script.txt | 28 +- tools/perf/Documentation/perf-stat.txt | 20 +- tools/perf/builtin-buildid-cache.c | 4 +- tools/perf/builtin-diff.c | 248 ++++++++++------ tools/perf/builtin-mem.c | 131 ++++++-- tools/perf/builtin-report.c | 16 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 106 ++++--- tools/perf/tests/attr.py | 1 - tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_output.c | 2 +- tools/perf/tests/make | 1 - tools/perf/tests/parse-events.c | 2 +- tools/perf/tests/sample-parsing.c | 2 +- tools/perf/ui/browsers/annotate.c | 3 +- tools/perf/ui/hist.c | 12 +- tools/perf/ui/progress.h | 4 +- tools/perf/ui/tui/helpline.c | 3 + tools/perf/ui/tui/setup.c | 3 +- tools/perf/util/annotate.c | 2 +- tools/perf/util/color.c | 126 -------- tools/perf/util/color.h | 2 - tools/perf/util/evlist.c | 27 -- tools/perf/util/evlist.h | 1 - tools/perf/util/hist.c | 48 ++- tools/perf/util/hist.h | 11 +- tools/perf/util/parse-events.c | 6 +- tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-options.c | 2 +- tools/perf/util/pmu.c | 102 ++++++- tools/perf/util/python.c | 2 +- .../util/scripting-engines/trace-event-python.c | 2 +- tools/perf/util/session.c | 2 +- tools/perf/util/sort.c | 37 ++- tools/perf/util/symbol.c | 2 +- 44 files changed, 950 insertions(+), 431 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/26 perf mem: Enable sampling loads and stores simultaneously
From: Stephane Eranian <[email protected]>
This patch modifies perf mem to default to sampling loads and stores simultaneously. It could only do one or the other before yet there was no hardware restriction preventing simultaneous collection. With this patch, one run is sufficient to collect both.
It is still possible to sample only loads or stores by using the -t option:
$ perf mem -t load rec $ perf mem -t load rep Or $ perf mem -t store rec $ perf mem -t store rep
The perf report TUI will show one event at a time. The store output will contain a Weight column which will be empty.
In V2, we updated the man pages to reflect the change and also simplify the initialization of the argv vector passed to the cmd_*() functions as per LKML feedback.
In V3, we fixed typos in the changelog.
--- tools/perf/Documentation/perf-mem.txt | 9 +-- tools/perf/builtin-mem.c | 123 +++++++++++++++++++++++++++------- 2 files changed, 105 insertions(+), 27 deletions(-)
tools/perf/Documentation/perf-mem.txt +5 -4
@@ -12,11 +12,12 @@ SYNOPSIS DESCRIPTION ----------- -"perf mem -t <TYPE> record" runs a command and gathers memory operation data +"perf mem record" runs a command and gathers memory operation data from it, into perf.data. Perf record options are accepted and are passed through. -"perf mem -t <TYPE> report" displays the result. It invokes perf report with the -right set of options to display a memory access profile. +"perf mem report" displays the result. It invokes perf report with the +right set of options to display a memory access profile. By default, loads +and stores are sampled. Use the -t option to limit to loads or stores. Note that on Intel systems the memory latency reported is the use-latency, not the pure load (or store latency). Use latency includes any pipeline
@@ -29,7 +30,7 @@ OPTIONS -t:: --type=:: - Select the memory operation type: load or store (default: load) + Select the memory operation type: load or store (default: load,store) -D:: --dump-raw-samples=::
tools/perf/builtin-mem.c +100 -23
167 lines not on this page · raw message
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/26 perf mem: Move the mem_operations global to struct perf_mem
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Just like the other parameters, grouping it on the builtin-mem specific config area: struct perf_mem.
--- tools/perf/builtin-mem.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
tools/perf/builtin-mem.c +13 -13
@@ -10,21 +10,17 @@#define MEM_OPERATION_LOAD 0x1#define MEM_OPERATION_STORE 0x2 -/* -* default to both load an store sampling -*/ -static int mem_operation =MEM_OPERATION_LOAD |MEM_OPERATION_STORE ; -struct perf_mem {struct perf_tool tool;char const *input_name;bool hide_unresolved;bool dump_raw; +int operation;const char *cpu_list; DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); }; -static int __cmd_record (int argc,const char **argv) +static int __cmd_record (int argc,const char **argv,struct perf_mem *mem) {int rec_argc, i =0 , j;const char **rec_argv;
@@ -37,17 +33,17 @@ static int __cmd_record(int argc, const char **argv) rec_argv[i++] ="record" ; -if (mem_operation &MEM_OPERATION_LOAD ) +if (mem->operation &MEM_OPERATION_LOAD ) rec_argv[i++] ="-W" ; rec_argv[i++] ="-d" ; -if (mem_operation &MEM_OPERATION_LOAD ) { +if (mem->operation &MEM_OPERATION_LOAD ) { rec_argv[i++] ="-e" ; rec_argv[i++] ="cpu/mem-loads/pp" ; } -if (mem_operation &MEM_OPERATION_STORE ) { +if (mem->operation &MEM_OPERATION_STORE ) { rec_argv[i++] ="-e" ; rec_argv[i++] ="cpu/mem-stores/pp" ; }
@@ -177,7 +173,7 @@ static int report_events(int argc, const char **argv, struct perf_mem *mem)* there is no weight (cost) associated with stores, so don't print * the column */ -if (!(mem_operation &MEM_OPERATION_LOAD )) +if (!(mem->operation &MEM_OPERATION_LOAD )) rep_argv[i++] ="--sort=mem,sym,dso,symbol_daddr," "dso_daddr,tlb,locked" ;
@@ -273,9 +269,13 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) .ordered_events = true, }, .input_name = "perf.data", +/* +* default to both load an store sampling +*/ + .operation = MEM_OPERATION_LOAD | MEM_OPERATION_STORE, };const struct option mem_options[] = { -OPT_CALLBACK ('t' ,"type" , &mem_operation, +OPT_CALLBACK ('t' ,"type" , &mem.operation,"type" ,"memory operations(load,store) Default load,store" , parse_mem_ops), OPT_BOOLEAN('D', "dump-raw-samples", &mem.dump_raw,
@@ -302,7 +302,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) argc =parse_options_subcommand (argc, argv, mem_options, mem_subcommands, mem_usage,PARSE_OPT_STOP_AT_NON_OPTION ); -if (!argc || !(strncmp (argv[0 ],"rec" ,3 ) || mem_operation)) +if (!argc || !(strncmp (argv[0 ],"rec" ,3 ) || mem.operation))usage_with_options (mem_usage, mem_options);if (!mem.input_name || !strlen (mem.input_name)) {
@@ -313,7 +313,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) }if (!strncmp (argv[0 ],"rec" ,3 )) -return __cmd_record (argc, argv); +return __cmd_record (argc, argv, &mem);else if (!strncmp (argv[0 ],"rep" ,3 ))return report_events (argc, argv, &mem);else
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/26 perf tools: Remove EOL whitespaces
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Janitorial stuff: boredom moment.
--- tools/perf/Documentation/perf-buildid-cache.txt | 2 +- tools/perf/Documentation/perf-script.txt | 28 ++++---- tools/perf/builtin-buildid-cache.c | 4 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 80 +++++++++++----------- tools/perf/tests/attr.py | 1 - tools/perf/tests/make | 1 - tools/perf/tests/parse-events.c | 2 +- tools/perf/ui/browsers/annotate.c | 3 +- tools/perf/ui/progress.h | 4 +- tools/perf/util/annotate.c | 2 +- tools/perf/util/parse-events.c | 6 +- tools/perf/util/python.c | 2 +- .../util/scripting-engines/trace-event-python.c | 2 +- tools/perf/util/session.c | 2 +- tools/perf/util/symbol.c | 2 +- 17 files changed, 71 insertions(+), 74 deletions(-)
tools/perf/Documentation/perf-buildid-cache.txt +1 -1
@@ -38,7 +38,7 @@ OPTIONS --remove=:: Remove specified file from the cache. -M:: ---missing=:: +--missing=:: List missing build ids in the cache for the specified file. -u:: --update::
tools/perf/Documentation/perf-script.txt +14 -14
@@ -125,46 +125,46 @@ OPTIONS is equivalent to: perf script -f trace:<fields> -f sw:<fields> -f hw:<fields> - + i.e., the specified fields apply to all event types if the type string is not given. - + The arguments are processed in the order received. A later usage can reset a prior request. e.g.: - + -f trace: -f comm,tid,time,ip,sym - + The first -f suppresses trace events (field list is ""), but then the second invocation sets the fields to comm,tid,time,ip,sym. In this case a warning is given to the user: - + "Overriding previous field request for all events." - + Alternatively, consider the order: - + -f comm,tid,time,ip,sym -f trace: - + The first -f sets the fields for all events and the second -f suppresses trace events. The user is given a warning message about the override, and the result of the above is that only S/W and H/W events are displayed with the given fields. - + For the 'wildcard' option if a user selected field is invalid for an event type, a message is displayed to the user that the option is ignored for that type. For example: - + $ perf script -f comm,tid,trace 'trace' not valid for hardware events. Ignoring. 'trace' not valid for software events. Ignoring. - + Alternatively, if the type is given an invalid field is specified it is an error. For example: - + perf script -v -f sw:comm,tid,trace 'trace' not valid for software events. - + At this point usage is displayed, and perf-script exits. - + Finally, a user may not set fields to none for all event types. i.e., -f "" is not allowed.
tools/perf/builtin-buildid-cache.c +2 -2
@@ -236,10 +236,10 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)if (errno ==ENOENT )return false; -pr_warning ("Problems with %s file, consider removing it from the cache\n" , +pr_warning ("Problems with %s file, consider removing it from the cache\n" , filename); }else if (memcmp (dso->build_id, build_id,sizeof (dso->build_id))) { -pr_warning ("Problems with %s file, consider removing it from the cache\n" , +pr_warning ("Problems with %s file, consider removing it from the cache\n" , filename); }
tools/perf/builtin-stat.c +1 -1
@@ -1730,7 +1730,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) "detailed run - start a lot of events"),OPT_BOOLEAN ('S' ,"sync" , &sync_run,"call sync() before starting a run" ), -OPT_CALLBACK_NOOPT ('B' ,"big-num" ,NULL ,NULL , +OPT_CALLBACK_NOOPT ('B' ,"big-num" ,NULL ,NULL ,"print large numbers with thousands\' separators" , stat__set_big_num), OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
tools/perf/builtin-top.c +1 -1
@@ -165,7 +165,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip) err ? "[unknown]" : uts.release, perf_version_string);if (use_browser <=0 )sleep (5 ); - + map->erange_warned = true; }
tools/perf/builtin-trace.c +40 -40
188 lines not on this page · raw message
tools/perf/tests/attr.py +0 -1
@@ -104,7 +104,6 @@ class Event(dict): continue if not self.compare_data(self[t], other[t]): log.warning("expected %s=%s, got %s" % (t, self[t], other[t])) - # Test file description needs to have following sections: # [config]
tools/perf/tests/make +0 -1
@@ -222,7 +222,6 @@ tarpkg: @cmd="$(PERF)/tests/perf-targz-src-pkg $(PERF)"; \ echo "- $@: $$cmd" && echo $$cmd > $@ && \ ( eval $$cmd ) >> $@ 2>&1 - all: $(run) $(run_O) tarpkg @echo OK
tools/perf/tests/parse-events.c +1 -1
@@ -1471,7 +1471,7 @@ static int test_event(struct evlist_test *e) }else { ret = e->check (evlist); } - +perf_evlist__delete (evlist);return ret;
tools/perf/ui/browsers/annotate.c +1 -2
@@ -517,7 +517,7 @@ static bool annotate_browser__jump(struct annotate_browser *browser) }annotate_browser__set_top (browser, dl, idx); - +return true; }
@@ -867,7 +867,6 @@ static void annotate_browser__mark_jump_targets(struct annotate_browser *browser ++browser->nr_jumps; } - }static inline int width_jumps (int n)
tools/perf/ui/progress.h +2 -2
@@ -4,12 +4,12 @@#include <linux/types.h> void ui_progress__finish (void ); - +struct ui_progress {const char *title;u64 curr, next, step, total; }; - +void ui_progress__init (struct ui_progress *p,u64 total,const char *title);void ui_progress__update (struct ui_progress *p,u64 adv);
tools/perf/util/annotate.c +1 -1
@@ -239,7 +239,7 @@ static int mov__parse(struct ins_operands *ops) *s ='\0' ; ops->source.raw =strdup (ops->raw); *s =',' ; - +if (ops->source.raw ==NULL )return -1 ;
tools/perf/util/parse-events.c +3 -3
@@ -1121,7 +1121,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,return ;for_each_subsystem (sys_dir, sys_dirent, sys_next) { -if (subsys_glob !=NULL && +if (subsys_glob !=NULL && !strglobmatch (sys_dirent.d_name, subsys_glob))continue ;
@@ -1132,7 +1132,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,continue ;for_each_event (sys_dirent, evt_dir, evt_dirent, evt_next) { -if (event_glob !=NULL && +if (event_glob !=NULL && !strglobmatch (evt_dirent.d_name, event_glob))continue ;
@@ -1305,7 +1305,7 @@ static void print_symbol_events(const char *event_glob, unsigned type,for (i =0 ; i < max; i++, syms++) { -if (event_glob !=NULL && +if (event_glob !=NULL && !(strglobmatch (syms->symbol, event_glob) || (syms->alias &&strglobmatch (syms->alias, event_glob))))continue ;
tools/perf/util/python.c +1 -1
@@ -768,7 +768,7 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,Py_DECREF (file); goto free_list; } - +Py_DECREF (file); }
tools/perf/util/scripting-engines/trace-event-python.c +1 -1
@@ -89,7 +89,7 @@ static void handler_call_die(const char *handler_name)/* * Insert val into into the dictionary and decrement the reference counter. -* This is necessary for dictionaries since PyDict_SetItemString() does not +* This is necessary for dictionaries since PyDict_SetItemString() does not * steal a reference, as opposed to PyTuple_SetItem(). */ static void pydict_set_item_string_decref (PyObject *dict,const char *key,PyObject *val)
tools/perf/util/session.c +1 -1
@@ -274,7 +274,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)if (tool->id_index ==NULL ) tool->id_index = process_id_index_stub; } - +static void swap_sample_id_all (union perf_event *event,void *data) {void *end = (void *) event + event->header.size;
tools/perf/util/symbol.c +1 -1
@@ -685,7 +685,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,struct machine *machine = kmaps->machine;struct map *curr_map = map;struct symbol *pos; -int count =0 , moved =0 ; +int count =0 , moved =0 ;struct rb_root *root = &dso->symbols[map->type];struct rb_node *next =rb_first (root);int kernel_range =0 ;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 4/26 perf hists: Rename hist_entry__free to __delete
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
No logic changes, just to be consistent.
--- tools/perf/builtin-diff.c | 2 +- tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_output.c | 2 +- tools/perf/util/hist.c | 8 ++++---- tools/perf/util/hist.h | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-)
tools/perf/builtin-diff.c +1 -1
@@ -430,7 +430,7 @@ static void hists__baseline_only(struct hists *hists) next =rb_next (&he->rb_node_in);if (!hist_entry__next_pair (he)) {rb_erase (&he->rb_node_in, root); -hist_entry__free (he); +hist_entry__delete (he); } } }
tools/perf/tests/hists_cumulate.c +1 -1
@@ -140,7 +140,7 @@ static void del_hist_entries(struct hists *hists) he = rb_entry(node, struct hist_entry, rb_node);rb_erase (node, root_out);rb_erase (&he->rb_node_in, root_in); -hist_entry__free (he); +hist_entry__delete (he); } }
tools/perf/tests/hists_output.c +1 -1
@@ -106,7 +106,7 @@ static void del_hist_entries(struct hists *hists) he = rb_entry(node, struct hist_entry, rb_node);rb_erase (node, root_out);rb_erase (&he->rb_node_in, root_in); -hist_entry__free (he); +hist_entry__delete (he); } }
tools/perf/util/hist.c +4 -4
@@ -267,7 +267,7 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)if (!n->filtered) --hists->nr_non_filtered_entries; -hist_entry__free (n); +hist_entry__delete (n); } } }
@@ -290,7 +290,7 @@ void hists__delete_entries(struct hists *hists)if (!n->filtered) --hists->nr_non_filtered_entries; -hist_entry__free (n); +hist_entry__delete (n); } }
@@ -941,7 +941,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)return cmp; } -void hist_entry__free (struct hist_entry *he) +void hist_entry__delete (struct hist_entry *he) {zfree (&he->branch_info);zfree (&he->mem_info);
@@ -981,7 +981,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, iter->callchain, he->callchain); } -hist_entry__free (he); +hist_entry__delete (he);return false; }
tools/perf/util/hist.h +1 -1
@@ -119,7 +119,7 @@ int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);int hist_entry__transaction_len (void );int hist_entry__sort_snprintf (struct hist_entry *he,char *bf,size_t size,struct hists *hists); -void hist_entry__free (struct hist_entry *); +void hist_entry__delete (struct hist_entry *he);void hists__output_resort (struct hists *hists,struct ui_progress *prog);void hists__collapse_resort (struct hists *hists,struct ui_progress *prog);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/26 perf hists: Introduce function for deleting/removing hist_entry
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
The code being used when decaying and deleting entries from a hists instance was the same, provide a function to avoid code dup.
--- tools/perf/util/hist.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-)
tools/perf/util/hist.c +16 -20
@@ -241,6 +241,20 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)return he->stat.period ==0 ; } +static void hists__delete_entry (struct hists *hists,struct hist_entry *he) +{ +rb_erase (&he->rb_node, &hists->entries); + +if (sort__need_collapse) +rb_erase (&he->rb_node_in, &hists->entries_collapsed); + + --hists->nr_entries; +if (!he->filtered) + --hists->nr_non_filtered_entries; + +hist_entry__delete (he); +} +void hists__decay_entries (struct hists *hists,bool zap_user,bool zap_kernel) {struct rb_node *next =rb_first (&hists->entries);
@@ -258,16 +272,7 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel) (zap_kernel && n->level != '.') || hists__decay_entry(hists, n)) && !n->used) { -rb_erase (&n->rb_node, &hists->entries); - -if (sort__need_collapse) -rb_erase (&n->rb_node_in, &hists->entries_collapsed); - - --hists->nr_entries; -if (!n->filtered) - --hists->nr_non_filtered_entries; - -hist_entry__delete (n); +hists__delete_entry (hists, n); } } }
@@ -281,16 +286,7 @@ void hists__delete_entries(struct hists *hists) n = rb_entry(next, struct hist_entry, rb_node); next =rb_next (&n->rb_node); -rb_erase (&n->rb_node, &hists->entries); - -if (sort__need_collapse) -rb_erase (&n->rb_node_in, &hists->entries_collapsed); - - --hists->nr_entries; -if (!n->filtered) - --hists->nr_non_filtered_entries; - -hist_entry__delete (n); +hists__delete_entry (hists, n); } }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 6/26 perf report: Get rid of report__inc_stat()
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The report__inc_stat() function collects the number of hist entries in the session in order to calculate the max size of the progess bar.
It'd be better if it does it during the addition of hist entries so that it can be used by other places too.
--- tools/perf/builtin-report.c | 16 +++------------- tools/perf/util/hist.c | 2 ++ 2 files changed, 5 insertions(+), 13 deletions(-)
tools/perf/builtin-report.c +3 -13
@@ -86,17 +86,6 @@ static int report__config(const char *var, const char *value, void *cb)return perf_default_config (var, value, cb); } -static void report__inc_stats (struct report *rep,struct hist_entry *he) -{ -/* -* The @he is either of a newly created one or an existing one -* merging current sample. We only want to count a new one so -* checking ->nr_events being 1. -*/ -if (he->stat.nr_events ==1 ) - rep->nr_entries++; -} -static int hist_iter__report_callback (struct hist_entry_iter *iter,struct addr_location *al,bool single,void *arg)
@@ -108,8 +97,6 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,struct mem_info *mi;struct branch_info *bi; -report__inc_stats (rep, he); -if (!ui__has_annotation ())return 0 ;
@@ -499,6 +486,9 @@ static int __cmd_report(struct report *rep)report__warn_kptr_restrict (rep); +evlist__for_each (session->evlist, pos) + rep->nr_entries +=evsel__hists (pos)->nr_entries; +if (use_browser ==0 ) {if (verbose >3 )perf_session__fprintf (session, stdout);
tools/perf/util/hist.c +2 -0
@@ -429,6 +429,8 @@ static struct hist_entry *add_hist_entry(struct hists *hists,if (!he)return NULL ; + hists->nr_entries++; +rb_link_node (&he->rb_node_in, parent, p);rb_insert_color (&he->rb_node_in, hists->entries_in); out:
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 7/26 perf tools: Remove some unused functions from color.c
In reply to Arnaldo Carvalho de MeloFrom: Rickard Strandqvist <[email protected]>
Removes some functions that are not used anywhere:
color_parse_mem()
color_parse()
This was partially found by using a static code analysis program called cppcheck.
--- tools/perf/util/color.c | 126 ------------------------------------------------ tools/perf/util/color.h | 2 - 2 files changed, 128 deletions(-)
tools/perf/util/color.c +0 -126
@@ -5,132 +5,6 @@int perf_use_color_default =-1 ; -static int parse_color (const char *name,int len) -{ -static const char *const color_names[] = { -"normal" ,"black" ,"red" ,"green" ,"yellow" , -"blue" ,"magenta" ,"cyan" ,"white" - }; -char *end; -int i; - -for (i =0 ; i < (int )ARRAY_SIZE (color_names); i++) { -const char *str = color_names[i]; -if (!strncasecmp (name, str, len) && !str[len]) -return i -1 ; - } - i =strtol (name, &end,10 ); -if (end - name == len && i >=-1 && i <=255 ) -return i; -return -2 ; -} - -static int parse_attr (const char *name,int len) -{ -static const int attr_values[] = {1 ,2 ,4 ,5 ,7 }; -static const char *const attr_names[] = { -"bold" ,"dim" ,"ul" ,"blink" ,"reverse" - }; -unsigned int i; - -for (i =0 ; i <ARRAY_SIZE (attr_names); i++) { -const char *str = attr_names[i]; -if (!strncasecmp (name, str, len) && !str[len]) -return attr_values[i]; - } -return -1 ; -} - -void color_parse (const char *value,const char *var,char *dst) -{ -color_parse_mem (value,strlen (value), var, dst); -} - -void color_parse_mem (const char *value,int value_len,const char *var, -char *dst) -{ -const char *ptr = value; -int len = value_len; -int attr =-1 ; -int fg =-2 ; -int bg =-2 ; - -if (!strncasecmp (value,"reset" , len)) { -strcpy (dst,PERF_COLOR_RESET ); -return ; - } - -/* [fg [bg]] [attr] */ -while (len >0 ) { -const char *word = ptr; -int val, wordlen =0 ; - -while (len >0 && !isspace (word[wordlen])) { - wordlen++; - len--; - } - - ptr = word + wordlen; -while (len >0 &&isspace (*ptr)) { - ptr++; - len--; - } - - val =parse_color (word, wordlen); -if (val >=-1 ) { -if (fg ==-2 ) { - fg = val; -continue ; - } -if (bg ==-2 ) { - bg = val; -continue ; - } - goto bad; - } - val =parse_attr (word, wordlen); -if (val <0 || attr !=-1 ) - goto bad; - attr = val; - } - -if (attr >=0 || fg >=0 || bg >=0 ) { -int sep =0 ; - - *dst++ ='\033' ; - *dst++ ='[' ; -if (attr >=0 ) { - *dst++ ='0' + attr; - sep++; - } -if (fg >=0 ) { -if (sep++) - *dst++ =';' ; -if (fg <8 ) { - *dst++ ='3' ; - *dst++ ='0' + fg; - }else { - dst +=sprintf (dst,"38;5;%d" , fg); - } - } -if (bg >=0 ) { -if (sep++) - *dst++ =';' ; -if (bg <8 ) { - *dst++ ='4' ; - *dst++ ='0' + bg; - }else { - dst +=sprintf (dst,"48;5;%d" , bg); - } - } - *dst++ ='m' ; - } - *dst =0 ; -return ; -bad: -die ("bad color value '%.*s' for variable '%s'" , value_len, value, var); -} -int perf_config_colorbool (const char *var,const char *value,int stdout_is_tty) {if (value) {
tools/perf/util/color.h +0 -2
@@ -30,8 +30,6 @@ extern int perf_use_color_default;int perf_color_default_config (const char *var,const char *value,void *cb);int perf_config_colorbool (const char *var,const char *value,int stdout_is_tty); -void color_parse (const char *value,const char *var,char *dst); -void color_parse_mem (const char *value,int len,const char *var,char *dst);int color_vsnprintf (char *bf,size_t size,const char *color,const char *fmt,va_list args);int color_vfprintf (FILE *fp,const char *color,const char *fmt,va_list args);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 8/26 perf tools: Support parsing parameterized events
In reply to Arnaldo Carvalho de MeloFrom: Cody P Schafer <[email protected]>
Enable event specification like:
pmu/event_name,param1=0x1,param2=0x4/
Assuming that
/sys/bus/event_source/devices/pmu/events/event_name
Contains something like
param2=?,bar=1,param1=?
--- tools/perf/util/parse-events.h | 1 + tools/perf/util/pmu.c | 74 +++++++++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 11 deletions(-)
tools/perf/util/parse-events.h +1 -0
@@ -71,6 +71,7 @@ struct parse_events_term {int type_val;int type_term;struct list_head list; +bool used; };struct parse_events_evlist {
tools/perf/util/pmu.c +63 -11
114 lines not on this page · raw message
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 9/26 perf tools: Extend format_alias() to include event parameters
In reply to Arnaldo Carvalho de MeloFrom: Cody P Schafer <[email protected]>
This causes perf list pmu to show parameters for parameterized events like:
pmu/event_name,param1=?,param2=?/ [Kernel PMU event]
An example:
hv_24x7/HPM_TLBIE__PHYS_CORE,core=?/ [Kernel PMU event]
--- tools/perf/util/pmu.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-)
tools/perf/util/pmu.c +27 -1
@@ -819,10 +819,36 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)set_bit (b, bits); } +static int sub_non_neg (int a,int b) +{ +if (b > a) +return 0 ; +return a - b; +} +static char *format_alias (char *buf,int len,struct perf_pmu *pmu,struct perf_pmu_alias *alias) { -snprintf (buf, len,"%s/%s/" , pmu->name, alias->name); +struct parse_events_term *term; +int used =snprintf (buf, len,"%s/%s" , pmu->name, alias->name); + +list_for_each_entry (term, &alias->terms, list) { +if (term->type_val ==PARSE_EVENTS__TERM_TYPE_STR ) + used +=snprintf (buf + used,sub_non_neg (len, used), +",%s=%s" , term->config, + term->val.str); + } + +if (sub_non_neg (len, used) >0 ) { + buf[used] ='/' ; + used++; + } +if (sub_non_neg (len, used) >0 ) { + buf[used] ='\0' ; + used++; + }else + buf[len -1 ] ='\0' ; +return buf; }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 10/26 perf Documentation: Add event parameters
In reply to Arnaldo Carvalho de MeloFrom: Cody P Schafer <[email protected]>
Event parameters are a basic way for partial events to be specified in sysfs with per-event names given to the fields that need to be filled in when using a particular event.
It is intended for supporting cases where the single 'cpu' parameter is insufficient. For example, POWER 8 has events for physical sockets/cores/cpus that are accessible from with virtual machines. To keep using the single 'cpu' parameter we'd need to perform a mapping between Linux's cpus and the physical machine's cpus (in this case Linux is running under a hypervisor). This isn't possible because bindings between our cpus and physical cpus may not be fixed, and we probably won't have a "cpu" on each physical cpu.
--- Documentation/ABI/testing/sysfs-bus-event_source-devices-events | 6 ++++++ 1 file changed, 6 insertions(+)
Documentation/ABI/testing/sysfs-bus-event_source-devices-events +6 -0
@@ -52,12 +52,18 @@ Description: Per-pmu performance monitoring events specific to the running syste event=0x2abc event=0x423,inv,cmask=0x3 domain=0x1,offset=0x8,starting_index=0xffff + domain=0x1,offset=0x8,core=? Each of the assignments indicates a value to be assigned to a particular set of bits (as defined by the format file corresponding to the <term>) in the perf_event structure passed to the perf_open syscall. + In the case of the last example, a value replacing "?" would + need to be provided by the user selecting the particular event. + This is referred to as "event parameterization". Event + parameters have the format 'param=?'. + What: /sys/bus/event_source/devices/<pmu>/events/<event>.unit Date: 2014/02/24 Contact: Linux kernel mailing list <[email protected]>
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 11/26 perf tools: Document parameterized and symbolic events
In reply to Arnaldo Carvalho de MeloFrom: Cody P Schafer <[email protected]>
--- tools/perf/Documentation/perf-list.txt | 13 +++++++++++++ tools/perf/Documentation/perf-record.txt | 12 ++++++++++++ tools/perf/Documentation/perf-stat.txt | 20 ++++++++++++++++---- 3 files changed, 41 insertions(+), 4 deletions(-)
tools/perf/Documentation/perf-list.txt +13 -0
@@ -89,6 +89,19 @@ raw encoding of 0x1A8 can be used: You should refer to the processor specific documentation for getting these details. Some of them are referenced in the SEE ALSO section below. +PARAMETERIZED EVENTS +-------------------- + +Some pmu events listed by 'perf-list' will be displayed with '?' in them. For +example: + + hv_gpci/dtbp_ptitc,phys_processor_idx=?/ + +This means that when provided as an event, a value for '?' must +also be supplied. For example: + + perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ... + OPTIONS -------
tools/perf/Documentation/perf-record.txt +12 -0
@@ -33,6 +33,18 @@ OPTIONS - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a hexadecimal event descriptor. + - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where + 'param1', 'param2', etc are defined as formats for the PMU in + /sys/bus/event_sources/devices/<pmu>/format/*. + + - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/' + + where M, N, K are numbers (in decimal, hex, octal format). Acceptable + values for each of 'config', 'config1' and 'config2' are defined by + corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/* + param1 and param2 are defined as formats for the PMU in: + /sys/bus/event_sources/devices/<pmu>/format/* + - a hardware breakpoint event in the form of '\mem:addr[:access]' where addr is the address in memory you want to break in. Access is the memory access type (read, write, execute) it can
tools/perf/Documentation/perf-stat.txt +16 -4
@@ -25,10 +25,22 @@ OPTIONS -e:: --event=:: - Select the PMU event. Selection can be a symbolic event name - (use 'perf list' to list all events) or a raw PMU - event (eventsel+umask) in the form of rNNN where NNN is a - hexadecimal event descriptor. + Select the PMU event. Selection can be: + + - a symbolic event name (use 'perf list' to list all events) + + - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a + hexadecimal event descriptor. + + - a symbolically formed event like 'pmu/param1=0x3,param2/' where + param1 and param2 are defined as formats for the PMU in + /sys/bus/event_sources/devices/<pmu>/format/* + + - a symbolically formed event like 'pmu/config=M,config1=N,config2=K/' + where M, N, K are numbers (in decimal, hex, octal format). + Acceptable values for each of 'config', 'config1' and 'config2' + parameters are defined by corresponding entries in + /sys/bus/event_sources/devices/<pmu>/format/* -i:: --no-inherit::
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 12/26 perf tools: Allow use of an exclusive option more than once
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The exclusive options are to prohibit use of conflicting options at the same time. But it had a side effect that it also limits a such option can be used at most once. Currently the only user of the flag is perf probe and it allows to use such options more than once, but when one tries to use it, perf will fail like below:
$ sudo perf probe -x /lib/libc-2.20.so --add malloc --add free
Error: option `add' cannot be used with add
...--- tools/perf/util/parse-options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/parse-options.c +1 -1
@@ -46,7 +46,7 @@ static int get_value(struct parse_opt_ctx_t *p,return opterror (opt,"is not usable" , flags);if (opt->flags &PARSE_OPT_EXCLUSIVE ) { -if (p->excl_opt) { +if (p->excl_opt && p->excl_opt != opt) {char msg[128 ]; if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 13/26 perf diff: Get rid of hists__compute_resort()
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The hists__compute_resort() is to sort output fields based on the given field/criteria. This was done without the sort list but as we added the field to the sort list, we can do it with normal hists__output_resort() using the ->sort callback.
--- tools/perf/builtin-diff.c | 59 +++-------------------------------------------- 1 file changed, 3 insertions(+), 56 deletions(-)
tools/perf/builtin-diff.c +3 -56
@@ -581,68 +581,15 @@ hist_entry__cmp_wdiff(struct hist_entry *left, struct hist_entry *right)return hist_entry__cmp_compute (right, left,COMPUTE_WEIGHTED_DIFF ); } -static void insert_hist_entry_by_compute (struct rb_root *root, -struct hist_entry *he, -int c) -{ -struct rb_node **p = &root->rb_node; -struct rb_node *parent =NULL ; -struct hist_entry *iter; - -while (*p !=NULL ) { - parent = *p; - iter = rb_entry(parent, struct hist_entry, rb_node); -if (hist_entry__cmp_compute (he, iter, c) <0 ) - p = &(*p)->rb_left; -else - p = &(*p)->rb_right; - } - -rb_link_node (&he->rb_node, parent, p); -rb_insert_color (&he->rb_node, root); -} - -static void hists__compute_resort (struct hists *hists) -{ -struct rb_root *root; -struct rb_node *next; - -if (sort__need_collapse) - root = &hists->entries_collapsed; -else - root = hists->entries_in; - - hists->entries =RB_ROOT ; - next =rb_first (root); - -hists__reset_stats (hists); -hists__reset_col_len (hists); - -while (next !=NULL ) { -struct hist_entry *he; - - he = rb_entry(next, struct hist_entry, rb_node_in); - next =rb_next (&he->rb_node_in); - -insert_hist_entry_by_compute (&hists->entries, he, compute); -hists__inc_stats (hists, he); - -if (!he->filtered) -hists__calc_col_len (hists, he); - } -} -static void hists__process (struct hists *hists) {if (show_baseline_only)hists__baseline_only (hists); -if (sort_compute) { +if (sort_compute)hists__precompute (hists); -hists__compute_resort (hists); - }else { -hists__output_resort (hists,NULL ); - } + +hists__output_resort (hists,NULL );hists__fprintf (hists, true,0 ,0 ,0 , stdout); }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 14/26 perf diff: Print diff result more precisely
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Current perf diff result is somewhat confusing since it sometimes hide small result and sometimes there's no result. So do not hide small result (less than 0.01%) and print "N/A" if baseline is not recorded (for ratio and wdiff only). Blank means the baseline is available but its pairs are not.
Before:
# Baseline Delta Shared Object Symbol # ........ ....... ................. .........................
#
...
0.01% -0.01% [kernel.kallsyms] [k] native_write_msr_safe
0.01% [kernel.kallsyms] [k] scheduler_tick
0.01% [kernel.kallsyms] [k] native_read_msr_safe
0.00% [kernel.kallsyms] [k] __rcu_read_unlock
[kernel.kallsyms] [k] _raw_spin_lock
+0.01% [kernel.kallsyms] [k] apic_timer_interrupt
[kernel.kallsyms] [k] read_tsc
After:
# Baseline Delta Shared Object Symbol
# ........ ....... ................. .........................
#
...
0.01% -0.01% [kernel.kallsyms] [k] native_write_msr_safe
0.01% [kernel.kallsyms] [k] scheduler_tick
0.01% [kernel.kallsyms] [k] native_read_msr_safe
0.00% [kernel.kallsyms] [k] __rcu_read_unlock
+0.01% [kernel.kallsyms] [k] _raw_spin_lock
+0.01% [kernel.kallsyms] [k] apic_timer_interrupt
+0.01% [kernel.kallsyms] [k] read_tsc--- tools/perf/builtin-diff.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
tools/perf/builtin-diff.c +11 -7
@@ -788,7 +788,7 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,char pfmt[20 ] =" " ;if (!pair) - goto dummy_print; + goto no_print;switch (comparison_method) {case COMPUTE_DELTA :
@@ -797,8 +797,6 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt,else diff =compute_delta (he, pair); -if (fabs (diff) <0.01 ) - goto dummy_print;scnprintf (pfmt,20 ,"%%%+d.2f%%%%" , dfmt->header_width -1 );return percent_color_snprintf (hpp->buf, hpp->size, pfmt, diff);
@@ -830,6 +828,9 @@ static int __hpp__color_compare(struct perf_hpp_fmt *fmt, } dummy_print:return scnprintf (hpp->buf, hpp->size,"%*s" , + dfmt->header_width,"N/A" ); +no_print: +return scnprintf (hpp->buf, hpp->size,"%*s" , dfmt->header_width, pfmt); }
@@ -879,14 +880,15 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,else diff =compute_delta (he, pair); -if (fabs (diff) >=0.01 ) -scnprintf (buf, size,"%+4.2F%%" , diff); +scnprintf (buf, size,"%+4.2F%%" , diff);break ;case PERF_HPP_DIFF__RATIO :/* No point for ratio number if we are dummy.. */ -if (he->dummy) +if (he->dummy) { +scnprintf (buf, size,"N/A" );break ; + }if (pair->diff.computed) ratio = pair->diff.period_ratio;
@@ -899,8 +901,10 @@ hpp__entry_pair(struct hist_entry *he, struct hist_entry *pair,case PERF_HPP_DIFF__WEIGHTED_DIFF :/* No point for wdiff number if we are dummy.. */ -if (he->dummy) +if (he->dummy) { +scnprintf (buf, size,"N/A" );break ; + }if (pair->diff.computed) wdiff = pair->diff.wdiff;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 15/26 perf diff: Introduce fmt_to_data_file() helper
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The fmt_to_data_file() is to retrieve struct data__file from perf_hpp_fmt which is embedded in diff_hpp_fmt. It'll be used by sort callback functions later.
--- tools/perf/builtin-diff.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
tools/perf/builtin-diff.c +10 -2
@@ -390,6 +390,15 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist) } } +static struct data__file *fmt_to_data_file (struct perf_hpp_fmt *fmt) +{ + struct diff_hpp_fmt *dfmt = container_of(fmt, struct diff_hpp_fmt, fmt); +void *ptr = dfmt - dfmt->idx; + struct data__file *d = container_of(ptr, struct data__file, fmt); + +return d; +} +static struct hist_entry *get_pair_data (struct hist_entry *he,struct data__file *d) {
@@ -407,8 +416,7 @@ get_pair_data(struct hist_entry *he, struct data__file *d)static struct hist_entry *get_pair_fmt (struct hist_entry *he,struct diff_hpp_fmt *dfmt) { -void *ptr = dfmt - dfmt->idx; - struct data__file *d = container_of(ptr, struct data__file, fmt); +struct data__file *d =fmt_to_data_file (&dfmt->fmt);return get_pair_data (he, d); }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 16/26 perf tools: Pass struct perf_hpp_fmt to its callbacks
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Currently ->cmp, ->collapse and ->sort callbacks doesn't pass corresponding fmt. But it'll be needed by upcoming changes in perf diff command.
--- tools/perf/builtin-diff.c | 15 ++++++++++----- tools/perf/ui/hist.c | 12 ++++++++---- tools/perf/util/hist.c | 6 +++--- tools/perf/util/hist.h | 9 ++++++--- tools/perf/util/sort.c | 37 ++++++++++++++++++++++++++++++++++--- 5 files changed, 61 insertions(+), 18 deletions(-)
tools/perf/builtin-diff.c +10 -5
@@ -554,14 +554,16 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, }static int64_t -hist_entry__cmp_nop (struct hist_entry *left__maybe_unused , +hist_entry__cmp_nop (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *left__maybe_unused ,struct hist_entry *right__maybe_unused ) {return 0 ; }static int64_t -hist_entry__cmp_baseline (struct hist_entry *left,struct hist_entry *right) +hist_entry__cmp_baseline (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *left,struct hist_entry *right) {if (sort_compute)return 0 ;
@@ -572,19 +574,22 @@ hist_entry__cmp_baseline(struct hist_entry *left, struct hist_entry *right) }static int64_t -hist_entry__cmp_delta (struct hist_entry *left,struct hist_entry *right) +hist_entry__cmp_delta (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *left,struct hist_entry *right) {return hist_entry__cmp_compute (right, left,COMPUTE_DELTA ); }static int64_t -hist_entry__cmp_ratio (struct hist_entry *left,struct hist_entry *right) +hist_entry__cmp_ratio (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *left,struct hist_entry *right) {return hist_entry__cmp_compute (right, left,COMPUTE_RATIO ); }static int64_t -hist_entry__cmp_wdiff (struct hist_entry *left,struct hist_entry *right) +hist_entry__cmp_wdiff (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *left,struct hist_entry *right) {return hist_entry__cmp_compute (right, left,COMPUTE_WEIGHTED_DIFF ); }
tools/perf/ui/hist.c +8 -4
@@ -285,7 +285,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \ }#define __HPP_SORT_FN (_type, _field) \ -static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ +static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ + struct hist_entry *a, struct hist_entry *b) \ { \ return __hpp__sort(a, b, he_get_##_field); \ }
@@ -312,7 +313,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \ }#define __HPP_SORT_ACC_FN (_type, _field) \ -static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ +static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ + struct hist_entry *a, struct hist_entry *b) \ { \ return __hpp__sort_acc(a, b, he_get_acc_##_field); \ }
@@ -331,7 +333,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \ }#define __HPP_SORT_RAW_FN (_type, _field) \ -static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \ +static int64_t hpp__sort_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ + struct hist_entry *a, struct hist_entry *b) \ { \ return __hpp__sort(a, b, he_get_raw_##_field); \ }
@@ -361,7 +364,8 @@ HPP_PERCENT_ACC_FNS(overhead_acc, period) HPP_RAW_FNS(samples, nr_events) HPP_RAW_FNS(period, period) -static int64_t hpp__nop_cmp (struct hist_entry *a__maybe_unused , +static int64_t hpp__nop_cmp (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *a__maybe_unused ,struct hist_entry *b__maybe_unused ) {return 0 ;
tools/perf/util/hist.c +3 -3
@@ -913,7 +913,7 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)if (perf_hpp__should_skip (fmt))continue ; - cmp = fmt->cmp (left, right); + cmp = fmt->cmp (fmt, left, right);if (cmp)break ; }
@@ -931,7 +931,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)if (perf_hpp__should_skip (fmt))continue ; - cmp = fmt->collapse (left, right); + cmp = fmt->collapse (fmt, left, right);if (cmp)break ; }
@@ -1061,7 +1061,7 @@ static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)if (perf_hpp__should_skip (fmt))continue ; - cmp = fmt->sort (a, b); + cmp = fmt->sort (fmt, a, b);if (cmp)break ; }
tools/perf/util/hist.h +6 -3
@@ -195,9 +195,12 @@ struct perf_hpp_fmt { struct hist_entry *he);int (*entry)(struct perf_hpp_fmt *fmt,struct perf_hpp *hpp,struct hist_entry *he); -int64_t (*cmp)(struct hist_entry *a,struct hist_entry *b); -int64_t (*collapse)(struct hist_entry *a,struct hist_entry *b); -int64_t (*sort)(struct hist_entry *a,struct hist_entry *b); +int64_t (*cmp)(struct perf_hpp_fmt *fmt, +struct hist_entry *a,struct hist_entry *b); +int64_t (*collapse)(struct perf_hpp_fmt *fmt, +struct hist_entry *a,struct hist_entry *b); +int64_t (*sort)(struct perf_hpp_fmt *fmt, +struct hist_entry *a,struct hist_entry *b);struct list_head list;struct list_head sort_list;
tools/perf/util/sort.c +34 -3
@@ -1304,6 +1304,37 @@ static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,return hse->se->se_snprintf (he, hpp->buf, hpp->size, len); } +static int64_t __sort__hpp_cmp (struct perf_hpp_fmt *fmt, +struct hist_entry *a,struct hist_entry *b) +{ +struct hpp_sort_entry *hse; + + hse = container_of(fmt, struct hpp_sort_entry, hpp); +return hse->se->se_cmp (a, b); +} + +static int64_t __sort__hpp_collapse (struct perf_hpp_fmt *fmt, +struct hist_entry *a,struct hist_entry *b) +{ +struct hpp_sort_entry *hse; +int64_t (*collapse_fn)(struct hist_entry *,struct hist_entry *); + + hse = container_of(fmt, struct hpp_sort_entry, hpp); + collapse_fn = hse->se->se_collapse ?: hse->se->se_cmp; +return collapse_fn (a, b); +} + +static int64_t __sort__hpp_sort (struct perf_hpp_fmt *fmt, +struct hist_entry *a,struct hist_entry *b) +{ +struct hpp_sort_entry *hse; +int64_t (*sort_fn)(struct hist_entry *,struct hist_entry *); + + hse = container_of(fmt, struct hpp_sort_entry, hpp); + sort_fn = hse->se->se_sort ?: hse->se->se_cmp; +return sort_fn (a, b); +} +static struct hpp_sort_entry *__sort_dimension__alloc_hpp (struct sort_dimension *sd) {
@@ -1322,9 +1353,9 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) hse->hpp.entry = __sort__hpp_entry; hse->hpp.color =NULL ; - hse->hpp.cmp = sd->entry->se_cmp; - hse->hpp.collapse = sd->entry->se_collapse ? : sd->entry->se_cmp; - hse->hpp.sort = sd->entry->se_sort ? : hse->hpp.collapse; + hse->hpp.cmp = __sort__hpp_cmp; + hse->hpp.collapse = __sort__hpp_collapse; + hse->hpp.sort = __sort__hpp_sort;INIT_LIST_HEAD (&hse->hpp.list);INIT_LIST_HEAD (&hse->hpp.sort_list);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 17/26 perf diff: Fix output ordering to honor next column
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When perf diff prints output, it sorts the entries using baseline field by default, but entries which don't have baseline are not sorted properly. This patch makes it sorted by values of next column.
Before:
# Baseline/0 Delta/1 Delta/2 Shared Object Symbol
# .......... ....... ....... ................. ..........................................
#
32.75% +0.28% -0.83% libc-2.20.so [.] malloc
31.50% -0.74% -0.23% libc-2.20.so [.] _int_free
22.98% +0.51% +0.52% libc-2.20.so [.] _int_malloc
5.70% +0.28% +0.30% libc-2.20.so [.] free
4.38% -0.21% +0.25% a.out [.] main
1.32% -0.15% +0.05% a.out [.] free@plt
1.31% +0.03% -0.06% a.out [.] malloc@plt
0.01% -0.01% -0.01% [kernel.kallsyms] [k] native_write_msr_safe
0.01% [kernel.kallsyms] [k] scheduler_tick
0.01% -0.00% [kernel.kallsyms] [k] native_read_msr_safe
+0.01% [kernel.kallsyms] [k] _raw_spin_lock_irqsave
+0.01% +0.01% [kernel.kallsyms] [k] apic_timer_interrupt
+0.01% [kernel.kallsyms] [k] intel_pstate_timer_func
+0.01% [kernel.kallsyms] [k] perf_adjust_freq_unthr_context.part.82
+0.01% [kernel.kallsyms] [k] read_tsc
+0.01% [kernel.kallsyms] [k] timekeeping_update.constprop.8After:
# Baseline/0 Delta/1 Delta/2 Shared Object Symbol
# .......... ....... ....... ................. ..........................................
#
32.75% +0.28% -0.83% libc-2.20.so [.] malloc
31.50% -0.74% -0.23% libc-2.20.so [.] _int_free
22.98% +0.51% +0.52% libc-2.20.so [.] _int_malloc
5.70% +0.28% +0.30% libc-2.20.so [.] free
4.38% -0.21% +0.25% a.out [.] main
1.32% -0.15% +0.05% a.out [.] free@plt
1.31% +0.03% -0.06% a.out [.] malloc@plt
0.01% -0.01% -0.01% [kernel.kallsyms] [k] native_write_msr_safe
0.01% [kernel.kallsyms] [k] scheduler_tick
0.01% -0.00% [kernel.kallsyms] [k] native_read_msr_safe
+0.01% +0.01% [kernel.kallsyms] [k] apic_timer_interrupt
+0.01% [kernel.kallsyms] [k] read_tsc
+0.01% [kernel.kallsyms] [k] perf_adjust_freq_unthr_context.part.82
+0.01% [kernel.kallsyms] [k] intel_pstate_timer_func
+0.01% [kernel.kallsyms] [k] _raw_spin_lock_irqsave
+0.01% [kernel.kallsyms] [k] timekeeping_update.constprop.8--- tools/perf/builtin-diff.c | 65 +++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 30 deletions(-)
tools/perf/builtin-diff.c +35 -30
@@ -456,26 +456,30 @@ static void hists__precompute(struct hists *hists) next =rb_first (root);while (next !=NULL ) {struct hist_entry *he, *pair; +struct data__file *d; +int i; he = rb_entry(next, struct hist_entry, rb_node_in); next =rb_next (&he->rb_node_in); - pair =get_pair_data (he, &data__files[sort_compute]); -if (!pair) -continue ; +data__for_each_file_new (i, d) { + pair =get_pair_data (he, d); +if (!pair) +continue ; -switch (compute) { -case COMPUTE_DELTA : -compute_delta (he, pair); -break ; -case COMPUTE_RATIO : -compute_ratio (he, pair); -break ; -case COMPUTE_WEIGHTED_DIFF : -compute_wdiff (he, pair); -break ; -default : -BUG_ON (1 ); +switch (compute) { +case COMPUTE_DELTA : +compute_delta (he, pair); +break ; +case COMPUTE_RATIO : +compute_ratio (he, pair); +break ; +case COMPUTE_WEIGHTED_DIFF : +compute_wdiff (he, pair); +break ; +default : +BUG_ON (1 ); + } } } }
@@ -525,7 +529,7 @@ __hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,static int64_t hist_entry__cmp_compute (struct hist_entry *left,struct hist_entry *right, -int c) +int c,int sort_idx) {bool pairs_left =hist_entry__has_pairs (left);bool pairs_right =hist_entry__has_pairs (right);
@@ -537,8 +541,8 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,if (!pairs_left || !pairs_right)return pairs_left ?-1 :1 ; - p_left =get_pair_data (left, &data__files[sort_compute]); - p_right =get_pair_data (right, &data__files[sort_compute]); + p_left =get_pair_data (left, &data__files[sort_idx]); + p_right =get_pair_data (right, &data__files[sort_idx]);if (!p_left && !p_right)return 0 ;
@@ -565,33 +569,36 @@ static int64_t hist_entry__cmp_baseline(struct perf_hpp_fmt *fmt __maybe_unused, struct hist_entry *left, struct hist_entry *right) { - if (sort_compute) - return 0; - if (left->stat.period == right->stat.period) return 0; return left->stat.period > right->stat.period ? 1 : -1; } static int64_t -hist_entry__cmp_delta(struct perf_hpp_fmt *fmt __maybe_unused, +hist_entry__cmp_delta(struct perf_hpp_fmt *fmt, struct hist_entry *left, struct hist_entry *right) { - return hist_entry__cmp_compute(right, left, COMPUTE_DELTA); + struct data__file *d = fmt_to_data_file(fmt); + +return hist_entry__cmp_compute (right, left,COMPUTE_DELTA , d->idx); }static int64_t -hist_entry__cmp_ratio (struct perf_hpp_fmt *fmt__maybe_unused , +hist_entry__cmp_ratio (struct perf_hpp_fmt *fmt,struct hist_entry *left,struct hist_entry *right) { -return hist_entry__cmp_compute (right, left,COMPUTE_RATIO ); +struct data__file *d =fmt_to_data_file (fmt); + +return hist_entry__cmp_compute (right, left,COMPUTE_RATIO , d->idx); }static int64_t -hist_entry__cmp_wdiff (struct perf_hpp_fmt *fmt__maybe_unused , +hist_entry__cmp_wdiff (struct perf_hpp_fmt *fmt,struct hist_entry *left,struct hist_entry *right) { -return hist_entry__cmp_compute (right, left,COMPUTE_WEIGHTED_DIFF ); +struct data__file *d =fmt_to_data_file (fmt); + +return hist_entry__cmp_compute (right, left,COMPUTE_WEIGHTED_DIFF , d->idx); }static void hists__process (struct hists *hists)
@@ -599,9 +606,7 @@ static void hists__process(struct hists *hists)if (show_baseline_only)hists__baseline_only (hists); -if (sort_compute) -hists__precompute (hists); - +hists__precompute (hists);hists__output_resort (hists,NULL );hists__fprintf (hists, true,0 ,0 ,0 , stdout);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 18/26 perf diff: Fix -o/--order option behavior
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The prior change fixes default output ordering with each column but it breaks -o/--order option. This patch prepends a new hpp fmt struct to sort list but not to output field list so that it can affect ordering without adding a new output column.
The new hpp fmt uses its own compare functions which treats dummy entries (which have no baseline) little differently - the delta field can be computed without baseline but others (ratio and wdiff) are not.
The new output will look like below:
$ perf diff -o 2 perf.data.{old,cur,new}
...
# Baseline/0 Delta/1 Delta/2 Shared Object Symbol
# .......... ....... ....... ................. ..........................................
22.98% +0.51% +0.52% libc-2.20.so [.] _int_malloc
5.70% +0.28% +0.30% libc-2.20.so [.] free
4.38% -0.21% +0.25% a.out [.] main
1.32% -0.15% +0.05% a.out [.] free@plt
+0.01% [kernel.kallsyms] [k] intel_pstate_timer_func
+0.01% [kernel.kallsyms] [k] _raw_spin_lock_irqsave
+0.01% [kernel.kallsyms] [k] timekeeping_update.constprop.8
+0.01% +0.01% [kernel.kallsyms] [k] apic_timer_interrupt
0.01% -0.00% [kernel.kallsyms] [k] native_read_msr_safe
0.01% -0.01% -0.01% [kernel.kallsyms] [k] native_write_msr_safe
1.31% +0.03% -0.06% a.out [.] malloc@plt
31.50% -0.74% -0.23% libc-2.20.so [.] _int_free
32.75% +0.28% -0.83% libc-2.20.so [.] malloc
0.01% [kernel.kallsyms] [k] scheduler_tick
+0.01% [kernel.kallsyms] [k] read_tsc
+0.01% [kernel.kallsyms] [k] perf_adjust_freq_unthr_context.part.82In above example, the output was sorted by 'Delta/2' column first, and then 'Baseline/0' and finally 'Delta/1'.
--- tools/perf/builtin-diff.c | 101 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-)
tools/perf/builtin-diff.c +99 -2
@@ -558,6 +558,37 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right, }static int64_t +hist_entry__cmp_compute_idx (struct hist_entry *left,struct hist_entry *right, +int c,int sort_idx) +{ +struct hist_entry *p_right, *p_left; + + p_left =get_pair_data (left, &data__files[sort_idx]); + p_right =get_pair_data (right, &data__files[sort_idx]); + +if (!p_left && !p_right) +return 0 ; + +if (!p_left || !p_right) +return p_left ?-1 :1 ; + +if (c !=COMPUTE_DELTA ) { +/* +* The delta can be computed without the baseline, but +* others are not. Put those entries which have no +* values below. +*/ +if (left->dummy && right->dummy) +return 0 ; + +if (left->dummy || right->dummy) +return left->dummy ?1 :-1 ; + } + +return __hist_entry__cmp_compute (p_left, p_right, c); +} + +static int64_t hist_entry__cmp_nop (struct perf_hpp_fmt *fmt__maybe_unused ,struct hist_entry *left__maybe_unused ,struct hist_entry *right__maybe_unused )
@@ -601,6 +632,30 @@ hist_entry__cmp_wdiff(struct perf_hpp_fmt *fmt,return hist_entry__cmp_compute (right, left,COMPUTE_WEIGHTED_DIFF , d->idx); } +static int64_t +hist_entry__cmp_delta_idx (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *left,struct hist_entry *right) +{ +return hist_entry__cmp_compute_idx (right, left,COMPUTE_DELTA , + sort_compute); +} + +static int64_t +hist_entry__cmp_ratio_idx (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *left,struct hist_entry *right) +{ +return hist_entry__cmp_compute_idx (right, left,COMPUTE_RATIO , + sort_compute); +} + +static int64_t +hist_entry__cmp_wdiff_idx (struct perf_hpp_fmt *fmt__maybe_unused , +struct hist_entry *left,struct hist_entry *right) +{ +return hist_entry__cmp_compute_idx (right, left,COMPUTE_WEIGHTED_DIFF , + sort_compute); +} +static void hists__process (struct hists *hists) {if (show_baseline_only)
@@ -1074,9 +1129,10 @@ static void data__hpp_register(struct data__file *d, int idx)perf_hpp__register_sort_field (fmt); } -static void ui_init (void ) +static int ui_init (void ) {struct data__file *d; +struct perf_hpp_fmt *fmt;int i;data__for_each_file (i, d) {
@@ -1106,6 +1162,46 @@ static void ui_init(void)data__hpp_register (d, i ?PERF_HPP_DIFF__PERIOD :PERF_HPP_DIFF__PERIOD_BASELINE ); } + +if (!sort_compute) +return 0 ; + +/* +* Prepend an fmt to sort on columns at 'sort_compute' first. +* This fmt is added only to the sort list but not to the +* output fields list. +* +* Note that this column (data) can be compared twice - one +* for this 'sort_compute' fmt and another for the normal +* diff_hpp_fmt. But it shouldn't a problem as most entries +* will be sorted out by first try or baseline and comparing +* is not a costly operation. +*/ + fmt =zalloc (sizeof (*fmt)); +if (fmt ==NULL ) { +pr_err ("Memory allocation failed\n" ); +return -1 ; + } + + fmt->cmp = hist_entry__cmp_nop; + fmt->collapse = hist_entry__cmp_nop; + +switch (compute) { +case COMPUTE_DELTA : + fmt->sort = hist_entry__cmp_delta_idx; +break ; +case COMPUTE_RATIO : + fmt->sort = hist_entry__cmp_ratio_idx; +break ; +case COMPUTE_WEIGHTED_DIFF : + fmt->sort = hist_entry__cmp_wdiff_idx; +break ; +default : +BUG_ON (1 ); + } + +list_add (&fmt->sort_list, &perf_hpp__sort_list); +return 0 ; }static int data_init (int argc,const char **argv)
@@ -1171,7 +1267,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)if (data_init (argc, argv) <0 )return -1 ; -ui_init (); +if (ui_init () <0 ) +return -1 ; sort__mode =SORT_MODE__DIFF ;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 19/26 tools lib fs: Adopt debugfs open strerrno method
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
As this is not specific to an evlist and may be used with other tools.
tools/perf/util/include/asm/hash.h
--- tools/lib/api/fs/debugfs.c | 27 +++++++++++++++++++++++++++ tools/lib/api/fs/debugfs.h | 2 ++ tools/perf/builtin-trace.c | 11 +++++++++-- tools/perf/util/evlist.c | 27 --------------------------- tools/perf/util/evlist.h | 1 - 5 files changed, 38 insertions(+), 30 deletions(-)
tools/lib/api/fs/debugfs.c +27 -0
@@ -1,3 +1,4 @@ +#define _GNU_SOURCE#include <errno.h> #include <stdio.h> #include <stdlib.h>
@@ -98,3 +99,29 @@ char *debugfs_mount(const char *mountpoint) out:return debugfs_mountpoint; } + +int debugfs__strerror_open (int err,char *buf,size_t size) +{ +char sbuf[128 ]; + +switch (err) { +case ENOENT : +snprintf (buf, size,"%s" , +"Error:\tUnable to find debugfs\n" +"Hint:\tWas your kernel compiled with debugfs support?\n" +"Hint:\tIs the debugfs filesystem mounted?\n" +"Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'" ); +break ; +case EACCES : +snprintf (buf, size, +"Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n" +"Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n" , + debugfs_mountpoint, debugfs_mountpoint); +break ; +default : +snprintf (buf, size,"%s" ,strerror_r (err, sbuf,sizeof (sbuf))); +break ; + } + +return 0 ; +}
tools/lib/api/fs/debugfs.h +2 -0
@@ -26,4 +26,6 @@ char *debugfs_mount(const char *mountpoint);extern char debugfs_mountpoint[]; +int debugfs__strerror_open (int err,char *buf,size_t size); +#endif /* __API_DEBUGFS_H__ */
tools/perf/builtin-trace.c +9 -2
@@ -2062,8 +2062,15 @@ static int trace__run(struct trace *trace, int argc, const char **argv)perf_evlist__add_vfs_getname (evlist);if ((trace->trace_pgfaults &TRACE_PFMAJ ) && -perf_evlist__add_pgfault (evlist,PERF_COUNT_SW_PAGE_FAULTS_MAJ )) +perf_evlist__add_pgfault (evlist,PERF_COUNT_SW_PAGE_FAULTS_MAJ )) { +/* +* FIXME: This one needs better error handling, as by now we +* already checked that debugfs is mounted and that we have access to it, +* so probably the case is that something is busted wrt this specific +* software event, ditto for the next gotos to out_error_tp... +*/ goto out_error_tp; + }if ((trace->trace_pgfaults &TRACE_PFMIN ) &&perf_evlist__add_pgfault (evlist,PERF_COUNT_SW_PAGE_FAULTS_MIN ))
@@ -2203,7 +2210,7 @@ out:char errbuf[BUFSIZ ]; out_error_tp: -perf_evlist__strerror_tp (evlist, errno, errbuf,sizeof (errbuf)); +debugfs__strerror_open (errno, errbuf,sizeof (errbuf)); goto out_error; out_error_mmap:
tools/perf/util/evlist.c +0 -27
@@ -1436,33 +1436,6 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)return printed +fprintf (fp,"\n" ); } -int perf_evlist__strerror_tp (struct perf_evlist *evlist__maybe_unused , -int err,char *buf,size_t size) -{ -char sbuf[128 ]; - -switch (err) { -case ENOENT : -scnprintf (buf, size,"%s" , -"Error:\tUnable to find debugfs\n" -"Hint:\tWas your kernel compiled with debugfs support?\n" -"Hint:\tIs the debugfs filesystem mounted?\n" -"Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'" ); -break ; -case EACCES : -scnprintf (buf, size, -"Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n" -"Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n" , - debugfs_mountpoint, debugfs_mountpoint); -break ; -default : -scnprintf (buf, size,"%s" ,strerror_r (err, sbuf,sizeof (sbuf))); -break ; - } - -return 0 ; -} -int perf_evlist__strerror_open (struct perf_evlist *evlist__maybe_unused ,int err,char *buf,size_t size) {
tools/perf/util/evlist.h +0 -1
@@ -183,7 +183,6 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)size_t perf_evlist__fprintf (struct perf_evlist *evlist,FILE *fp); -int perf_evlist__strerror_tp (struct perf_evlist *evlist,int err,char *buf,size_t size);int perf_evlist__strerror_open (struct perf_evlist *evlist,int err,char *buf,size_t size);int perf_evlist__strerror_mmap (struct perf_evlist *evlist,int err,char *buf,size_t size);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 20/26 tools lib fs: Pass filename to debugfs__strerror_open
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
It was hardcoded for one specific tracepoint, leftover from its initial
user: 'perf trace'.
--- tools/lib/api/fs/debugfs.c | 6 +++--- tools/lib/api/fs/debugfs.h | 2 +- tools/perf/builtin-trace.c | 5 +++-- 3 files changed, 7 insertions(+), 6 deletions(-)
tools/lib/api/fs/debugfs.c +3 -3
@@ -100,7 +100,7 @@ out:return debugfs_mountpoint; } -int debugfs__strerror_open (int err,char *buf,size_t size) +int debugfs__strerror_open (int err,char *buf,size_t size,const char *filename) {char sbuf[128 ];
@@ -114,9 +114,9 @@ int debugfs__strerror_open(int err, char *buf, size_t size)break ;case EACCES :snprintf (buf, size, -"Error:\tNo permissions to read %s/tracing/events/raw_syscalls\n" +"Error:\tNo permissions to read %s/%s\n" "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n" , - debugfs_mountpoint, debugfs_mountpoint); + debugfs_mountpoint, filename, debugfs_mountpoint);break ;default :snprintf (buf, size,"%s" ,strerror_r (err, sbuf,sizeof (sbuf)));
tools/lib/api/fs/debugfs.h +1 -1
@@ -26,6 +26,6 @@ char *debugfs_mount(const char *mountpoint);extern char debugfs_mountpoint[]; -int debugfs__strerror_open (int err,char *buf,size_t size); +int debugfs__strerror_open (int err,char *buf,size_t size,const char *filename);#endif /* __API_DEBUGFS_H__ */
tools/perf/builtin-trace.c +3 -2
@@ -2056,7 +2056,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)if (trace->trace_syscalls &&perf_evlist__add_syscall_newtp (evlist, trace__sys_enter, trace__sys_exit)) - goto out_error_tp; + goto out_error_raw_syscalls;if (trace->trace_syscalls)perf_evlist__add_vfs_getname (evlist);
@@ -2210,7 +2210,8 @@ out:char errbuf[BUFSIZ ]; out_error_tp: -debugfs__strerror_open (errno, errbuf,sizeof (errbuf)); +out_error_raw_syscalls: +debugfs__strerror_open (errno, errbuf,sizeof (errbuf),"tracing/events/raw_syscalls" ); goto out_error; out_error_mmap:
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 21/26 perf trace: Fix error reporting for evsel pgfault constructor
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
In that case the only failure possible is not to have enough memory, as we are just creating the evsels, not trying to access any system facility such as debugfs files or syscalls.
--- tools/perf/builtin-trace.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
tools/perf/builtin-trace.c +5 -8
@@ -2063,18 +2063,12 @@ static int trace__run(struct trace *trace, int argc, const char **argv)if ((trace->trace_pgfaults &TRACE_PFMAJ ) &&perf_evlist__add_pgfault (evlist,PERF_COUNT_SW_PAGE_FAULTS_MAJ )) { -/* -* FIXME: This one needs better error handling, as by now we -* already checked that debugfs is mounted and that we have access to it, -* so probably the case is that something is busted wrt this specific -* software event, ditto for the next gotos to out_error_tp... -*/ - goto out_error_tp; + goto out_error_mem; }if ((trace->trace_pgfaults &TRACE_PFMIN ) &&perf_evlist__add_pgfault (evlist,PERF_COUNT_SW_PAGE_FAULTS_MIN )) - goto out_error_tp; + goto out_error_mem;if (trace->sched && perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
@@ -2225,6 +2219,9 @@ out_error:fprintf (trace->output,"%s\n" , errbuf); goto out_delete_evlist; } +out_error_mem: +fprintf (trace->output,"Not enough memory to run!\n" ); + goto out_delete_evlist; }static int trace__replay (struct trace *trace)
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 22/26 tools lib fs debugfs: Introduce debugfs__strerror_open_tp
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
There will be other cases where not just a tracepoint event is being opened below the debugfs mountpoint, but it is rather common, so provide one helper for that.
--- tools/lib/api/fs/debugfs.c | 9 +++++++++ tools/lib/api/fs/debugfs.h | 1 + tools/perf/builtin-trace.c | 13 ++++++++----- 3 files changed, 18 insertions(+), 5 deletions(-)
tools/lib/api/fs/debugfs.c +9 -0
@@ -125,3 +125,12 @@ int debugfs__strerror_open(int err, char *buf, size_t size, const char *filenamereturn 0 ; } + +int debugfs__strerror_open_tp (int err,char *buf,size_t size,const char *sys,const char *name) +{ +char path[PATH_MAX ]; + +snprintf (path,PATH_MAX ,"tracing/events/%s/%s" , sys, name ?:"*" ); + +return debugfs__strerror_open (err, buf, size, path); +}
tools/lib/api/fs/debugfs.h +1 -0
@@ -27,5 +27,6 @@ char *debugfs_mount(const char *mountpoint);extern char debugfs_mountpoint[];int debugfs__strerror_open (int err,char *buf,size_t size,const char *filename); +int debugfs__strerror_open_tp (int err,char *buf,size_t size,const char *sys,const char *name);#endif /* __API_DEBUGFS_H__ */
tools/perf/builtin-trace.c +8 -5
@@ -2071,9 +2071,9 @@ static int trace__run(struct trace *trace, int argc, const char **argv) goto out_error_mem;if (trace->sched && -perf_evlist__add_newtp (evlist,"sched" ,"sched_stat_runtime" , - trace__sched_stat_runtime)) - goto out_error_tp; +perf_evlist__add_newtp (evlist,"sched" ,"sched_stat_runtime" , + trace__sched_stat_runtime)) + goto out_error_sched_stat_runtime; err =perf_evlist__create_maps (evlist, &trace->opts.target);if (err <0 ) {
@@ -2203,9 +2203,12 @@ out: {char errbuf[BUFSIZ ]; -out_error_tp: +out_error_sched_stat_runtime: +debugfs__strerror_open_tp (errno, errbuf,sizeof (errbuf),"sched" ,"sched_stat_runtime" ); + goto out_error; + out_error_raw_syscalls: -debugfs__strerror_open (errno, errbuf,sizeof (errbuf),"tracing/events/raw_syscalls" ); +debugfs__strerror_open_tp (errno, errbuf,sizeof (errbuf),"raw_syscalls" ,"sys_(enter|exit)" ); goto out_error; out_error_mmap:
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 23/26 tools lib fs debugfs: Check if debugfs is mounted when handling ENOENT
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
If debugfs was already mounted, then its a matter of not finding the tracepoint, tell the user that perhaps a CONFIG_ setting is not enabled.
--- tools/lib/api/fs/debugfs.c | 7 +++++++ 1 file changed, 7 insertions(+)
tools/lib/api/fs/debugfs.c +7 -0
@@ -106,6 +106,13 @@ int debugfs__strerror_open(int err, char *buf, size_t size, const char *filenameswitch (err) {case ENOENT : +if (debugfs_found) { +snprintf (buf, size, +"Error:\tFile %s/%s not found.\n" +"Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n" , + debugfs_mountpoint, filename); +break ; + }snprintf (buf, size,"%s" ,"Error:\tUnable to find debugfs\n" "Hint:\tWas your kernel compiled with debugfs support?\n"
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 24/26 perf tests: Fix typo in sample-parsing.c
In reply to Arnaldo Carvalho de MeloFrom: Rasmus Villemoes <[email protected]>
It was testing the same buffer for differences:
memcmp(s1->user_stack.data, s1->user_stack.data, s1->user_stack.size)
I'm pretty sure this wasn't supposed to be dead code.
--- tools/perf/tests/sample-parsing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/sample-parsing.c +1 -1
@@ -110,7 +110,7 @@ static bool samples_same(const struct perf_sample *s1,if (type &PERF_SAMPLE_STACK_USER ) {COMP (user_stack.size); -if (memcmp (s1->user_stack.data, s1->user_stack.data, +if (memcmp (s1->user_stack.data, s2->user_stack.data, s1->user_stack.size)) {pr_debug ("Samples differ at 'user_stack'\n" );return false;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 25/26 perf ui/tui: Show fatal error message only if exists
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When perf exits with some error it shows the error message with ui__error() or ui__warning() and then calls ui__exit() during exit_browser().
On TUI, it then shows a window titled "Fatal Error" to inform user a last message which might be related with this condition. However it sometimes contains no message and just annoyes users.
The usual case for this is running perf top as normal user. (And /proc/sys/kernel/perf_event_paranoid being 1).
--- tools/perf/ui/tui/helpline.c | 3 +++ tools/perf/ui/tui/setup.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-)
tools/perf/ui/tui/helpline.c +3 -0
@@ -9,6 +9,7 @@#include "../libslang.h" char ui_helpline__last_msg[1024 ]; +bool tui_helpline__set;static void tui_helpline__pop (void ) {
@@ -35,6 +36,8 @@ static int tui_helpline__show(const char *format, va_list ap) sizeof(ui_helpline__last_msg) - backlog, format, ap); backlog += ret; + tui_helpline__set = true; +if (ui_helpline__last_msg[backlog -1 ] =='\n' ) {ui_helpline__puts (ui_helpline__last_msg);SLsmg_refresh ();
tools/perf/ui/tui/setup.c +2 -1
@@ -17,6 +17,7 @@static volatile int ui__need_resize;extern struct perf_error_ops perf_tui_eops; +extern bool tui_helpline__set;extern void hist_browser__init_hpp (void );
@@ -159,7 +160,7 @@ out:void ui__exit (bool wait_for_ok) { -if (wait_for_ok) +if (wait_for_ok && tui_helpline__set)ui__question_window ("Fatal Error" , ui_helpline__last_msg,"Press any key..." ,0 );
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 26/26 tools lib traceevent: Add support for IP address formats
In reply to Arnaldo Carvalho de MeloFrom: David Ahern <[email protected]>
Add helpers for the following kernel formats:
%pi4 print an IPv4 address with leading zeros %pI4 print an IPv4 address without leading zeros %pi6 print an IPv6 address without colons
%pI6 print an IPv6 address with colons
%pI6c print an IPv6 address in compressed form with colons %pISpc print an IP address from a sockaddr
Allows these formats to be used in tracepoints.
Quite a bit of this is adapted from code in lib/vsprintf.c.
v4:
- fixed pI6c description in git commit message per Valdis' comment
v3:
- use of 'c' and 'p' requires 'I'
v2:
- pass ptr+1 to print_ip_arg per Namhyung's comments
- added field length checks to sockaddr function
--- tools/lib/traceevent/event-parse.c | 328 +++++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+)
tools/lib/traceevent/event-parse.c +328 -0
@@ -32,6 +32,7 @@#include <stdint.h> #include <limits.h> +#include <netinet/ip6.h> #include "event-parse.h" #include "event-utils.h"
@@ -4149,6 +4150,324 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,trace_seq_printf (s, fmt, buf[0 ], buf[1 ], buf[2 ], buf[3 ], buf[4 ], buf[5 ]); } +static void print_ip4_addr (struct trace_seq *s,char i,unsigned char *buf) +{ +const char *fmt; + +if (i =='i' ) + fmt ="%03d.%03d.%03d.%03d" ; +else + fmt ="%d.%d.%d.%d" ; + +trace_seq_printf (s, fmt, buf[0 ], buf[1 ], buf[2 ], buf[3 ]); +} + +static inline bool ipv6_addr_v4mapped (const struct in6_addr *a) +{ +return ((unsigned long )(a->s6_addr32[0 ] | a->s6_addr32[1 ]) | + (unsigned long )(a->s6_addr32[2 ] ^htonl (0x0000ffff ))) ==0UL ; +} + +static inline bool ipv6_addr_is_isatap (const struct in6_addr *addr) +{ +return (addr->s6_addr32[2 ] |htonl (0x02000000 )) ==htonl (0x02005EFE ); +} + +static void print_ip6c_addr (struct trace_seq *s,unsigned char *addr) +{ +int i, j, range; +unsigned char zerolength[8 ]; +int longest =1 ; +int colonpos =-1 ; +uint16_t word; +uint8_t hi, lo; +bool needcolon = false; +bool useIPv4; +struct in6_addr in6; + +memcpy (&in6, addr,sizeof (struct in6_addr )); + + useIPv4 =ipv6_addr_v4mapped (&in6) ||ipv6_addr_is_isatap (&in6); + +memset (zerolength,0 ,sizeof (zerolength)); + +if (useIPv4) + range =6 ; +else + range =8 ; + +/* find position of longest 0 run */ +for (i =0 ; i < range; i++) { +for (j = i; j < range; j++) { +if (in6.s6_addr16[j] !=0 ) +break ; + zerolength[i]++; + } + } +for (i =0 ; i < range; i++) { +if (zerolength[i] > longest) { + longest = zerolength[i]; + colonpos = i; + } + } +if (longest ==1 )/* don't compress a single 0 */ + colonpos =-1 ; + +/* emit address */ +for (i =0 ; i < range; i++) { +if (i == colonpos) { +if (needcolon || i ==0 ) +trace_seq_printf (s,":" ); +trace_seq_printf (s,":" ); + needcolon = false; + i += longest -1 ; +continue ; + } +if (needcolon) { +trace_seq_printf (s,":" ); + needcolon = false; + } +/* hex u16 without leading 0s */ + word =ntohs (in6.s6_addr16[i]); + hi = word >>8 ; + lo = word &0xff ; +if (hi) +trace_seq_printf (s,"%x%02x" , hi, lo); +else +trace_seq_printf (s,"%x" , lo); + + needcolon = true; + } + +if (useIPv4) { +if (needcolon) +trace_seq_printf (s,":" ); +print_ip4_addr (s,'I' , &in6.s6_addr[12 ]); + } + +return ; +} + +static void print_ip6_addr (struct trace_seq *s,char i,unsigned char *buf) +{ +int j; + +for (j =0 ; j <16 ; j +=2 ) { +trace_seq_printf (s,"%02x%02x" , buf[j], buf[j+1 ]); +if (i =='I' && j <14 ) +trace_seq_printf (s,":" ); + } +} + +/* +* %pi4 print an IPv4 address with leading zeros +* %pI4 print an IPv4 address without leading zeros +* %pi6 print an IPv6 address without colons +* %pI6 print an IPv6 address with colons +* %pI6c print an IPv6 address in compressed form with colons +* %pISpc print an IP address based on sockaddr; p adds port. +*/ +static int print_ipv4_arg (struct trace_seq *s,const char *ptr,char i, +void *data,int size,struct event_format *event, +struct print_arg *arg) +{ +unsigned char *buf; + +if (arg->type ==PRINT_FUNC ) { +process_defined_func (s, data, size, event, arg); +return 0 ; + } + +if (arg->type !=PRINT_FIELD ) { +trace_seq_printf (s,"ARG TYPE NOT FIELD BUT %d" , arg->type); +return 0 ; + } + +if (!arg->field.field) { + arg->field.field = +pevent_find_any_field (event, arg->field.name); +if (!arg->field.field) { +do_warning ("%s: field %s not found" , + __func__, arg->field.name); +return 0 ; + } + } + + buf = data + arg->field.field->offset; + +if (arg->field.field->size !=4 ) { +trace_seq_printf (s,"INVALIDIPv4" ); +return 0 ; + } +print_ip4_addr (s, i, buf); + +return 0 ; +} + +static int print_ipv6_arg (struct trace_seq *s,const char *ptr,char i, +void *data,int size,struct event_format *event, +struct print_arg *arg) +{ +char have_c =0 ; +unsigned char *buf; +int rc =0 ; + +/* pI6c */ +if (i =='I' && *ptr =='c' ) { + have_c =1 ; + ptr++; + rc++; + } + +if (arg->type ==PRINT_FUNC ) { +process_defined_func (s, data, size, event, arg); +return rc; + } + +if (arg->type !=PRINT_FIELD ) { +trace_seq_printf (s,"ARG TYPE NOT FIELD BUT %d" , arg->type); +return rc; + } + +if (!arg->field.field) { + arg->field.field = +pevent_find_any_field (event, arg->field.name); +if (!arg->field.field) { +do_warning ("%s: field %s not found" , + __func__, arg->field.name); +return rc; + } + } + + buf = data + arg->field.field->offset; + +if (arg->field.field->size !=16 ) { +trace_seq_printf (s,"INVALIDIPv6" ); +return rc; + } + +if (have_c) +print_ip6c_addr (s, buf); +else +print_ip6_addr (s, i, buf); + +return rc; +} + +static int print_ipsa_arg (struct trace_seq *s,const char *ptr,char i, +void *data,int size,struct event_format *event, +struct print_arg *arg) +{ +char have_c =0 , have_p =0 ; +unsigned char *buf; +struct sockaddr_storage *sa; +int rc =0 ; + +/* pISpc */ +if (i =='I' ) { +if (*ptr =='p' ) { + have_p =1 ; + ptr++; + rc++; + } +if (*ptr =='c' ) { + have_c =1 ; + ptr++; + rc++; + } + } + +if (arg->type ==PRINT_FUNC ) { +process_defined_func (s, data, size, event, arg); +return rc; + } + +if (arg->type !=PRINT_FIELD ) { +trace_seq_printf (s,"ARG TYPE NOT FIELD BUT %d" , arg->type); +return rc; + } + +if (!arg->field.field) { + arg->field.field = +pevent_find_any_field (event, arg->field.name); +if (!arg->field.field) { +do_warning ("%s: field %s not found" , + __func__, arg->field.name); +return rc; + } + } + + sa = (struct sockaddr_storage *) (data + arg->field.field->offset); + +if (sa->ss_family ==AF_INET ) { +struct sockaddr_in *sa4 = (struct sockaddr_in *) sa; + +if (arg->field.field->size <sizeof (struct sockaddr_in )) { +trace_seq_printf (s,"INVALIDIPv4" ); +return rc; + } + +print_ip4_addr (s, i, (unsigned char *) &sa4->sin_addr); +if (have_p) +trace_seq_printf (s,":%d" ,ntohs (sa4->sin_port)); + + + }else if (sa->ss_family ==AF_INET6 ) { +struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa; + +if (arg->field.field->size <sizeof (struct sockaddr_in6 )) { +trace_seq_printf (s,"INVALIDIPv6" ); +return rc; + } + +if (have_p) +trace_seq_printf (s,"[" ); + + buf = (unsigned char *) &sa6->sin6_addr; +if (have_c) +print_ip6c_addr (s, buf); +else +print_ip6_addr (s, i, buf); + +if (have_p) +trace_seq_printf (s,"]:%d" ,ntohs (sa6->sin6_port)); + } + +return rc; +} + +static int print_ip_arg (struct trace_seq *s,const char *ptr, +void *data,int size,struct event_format *event, +struct print_arg *arg) +{ +char i = *ptr;/* 'i' or 'I' */ +char ver; +int rc =0 ; + + ptr++; + rc++; + + ver = *ptr; + ptr++; + rc++; + +switch (ver) { +case '4' : + rc +=print_ipv4_arg (s, ptr, i, data, size, event, arg); +break ; +case '6' : + rc +=print_ipv6_arg (s, ptr, i, data, size, event, arg); +break ; +case 'S' : + rc +=print_ipsa_arg (s, ptr, i, data, size, event, arg); +break ; +default : +return 0 ; + } + +return rc; +} +static int is_printable_array (char *p,unsigned int len) {unsigned int i;
@@ -4337,6 +4656,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ptr++; arg = arg->next;break ; + }else if (*(ptr+1 ) =='I' || *(ptr+1 ) =='i' ) { +int n; + + n =print_ip_arg (s, ptr+1 , data, size, event, arg); +if (n >0 ) { + ptr += n; + arg = arg->next; +break ; + } }/* fall through */
Signature · 1 line
1.9.3
Quoted 128 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling, it has my latest perf/urgent pull content,
please let me know if you don't want it to be submitted like that, i.e. if you have any problems with my latest perf/urgent pull request and I'll try to address it ASAP.- Arnaldo
The following changes since commit
25dd9171f51c482eb7c4dc8618766ae733756e2d:perf probe: Fix probing kretprobes (2015-01-21 10:06:24 -0300)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingofor you to fetch changes up to
3d199b5be53348bef84883013c484b414adf0a2e:tools lib traceevent: Add support for IP address formats (2015-01-26 12:04:41 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:User visible:
- Enable sampling loads and stores simultaneously in 'perf mem' (Stephane Eranian)
- 'perf diff' output improvements (Namhyung Kim)
- Fix error reporting for evsel pgfault constructor (Arnaldo Carvalho de Melo)
Infrastructure:
- Move debugfs sterrno like method to
tools/lib/so that it may be used by other tools, as 'perf probe' will be soon (Arnaldo Carvalho de Melo)- Introduce function fro deleting/removing
hist_entryto avoid code duplication (Arnaldo Carvalho de Melo)- Support parsing parameterized events (Cody P Schafer)
- Add support for IP address formats in libtraceevent (David Ahern)
- Fix typo in
sample-parsing.c'perf test' entry (Rasmus Villemoes)- Remove some unused functions from
color.c(Rickard Strandqvist)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Arnaldo Carvalho de Melo (9):
perf mem: Move themem_operationsglobal to structperf_memperf tools: Remove EOL whitespaces
perf hists: Renamehist_entry__freeto__delete
perf hists: Introduce function for deleting/removinghist_entrytools lib fs: Adopt debugfs open strerrno method
tools lib fs: Pass filename todebugfs__strerror_open
perf trace: Fix error reporting for evsel pgfault constructor tools lib fs debugfs: Introducedebugfs__strerror_open_tptools lib fs debugfs: Check if debugfs is mounted when handling ENOENTCody P Schafer (4):
perf tools: Support parsing parameterized events perf tools: Extendformat_alias()to include event parameters perf Documentation: Add event parameters
perf tools: Document parameterized and symbolic eventsDavid Ahern (1):
tools lib traceevent: Add support for IP address formatsNamhyung Kim (9):
perf report: Get rid ofreport__inc_stat()
perf tools: Allow use of an exclusive option more than once perf diff: Get rid ofhists__compute_resort()perf diff: Print diff result more precisely
perf diff: Introducefmt_to_data_file()helper perf tools: Pass structperf_hpp_fmtto its callbacks perf diff: Fix output ordering to honor next column perf diff: Fix -o/--order option behavior
perf ui/tui: Show fatal error message only if existsRasmus Villemoes (1):
perf tests: Fix typo insample-parsing.cRickard Strandqvist (1):
perf tools: Remove some unused functions fromcolor.cStephane Eranian (1):
perf mem: Enable sampling loads and stores simultaneously.../testing/sysfs-bus-event_source-devices-events | 6 + tools/lib/api/fs/debugfs.c | 43 +++ tools/lib/api/fs/debugfs.h | 3 + tools/lib/traceevent/event-parse.c | 328 +++++++++++++++++++++ tools/perf/Documentation/perf-buildid-cache.txt | 2 +- tools/perf/Documentation/perf-list.txt | 13 + tools/perf/Documentation/perf-mem.txt | 9 +- tools/perf/Documentation/perf-record.txt | 12 + tools/perf/Documentation/perf-script.txt | 28 +- tools/perf/Documentation/perf-stat.txt | 20 +- tools/perf/builtin-buildid-cache.c | 4 +- tools/perf/builtin-diff.c | 248 ++++++++++------ tools/perf/builtin-mem.c | 131 ++++++-- tools/perf/builtin-report.c | 16 +- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/builtin-trace.c | 106 ++++--- tools/perf/tests/attr.py | 1 - tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_output.c | 2 +- tools/perf/tests/make | 1 - tools/perf/tests/parse-events.c | 2 +- tools/perf/tests/sample-parsing.c | 2 +- tools/perf/ui/browsers/annotate.c | 3 +- tools/perf/ui/hist.c | 12 +- tools/perf/ui/progress.h | 4 +- tools/perf/ui/tui/helpline.c | 3 + tools/perf/ui/tui/setup.c | 3 +- tools/perf/util/annotate.c | 2 +- tools/perf/util/color.c | 126 -------- tools/perf/util/color.h | 2 - tools/perf/util/evlist.c | 27 -- tools/perf/util/evlist.h | 1 - tools/perf/util/hist.c | 48 ++- tools/perf/util/hist.h | 11 +- tools/perf/util/parse-events.c | 6 +- tools/perf/util/parse-events.h | 1 +
Quoted 8 lines
tools/perf/util/parse-options.c | 2 +- tools/perf/util/pmu.c | 102 ++++++- tools/perf/util/python.c | 2 +- .../util/scripting-engines/trace-event-python.c | 2 +- tools/perf/util/session.c | 2 +- tools/perf/util/sort.c | 37 ++- tools/perf/util/symbol.c | 2 +- 44 files changed, 950 insertions(+), 431 deletions(-)
Pulled, thanks a lot Arnaldo!
Note that there was some minimal interaction with Frederic's pending perf/hw_breakpoint work, in tools/perf/Documentation/perf-record.txt.
I resolved the conflict and merged perf/hw_breakpoint into perf/core as well, to avoid future complications. (Once I've pushed it all out you guys might want to double check what I did there though, just to make sure.)
Thanks,
Ingo
Arnaldo Carvalho de Melo
maintainerEm Wed, Jan 28, 2015 at 03:50:15PM +0100, Ingo Molnar escreveu:
Quoted 1 line
Pulled, thanks a lot Arnaldo!
Thanks!
Quoted 7 lines
Note that there was some minimal interaction with Frederic's pending perf/hw_breakpoint work, in
tools/perf/Documentation/perf-record.txt.I resolved the conflict and merged perf/hw_breakpoint into perf/core as well, to avoid future complications. (Once I've pushed it all out you guys might want to double check what I did there though, just to make sure.)
As soon as 'git remote update tip' gets this stuff, I'll check it!
- Arnaldo