perf/urgent fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit ed9eb845d7916b2bc863e5b93c82e18be8faf032:
Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent (2015-01-08 08:59:22 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-urgent-for-mingo
for you to fetch changes up to c09e31cc128cf1aec3a6cd47203508fbf0082873:
perf hists browser: Fix segfault when showing callchain (2015-01-08 11:59:16 -0300)
----------------------------------------------------------------
perf/urgent fixes:
. Free callchains when hist entries are deleted, plugging a massive leak in
'top -g', where hist_entries (and its callchains) are decayed over time. (Namhyung Kim)
. Fix segfault when showing callchain in the hists browser (report & top) (Namhyung Kim)
. Fix children sort key behavior, and also the 'perf test 32' test that
was failing due to reliance on undefined behaviour (Namhyung Kim)
----------------------------------------------------------------
Namhyung Kim (3):
perf hists: Fix children sort key behavior
perf callchain: Free callchains when hist entries are deleted perf hists browser: Fix segfault when showing callchain
tools/perf/tests/hists_cumulate.c | 64 +++++++++++++++++++-------------------- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/ui/hist.c | 3 ++ tools/perf/util/callchain.c | 30 ++++++++++++++++++ tools/perf/util/callchain.h | 2 ++ tools/perf/util/hist.c | 1 + 6 files changed, 69 insertions(+), 33 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/3 perf hists: Fix children sort key behavior
From: Namhyung Kim <[email protected]>
When perf report --children resorts output fields, it tries to put caller above the callee. But this was only meaningful for a same thread and doing this requires callchain enabled. So fix its check before comparing the callchain depth.
This also changes the hist accumulation tests: In test 3, xmalloc in bash thread should be above than other perf threads due to alphabetical order of comm string. Also it's under page_fault in bash thread since alphabetical order of dso name. The sys_perf_event_open in perf thread is put on the last line since it's self overhead is 0.
In test 4, the sys_perf_event_open is put above other perf entries that have same children overhead since its callchain depth is smaller.
--- tools/perf/tests/hists_cumulate.c | 64 +++++++++++++++++++-------------------- tools/perf/ui/hist.c | 3 ++ 2 files changed, 35 insertions(+), 32 deletions(-)
tools/perf/tests/hists_cumulate.c +32 -32
@@ -454,12 +454,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)* 30.00% 10.00% perf perf [.] cmd_record * 20.00% 0.00% bash libc [.] malloc * 10.00% 10.00% bash [kernel] [k] page_fault -* 10.00% 10.00% perf [kernel] [k] schedule -* 10.00% 0.00% perf [kernel] [k] sys_perf_event_open +* 10.00% 10.00% bash bash [.] xmalloc * 10.00% 10.00% perf [kernel] [k] page_fault -* 10.00% 10.00% perf libc [.] free * 10.00% 10.00% perf libc [.] malloc -* 10.00% 10.00% bash bash [.] xmalloc +* 10.00% 10.00% perf [kernel] [k] schedule +* 10.00% 10.00% perf libc [.] free +* 10.00% 0.00% perf [kernel] [k] sys_perf_event_open */ struct result expected[] = { {7000 ,2000 ,"perf" ,"perf" ,"main" },
@@ -468,12 +468,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine) { 3000, 1000, "perf", "perf", "cmd_record" }, { 2000, 0, "bash", "libc", "malloc" }, { 1000, 1000, "bash", "[kernel]", "page_fault" }, - { 1000, 1000, "perf", "[kernel]", "schedule" }, - { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, + { 1000, 1000, "bash", "bash", "xmalloc" }, { 1000, 1000, "perf", "[kernel]", "page_fault" }, + { 1000, 1000, "perf", "[kernel]", "schedule" }, { 1000, 1000, "perf", "libc", "free" }, { 1000, 1000, "perf", "libc", "malloc" }, - { 1000, 1000, "bash", "bash", "xmalloc" }, + { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, }; symbol_conf.use_callchain = false;
@@ -537,10 +537,13 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)* malloc * main * -* 10.00% 10.00% perf [kernel] [k] schedule +* 10.00% 10.00% bash bash [.] xmalloc * | -* --- schedule -* run_command +* --- xmalloc +* malloc +* xmalloc <--- NOTE: there's a cycle +* malloc +* xmalloc * main * * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
@@ -556,6 +559,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)* run_command * main * +* 10.00% 10.00% perf [kernel] [k] schedule +* | +* --- schedule +* run_command +* main +* * 10.00% 10.00% perf libc [.] free * | * --- free
@@ -570,15 +579,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)* run_command * main * -* 10.00% 10.00% bash bash [.] xmalloc -* | -* --- xmalloc -* malloc -* xmalloc <--- NOTE: there's a cycle -* malloc -* xmalloc -* main -* */ struct result expected[] = { {7000 ,2000 ,"perf" ,"perf" ,"main" },
@@ -587,12 +587,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) { 3000, 1000, "perf", "perf", "cmd_record" }, { 2000, 0, "bash", "libc", "malloc" }, { 1000, 1000, "bash", "[kernel]", "page_fault" }, - { 1000, 1000, "perf", "[kernel]", "schedule" }, + { 1000, 1000, "bash", "bash", "xmalloc" }, { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, { 1000, 1000, "perf", "[kernel]", "page_fault" }, + { 1000, 1000, "perf", "[kernel]", "schedule" }, { 1000, 1000, "perf", "libc", "free" }, { 1000, 1000, "perf", "libc", "malloc" }, - { 1000, 1000, "bash", "bash", "xmalloc" }, }; struct callchain_result expected_callchain[] = { {
@@ -622,9 +622,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) { "bash", "main" }, }, }, { - 3, { { "[kernel]", "schedule" }, - { "perf", "run_command" }, - { "perf", "main" }, }, + 6, { { "bash", "xmalloc" }, + { "libc", "malloc" }, + { "bash", "xmalloc" }, + { "libc", "malloc" }, + { "bash", "xmalloc" }, + { "bash", "main" }, }, }, { 3, { { "[kernel]", "sys_perf_event_open" },
@@ -638,6 +641,11 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) { "perf", "main" }, }, }, { + 3, { { "[kernel]", "schedule" }, + { "perf", "run_command" }, + { "perf", "main" }, }, + }, + { 4, { { "libc", "free" }, { "perf", "cmd_record" }, { "perf", "run_command" },
@@ -649,14 +657,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine) { "perf", "run_command" }, { "perf", "main" }, }, }, - { - 6, { { "bash", "xmalloc" }, - { "libc", "malloc" }, - { "bash", "xmalloc" }, - { "libc", "malloc" }, - { "bash", "xmalloc" }, - { "bash", "main" }, }, - }, }; symbol_conf.use_callchain = true;
tools/perf/ui/hist.c +3 -0
@@ -204,6 +204,9 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,if (ret)return ret; +if (a->thread != b->thread || !symbol_conf.use_callchain) +return 0 ; + ret = b->callchain->max_depth - a->callchain->max_depth; }return ret;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/3 perf callchain: Free callchains when hist entries are deleted
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
Markus reported that "perf top -g" can leak ~300MB per second on his machine. This is partly because it missed to free callchains when hist entries are deleted. Fix it.
--- tools/perf/util/callchain.c | 30 ++++++++++++++++++++++++++++++ tools/perf/util/callchain.h | 2 ++ tools/perf/util/hist.c | 1 + 3 files changed, 33 insertions(+)
tools/perf/util/callchain.c +30 -0
@@ -841,3 +841,33 @@ char *callchain_list__sym_name(struct callchain_list *cl,return bf; } + +static void free_callchain_node (struct callchain_node *node) +{ +struct callchain_list *list, *tmp; +struct callchain_node *child; +struct rb_node *n; + +list_for_each_entry_safe (list, tmp, &node->val, list) { +list_del (&list->list); +free (list); + } + + n =rb_first (&node->rb_root_in); +while (n) { + child = container_of(n, struct callchain_node, rb_node_in); + n =rb_next (n); +rb_erase (&child->rb_node_in, &node->rb_root_in); + +free_callchain_node (child); +free (child); + } +} + +void free_callchain (struct callchain_root *root) +{ +if (!symbol_conf.use_callchain) +return ; + +free_callchain_node (&root->node); +}
tools/perf/util/callchain.h +2 -0
@@ -198,4 +198,6 @@ static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,char *callchain_list__sym_name (struct callchain_list *cl,char *bf,size_t bfsize,bool show_dso); +void free_callchain (struct callchain_root *root); +#endif /* __PERF_CALLCHAIN_H */
tools/perf/util/hist.c +1 -0
@@ -947,6 +947,7 @@ void hist_entry__free(struct hist_entry *he)zfree (&he->mem_info);zfree (&he->stat_acc);free_srcline (he->srcline); +free_callchain (he->callchain);free (he); }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/3 perf hists browser: Fix segfault when showing callchain
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
When perf report on TUI shows callchain it checks first node has siblings to determine whether it needs to print percentage value.
But it missed a case that first node is NULL. So sometimes it segfaults like below:
$ perf top -g perf: Segmentation fault -------- backtrace -------- perf[0x4fcefb] /usr/lib/libc.so.6(+0x33b20)[0x7f2a35839b20] perf(rb_next+0x8)[0x47d3d8] perf[0x4f6058] perf[0x4f833b] perf[0x4f8610] perf[0x4f209e] perf(ui_browser__run+0x3a)[0x4f2e6a] perf[0x4f94ee] perf(perf_evlist__tui_browse_hists+0x94)[0x4fbbf4] perf[0x444d10] /usr/lib/libpthread.so.0(+0x7314)[0x7f2a37070314] /usr/lib/libc.so.6(clone+0x6d)[0x7f2a358ee5bd]
$ addr2line -e `which perf` 0x4f6058 /home/namhyung/project/linux/tools/perf/ui/browsers/hists.c:553
I don't know why the backtrace didn't print some symbols..
--- tools/perf/ui/browsers/hists.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/ui/browsers/hists.c +1 -1
@@ -550,7 +550,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser,bool need_percent; node =rb_first (root); - need_percent = !!rb_next (node); + need_percent = node &&rb_next (node);while (node) { struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
Signature · 1 line
1.9.3
Quoted 38 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
ed9eb845d7916b2bc863e5b93c82e18be8faf032:Merge tag 'perf-urgent-for-mingo' of
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linuxinto perf/urgent (2015-01-08 08:59:22 +0100)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-urgent-for-mingofor you to fetch changes up to
c09e31cc128cf1aec3a6cd47203508fbf0082873:perf hists browser: Fix segfault when showing callchain (2015-01-08 11:59:16 -0300)
----------------------------------------------------------------
perf/urgent fixes:. Free callchains when hist entries are deleted, plugging a massive leak in
'top -g', wherehist_entries(and its callchains) are decayed over time. (Namhyung Kim). Fix segfault when showing callchain in the hists browser (report & top) (Namhyung Kim)
. Fix children sort key behavior, and also the 'perf test 32' test that
was failing due to reliance on undefined behaviour (Namhyung Kim)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Namhyung Kim (3):
perf hists: Fix children sort key behavior
perf callchain: Free callchains when hist entries are deleted perf hists browser: Fix segfault when showing callchain
Quoted 7 lines
tools/perf/tests/hists_cumulate.c | 64 +++++++++++++++++++-------------------- tools/perf/ui/browsers/hists.c | 2 +- tools/perf/ui/hist.c | 3 ++ tools/perf/util/callchain.c | 30 ++++++++++++++++++ tools/perf/util/callchain.h | 2 ++ tools/perf/util/hist.c | 1 + 6 files changed, 69 insertions(+), 33 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo