perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerFrom: Arnaldo Carvalho de Melo <[email protected]>
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit ac931f87a647ca156f65a4c00e7297165e4fa2d8:
perf: Fix building warning on ARM 32 (2014-12-19 13:09:43 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
for you to fetch changes up to e51679f54467febc6e9f1091c0ac8c31b54d59a1:
perf tools: Remove some unused functions from color.c (2014-12-22 11:55:09 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Enable sampling loads and stores simultaneously by default in 'perf mem' (Stephane Eranian)
- Show progress bar in more places while doing histogram processing in the hists browser (Namhyung Kim)
- Print backtrace symbols when segfault occurs in 'report' (Namhyung Kim)
Infrastructure:
- Consistency and code duplication elimination fixes in the hists code (Arnaldo Carvalho de Melo)
- Append callchains only when requested (Namhyung Kim)
- Remove some unused functions from color.c (Rickard Strandqvist)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (4):
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
Namhyung Kim (4):
perf report: Get rid of report__inc_stat()
perf report: Show progress bar for output resorting perf ui/tui: Print backtrace symbols when segfault occurs perf callchain: Append callchains only when requested
Rickard Strandqvist (1):
perf tools: Remove some unused functions from color.c
Stephane Eranian (1):
perf mem: Enable sampling loads and stores simultaneously
tools/perf/Documentation/perf-buildid-cache.txt | 2 +- tools/perf/Documentation/perf-mem.txt | 9 +- tools/perf/Documentation/perf-script.txt | 28 ++--- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-buildid-cache.c | 4 +- tools/perf/builtin-diff.c | 4 +- tools/perf/builtin-mem.c | 131 ++++++++++++++++----- tools/perf/builtin-report.c | 40 ++++--- tools/perf/builtin-stat.c | 2 +- tools/perf/builtin-top.c | 6 +- tools/perf/builtin-trace.c | 80 ++++++------- tools/perf/tests/attr.py | 1 - tools/perf/tests/hists_cumulate.c | 4 +- tools/perf/tests/hists_filter.c | 2 +- tools/perf/tests/hists_output.c | 12 +- 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/ui/tui/setup.c | 26 +++- tools/perf/util/annotate.c | 2 +- tools/perf/util/color.c | 126 -------------------- tools/perf/util/color.h | 2 - tools/perf/util/hist.c | 59 ++++++---- tools/perf/util/hist.h | 4 +- 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 +- 30 files changed, 278 insertions(+), 292 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/10 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/10 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/10 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
@@ -166,7 +166,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
@@ -229,7 +229,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
@@ -660,7 +660,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/10 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
@@ -266,7 +266,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); } } }
@@ -289,7 +289,7 @@ void hists__delete_entries(struct hists *hists)if (!n->filtered) --hists->nr_non_filtered_entries; -hist_entry__free (n); +hist_entry__delete (n); } }
@@ -939,7 +939,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);
@@ -978,7 +978,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);void hists__collapse_resort (struct hists *hists,struct ui_progress *prog);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/10 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
@@ -240,6 +240,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);
@@ -257,16 +271,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); } } }
@@ -280,16 +285,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/10 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 ;
@@ -486,6 +473,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
@@ -428,6 +428,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/10 perf report: Show progress bar for output resorting
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Sometimes it takes a long time to resort hist entries for output in case of a large data file. Show a progress bar window and inform user.
--- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-diff.c | 2 +- tools/perf/builtin-report.c | 24 ++++++++++++++++++++++-- tools/perf/builtin-top.c | 4 ++-- tools/perf/tests/hists_cumulate.c | 2 +- tools/perf/tests/hists_filter.c | 2 +- tools/perf/tests/hists_output.c | 10 +++++----- tools/perf/util/hist.c | 10 +++++++++- tools/perf/util/hist.h | 2 +- 9 files changed, 43 insertions(+), 15 deletions(-)
tools/perf/builtin-annotate.c +1 -1
@@ -232,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann)if (nr_samples >0 ) { total_nr_samples += nr_samples;hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );if (symbol_conf.event_group && !perf_evsel__is_group_leader (pos))
tools/perf/builtin-diff.c +1 -1
@@ -605,7 +605,7 @@ static void hists__process(struct hists *hists)hists__precompute (hists);hists__compute_resort (hists); }else { -hists__output_resort (hists); +hists__output_resort (hists,NULL ); }hists__fprintf (hists, true,0 ,0 ,0 , stdout);
tools/perf/builtin-report.c +22 -2
@@ -444,6 +444,19 @@ static void report__collapse_hists(struct report *rep)ui_progress__finish (); } +static void report__output_resort (struct report *rep) +{ +struct ui_progress prog; +struct perf_evsel *pos; + +ui_progress__init (&prog, rep->nr_entries,"Sorting events for output..." ); + +evlist__for_each (rep->session->evlist, pos) +hists__output_resort (evsel__hists (pos), &prog); + +ui_progress__finish (); +} +static int __cmd_report (struct report *rep) {int ret;
@@ -495,13 +508,20 @@ static int __cmd_report(struct report *rep)if (session_done ())return 0 ; +/* +* recalculate number of entries after collapsing since it +* might be changed during the collapse phase. +*/ + rep->nr_entries =0 ; +evlist__for_each (session->evlist, pos) + rep->nr_entries +=evsel__hists (pos)->nr_entries; +if (rep->nr_entries ==0 ) {ui__error ("The %s file has no samples!\n" , file->path);return 0 ; } -evlist__for_each (session->evlist, pos) -hists__output_resort (evsel__hists (pos)); +report__output_resort (rep);return report__browse_hists (rep); }
tools/perf/builtin-top.c +2 -2
@@ -285,7 +285,7 @@ static void perf_top__print_sym_table(struct perf_top *top) }hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );hists__output_recalc_col_len (hists, top->print_entries - printed);putchar ('\n' );
@@ -554,7 +554,7 @@ static void perf_top__sort_new_samples(void *arg) }hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL ); }static void *display_thread_tui (void *arg)
tools/perf/tests/hists_cumulate.c +1 -1
@@ -187,7 +187,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec* function since TEST_ASSERT_VAL() returns in case of failure. */ hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );if (verbose >2 ) { pr_info("use callchain: %d, cumulate callchain: %d\n",
tools/perf/tests/hists_filter.c +1 -1
@@ -138,7 +138,7 @@ int test__hists_filter(void)struct hists *hists =evsel__hists (evsel);hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );if (verbose >2 ) {pr_info ("Normal histogram\n" );
tools/perf/tests/hists_output.c +5 -5
@@ -152,7 +152,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine) goto out;hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );if (verbose >2 ) {pr_info ("[fields = %s, sort = %s]\n" , field_order, sort_order);
@@ -252,7 +252,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine) goto out;hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );if (verbose >2 ) {pr_info ("[fields = %s, sort = %s]\n" , field_order, sort_order);
@@ -306,7 +306,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) goto out;hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );if (verbose >2 ) {pr_info ("[fields = %s, sort = %s]\n" , field_order, sort_order);
@@ -384,7 +384,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) goto out;hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );if (verbose >2 ) {pr_info ("[fields = %s, sort = %s]\n" , field_order, sort_order);
@@ -487,7 +487,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine) goto out;hists__collapse_resort (hists,NULL ); -hists__output_resort (hists); +hists__output_resort (hists,NULL );if (verbose >2 ) {pr_info ("[fields = %s, sort = %s]\n" , field_order, sort_order);
tools/perf/util/hist.c +9 -1
@@ -6,6 +6,7 @@#include "evlist.h" #include "evsel.h" #include "annotate.h" +#include "ui/progress.h" #include <math.h> static bool hists__filter_entry_by_dso(struct hists *hists,
@@ -985,6 +986,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,else p = &(*p)->rb_right; } + hists->nr_entries++;rb_link_node (&he->rb_node_in, parent, p);rb_insert_color (&he->rb_node_in, root);
@@ -1022,7 +1024,10 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)if (!sort__need_collapse)return ; + hists->nr_entries =0 ; + root =hists__get_rotate_entries_in (hists); + next =rb_first (root);while (next) {
@@ -1117,7 +1122,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,rb_insert_color (&he->rb_node, entries); } -void hists__output_resort (struct hists *hists) +void hists__output_resort (struct hists *hists,struct ui_progress *prog) {struct rb_root *root;struct rb_node *next;
@@ -1146,6 +1151,9 @@ void hists__output_resort(struct hists *hists)if (!n->filtered)hists__calc_col_len (hists, n); + +if (prog) +ui_progress__update (prog,1 ); } }
tools/perf/util/hist.h +1 -1
@@ -121,7 +121,7 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size, struct hists *hists);void hist_entry__delete (struct hist_entry *he); -void hists__output_resort (struct hists *hists); +void hists__output_resort (struct hists *hists,struct ui_progress *prog);void hists__collapse_resort (struct hists *hists,struct ui_progress *prog);void hists__decay_entries (struct hists *hists,bool zap_user,bool zap_kernel);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 8/10 perf ui/tui: Print backtrace symbols when segfault occurs
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The output will look like below. (I added an error into ui__init() for the test).
$ perf report perf: Segmentation fault -------- backtrace -------- perf[0x503781] /usr/lib/libc.so.6(+0x33b20)[0x7f1a14f04b20] perf(ui__init+0xd5)[0x503645] perf(setup_browser+0x97)[0x4ce4e7] perf(cmd_report+0xcea)[0x4392ba] perf[0x428493] perf(main+0x60a)[0x427c0a] /usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7f1a14ef1040] perf[0x427d29] [0x0]
--- tools/perf/ui/tui/setup.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-)
tools/perf/ui/tui/setup.c +24 -2
@@ -1,5 +1,8 @@#include <signal.h> #include <stdbool.h> +#ifdef HAVE_BACKTRACE_SUPPORT +#include <execinfo.h> +#endif #include "../../util/cache.h" #include "../../util/debug.h"
@@ -88,6 +91,25 @@ int ui__getch(int delay_secs)return SLkp_getkey (); } +#ifdef HAVE_BACKTRACE_SUPPORT +static void ui__signal_backtrace (int sig) +{ +void *stackdump[32 ]; +size_t size; + +ui__exit (false); +psignal (sig,"perf" ); + +printf ("-------- backtrace --------\n" ); + size =backtrace (stackdump,ARRAY_SIZE (stackdump)); +backtrace_symbols_fd (stackdump, size,STDOUT_FILENO ); + +exit (0 ); +} +#else +# define ui__signal_backtrace ui__signal +#endif +static void ui__signal (int sig) {ui__exit (false);
@@ -122,8 +144,8 @@ int ui__init(void)ui_browser__init ();tui_progress__init (); -signal (SIGSEGV , ui__signal); -signal (SIGFPE , ui__signal); +signal (SIGSEGV , ui__signal_backtrace); +signal (SIGFPE , ui__signal_backtrace);signal (SIGINT , ui__signal);signal (SIGQUIT , ui__signal);signal (SIGTERM , ui__signal);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 9/10 perf callchain: Append callchains only when requested
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
The perf report --children can be called with callchain disabled so no need to append callchains. Actually the root of callchain tree is not initialized properly in this case.
--- tools/perf/util/hist.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
tools/perf/util/hist.c +4 -3
@@ -300,7 +300,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,size_t callchain_size =0 ;struct hist_entry *he; -if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) +if (symbol_conf.use_callchain) callchain_size =sizeof (struct callchain_root ); he =zalloc (sizeof (*he) + callchain_size);
@@ -735,7 +735,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter, iter->he = he; he_cache[iter->curr++] = he; -callchain_append (he->callchain, &callchain_cursor, sample->period); +hist_entry__append_callchain (he, sample);/* * We need to re-initialize the cursor since callchain_append()
@@ -808,7 +808,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter, iter->he = he; he_cache[iter->curr++] = he; -callchain_append (he->callchain, &cursor, sample->period); +if (symbol_conf.use_callchain) +callchain_append (he->callchain, &cursor, sample->period);return 0 ; }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 10/10 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