Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d114960c authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo
Browse files

perf callchain: Free callchains when hist entries are deleted



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.

Reported-by: default avatarMarkus Trippelsdorf <markus@trippelsdorf.de>
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Markus Trippelsdorf <markus@trippelsdorf.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20141230053813.GD6081@sejong


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 5ca82710
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -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);
}
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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);
}