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) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJUrqORAAoJEBpxZoYYoA71ztUIAKt5ElyjO4yVdUctT+/ER9Ku Wl0KDEtpbRswtZJmNa88AteBx+ZUwgcDp0A3kKFArxAxnPZ5C0GjeZrd1MR9cY4j 0hx311ZR2UWi9M51rVBpmy1Cc5HoroNJY6zA/j3o9baeeDfWLLcavo1O5nl7II4n SekmyO+zqhNj+kN26OO2tMwzBstGYUJYSlGLKXZ1KCNWYi9qUlvQ5tmb7tAD6/mH Tu0ZpeI4QbhH3rb33JJYx4xLap+zYsb67/yzAeSw7wiLeJq3NhWVDHGaLbAUR1hF FgRnBV+cxuTEAvehdhwqdd4Gw0CpEdFxENKlZaZIOOPQj+oqcVSXlkxpj00z9ko= =aWvF -----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: - 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) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
300176af03
@ -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% 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] page_fault
|
||||
* 10.00% 10.00% perf libc [.] malloc
|
||||
* 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" },
|
||||
@ -637,6 +640,11 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
|
||||
{ "perf", "run_command" },
|
||||
{ "perf", "main" }, },
|
||||
},
|
||||
{
|
||||
3, { { "[kernel]", "schedule" },
|
||||
{ "perf", "run_command" },
|
||||
{ "perf", "main" }, },
|
||||
},
|
||||
{
|
||||
4, { { "libc", "free" },
|
||||
{ "perf", "cmd_record" },
|
||||
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user