perf/urgent fixes and improvements:
User visible: - 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: - Append callchains only when requested (Namhyung Kim) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJUmYq/AAoJEBpxZoYYoA71M6cH/iK+G5s4u2sa66BbgSfp3DP1 Vff5mW83cZ92JR4uSpLhTyk+TlQ8NwekN0hWnzW9MwAOnsLVAo2IFLg99Xv979rl 1T0zpU13ord/9XdIdd0f2Ngx1m0RQGIh3NIfAitzkFfjUvpk7omOwBGk17Bvzlhi eY5VcldFX5szaPdtcAugd622pW0NMnFyRVCPMA15NZ5Ct4zvyRiv5zxlMhxu/F3o spmjSWzJ5TKpzjr20XSjk3g9CbbEeALloIY2MFbdalXjjWhKCGk+qyeb0qmWGRAb VPm32T2TzmaapFZXJrWLLi8cYnIMELGIt3L8mmH+MVzqFuVPTcn2xCNhdRPINIo= =ktsc -----END PGP SIGNATURE----- Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent Pull perf/urgent fixes from Arnaldo Carvalho de Melo: User visible fixes: - 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 fixes: - Append callchains only when requested (Namhyung Kim) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
5b5e76218f
|
@ -232,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
|
||||||
if (nr_samples > 0) {
|
if (nr_samples > 0) {
|
||||||
total_nr_samples += nr_samples;
|
total_nr_samples += nr_samples;
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
if (symbol_conf.event_group &&
|
if (symbol_conf.event_group &&
|
||||||
!perf_evsel__is_group_leader(pos))
|
!perf_evsel__is_group_leader(pos))
|
||||||
|
|
|
@ -605,7 +605,7 @@ static void hists__process(struct hists *hists)
|
||||||
hists__precompute(hists);
|
hists__precompute(hists);
|
||||||
hists__compute_resort(hists);
|
hists__compute_resort(hists);
|
||||||
} else {
|
} else {
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
hists__fprintf(hists, true, 0, 0, 0, stdout);
|
hists__fprintf(hists, true, 0, 0, 0, stdout);
|
||||||
|
|
|
@ -457,6 +457,19 @@ static void report__collapse_hists(struct report *rep)
|
||||||
ui_progress__finish();
|
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)
|
static int __cmd_report(struct report *rep)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -505,13 +518,20 @@ static int __cmd_report(struct report *rep)
|
||||||
if (session_done())
|
if (session_done())
|
||||||
return 0;
|
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) {
|
if (rep->nr_entries == 0) {
|
||||||
ui__error("The %s file has no samples!\n", file->path);
|
ui__error("The %s file has no samples!\n", file->path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
evlist__for_each(session->evlist, pos)
|
report__output_resort(rep);
|
||||||
hists__output_resort(evsel__hists(pos));
|
|
||||||
|
|
||||||
return report__browse_hists(rep);
|
return report__browse_hists(rep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,7 +285,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
|
||||||
}
|
}
|
||||||
|
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
hists__output_recalc_col_len(hists, top->print_entries - printed);
|
hists__output_recalc_col_len(hists, top->print_entries - printed);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
@ -554,7 +554,7 @@ static void perf_top__sort_new_samples(void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *display_thread_tui(void *arg)
|
static void *display_thread_tui(void *arg)
|
||||||
|
|
|
@ -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.
|
* function since TEST_ASSERT_VAL() returns in case of failure.
|
||||||
*/
|
*/
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
if (verbose > 2) {
|
if (verbose > 2) {
|
||||||
pr_info("use callchain: %d, cumulate callchain: %d\n",
|
pr_info("use callchain: %d, cumulate callchain: %d\n",
|
||||||
|
|
|
@ -138,7 +138,7 @@ int test__hists_filter(void)
|
||||||
struct hists *hists = evsel__hists(evsel);
|
struct hists *hists = evsel__hists(evsel);
|
||||||
|
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
if (verbose > 2) {
|
if (verbose > 2) {
|
||||||
pr_info("Normal histogram\n");
|
pr_info("Normal histogram\n");
|
||||||
|
|
|
@ -152,7 +152,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
if (verbose > 2) {
|
if (verbose > 2) {
|
||||||
pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
|
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;
|
goto out;
|
||||||
|
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
if (verbose > 2) {
|
if (verbose > 2) {
|
||||||
pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
|
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;
|
goto out;
|
||||||
|
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
if (verbose > 2) {
|
if (verbose > 2) {
|
||||||
pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
|
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;
|
goto out;
|
||||||
|
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
if (verbose > 2) {
|
if (verbose > 2) {
|
||||||
pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
|
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;
|
goto out;
|
||||||
|
|
||||||
hists__collapse_resort(hists, NULL);
|
hists__collapse_resort(hists, NULL);
|
||||||
hists__output_resort(hists);
|
hists__output_resort(hists, NULL);
|
||||||
|
|
||||||
if (verbose > 2) {
|
if (verbose > 2) {
|
||||||
pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
|
pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#ifdef HAVE_BACKTRACE_SUPPORT
|
||||||
|
#include <execinfo.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../../util/cache.h"
|
#include "../../util/cache.h"
|
||||||
#include "../../util/debug.h"
|
#include "../../util/debug.h"
|
||||||
|
@ -88,6 +91,25 @@ int ui__getch(int delay_secs)
|
||||||
return SLkp_getkey();
|
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)
|
static void ui__signal(int sig)
|
||||||
{
|
{
|
||||||
ui__exit(false);
|
ui__exit(false);
|
||||||
|
@ -122,8 +144,8 @@ int ui__init(void)
|
||||||
ui_browser__init();
|
ui_browser__init();
|
||||||
tui_progress__init();
|
tui_progress__init();
|
||||||
|
|
||||||
signal(SIGSEGV, ui__signal);
|
signal(SIGSEGV, ui__signal_backtrace);
|
||||||
signal(SIGFPE, ui__signal);
|
signal(SIGFPE, ui__signal_backtrace);
|
||||||
signal(SIGINT, ui__signal);
|
signal(SIGINT, ui__signal);
|
||||||
signal(SIGQUIT, ui__signal);
|
signal(SIGQUIT, ui__signal);
|
||||||
signal(SIGTERM, ui__signal);
|
signal(SIGTERM, ui__signal);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "evlist.h"
|
#include "evlist.h"
|
||||||
#include "evsel.h"
|
#include "evsel.h"
|
||||||
#include "annotate.h"
|
#include "annotate.h"
|
||||||
|
#include "ui/progress.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
static bool hists__filter_entry_by_dso(struct hists *hists,
|
static bool hists__filter_entry_by_dso(struct hists *hists,
|
||||||
|
@ -303,7 +304,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
|
||||||
size_t callchain_size = 0;
|
size_t callchain_size = 0;
|
||||||
struct hist_entry *he;
|
struct hist_entry *he;
|
||||||
|
|
||||||
if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain)
|
if (symbol_conf.use_callchain)
|
||||||
callchain_size = sizeof(struct callchain_root);
|
callchain_size = sizeof(struct callchain_root);
|
||||||
|
|
||||||
he = zalloc(sizeof(*he) + callchain_size);
|
he = zalloc(sizeof(*he) + callchain_size);
|
||||||
|
@ -736,7 +737,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
|
||||||
iter->he = he;
|
iter->he = he;
|
||||||
he_cache[iter->curr++] = 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()
|
* We need to re-initialize the cursor since callchain_append()
|
||||||
|
@ -809,6 +810,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
|
||||||
iter->he = he;
|
iter->he = he;
|
||||||
he_cache[iter->curr++] = he;
|
he_cache[iter->curr++] = he;
|
||||||
|
|
||||||
|
if (symbol_conf.use_callchain)
|
||||||
callchain_append(he->callchain, &cursor, sample->period);
|
callchain_append(he->callchain, &cursor, sample->period);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -987,6 +989,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
|
||||||
else
|
else
|
||||||
p = &(*p)->rb_right;
|
p = &(*p)->rb_right;
|
||||||
}
|
}
|
||||||
|
hists->nr_entries++;
|
||||||
|
|
||||||
rb_link_node(&he->rb_node_in, parent, p);
|
rb_link_node(&he->rb_node_in, parent, p);
|
||||||
rb_insert_color(&he->rb_node_in, root);
|
rb_insert_color(&he->rb_node_in, root);
|
||||||
|
@ -1024,7 +1027,10 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
|
||||||
if (!sort__need_collapse)
|
if (!sort__need_collapse)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
hists->nr_entries = 0;
|
||||||
|
|
||||||
root = hists__get_rotate_entries_in(hists);
|
root = hists__get_rotate_entries_in(hists);
|
||||||
|
|
||||||
next = rb_first(root);
|
next = rb_first(root);
|
||||||
|
|
||||||
while (next) {
|
while (next) {
|
||||||
|
@ -1119,7 +1125,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
|
||||||
rb_insert_color(&he->rb_node, 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_root *root;
|
||||||
struct rb_node *next;
|
struct rb_node *next;
|
||||||
|
@ -1148,6 +1154,9 @@ void hists__output_resort(struct hists *hists)
|
||||||
|
|
||||||
if (!n->filtered)
|
if (!n->filtered)
|
||||||
hists__calc_col_len(hists, n);
|
hists__calc_col_len(hists, n);
|
||||||
|
|
||||||
|
if (prog)
|
||||||
|
ui_progress__update(prog, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
|
||||||
struct hists *hists);
|
struct hists *hists);
|
||||||
void hist_entry__free(struct hist_entry *);
|
void hist_entry__free(struct hist_entry *);
|
||||||
|
|
||||||
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__collapse_resort(struct hists *hists, struct ui_progress *prog);
|
||||||
|
|
||||||
void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
|
void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
|
||||||
|
|
Loading…
Reference in New Issue