* [PATCH v2 1/2] perf callchain: Create an address space per thread
@ 2014-09-29 4:58 Namhyung Kim
2014-09-29 4:58 ` [PATCH v2 2/2] perf callchain: Use global caching provided by libunwind Namhyung Kim
2014-09-29 8:34 ` [PATCH v2 1/2] perf callchain: Create an address space per thread Jiri Olsa
0 siblings, 2 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-09-29 4:58 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
Namhyung Kim, LKML, Jiri Olsa, Arun Sharma, David Ahern,
Frederic Weisbecker, Jean Pihet
The unw_addr_space_t in libunwind represents an address space to be
used for stack unwinding. It doesn't need to be create/destory
everytime to unwind callchain (as in get_entries) and can have a same
lifetime as thread (unless exec called).
So move the address space construction/destruction logic to the thread
lifetime handling functions. This is a preparation to enable caching
in the unwind library.
Note that it saves unw_addr_space_t object using thread__set_priv().
It seems currently only used by perf trace and perf kvm stat commands
which don't use callchain.
Acked-by: Jean Pihet <jean.pihet@linaro.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/thread.c | 6 ++++++
tools/perf/util/unwind-libunwind.c | 30 +++++++++++++++++++++++++-----
tools/perf/util/unwind.h | 17 +++++++++++++++++
3 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index a9df7f2c6dc9..2b7b2d91c016 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,6 +7,7 @@
#include "util.h"
#include "debug.h"
#include "comm.h"
+#include "unwind.h"
int thread__init_map_groups(struct thread *thread, struct machine *machine)
{
@@ -37,6 +38,9 @@ struct thread *thread__new(pid_t pid, pid_t tid)
thread->cpu = -1;
INIT_LIST_HEAD(&thread->comm_list);
+ if (unwind__prepare_access(thread) < 0)
+ goto err_thread;
+
comm_str = malloc(32);
if (!comm_str)
goto err_thread;
@@ -48,6 +52,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
goto err_thread;
list_add(&comm->list, &thread->comm_list);
+
}
return thread;
@@ -69,6 +74,7 @@ void thread__delete(struct thread *thread)
list_del(&comm->list);
comm__free(comm);
}
+ unwind__finish_access(thread);
free(thread);
}
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 92b56db52471..76ec25663c95 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -525,12 +525,9 @@ static unw_accessors_t accessors = {
.get_proc_name = get_proc_name,
};
-static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
- void *arg, int max_stack)
+int unwind__prepare_access(struct thread *thread)
{
unw_addr_space_t addr_space;
- unw_cursor_t c;
- int ret;
addr_space = unw_create_addr_space(&accessors, 0);
if (!addr_space) {
@@ -538,6 +535,30 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
return -ENOMEM;
}
+ thread__set_priv(thread, addr_space);
+
+ return 0;
+}
+
+void unwind__finish_access(struct thread *thread)
+{
+ unw_addr_space_t addr_space;
+
+ addr_space = thread__priv(thread);
+ unw_destroy_addr_space(addr_space);
+}
+
+static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
+ void *arg, int max_stack)
+{
+ unw_addr_space_t addr_space;
+ unw_cursor_t c;
+ int ret;
+
+ addr_space = thread__priv(ui->thread);
+ if (addr_space == NULL)
+ return -1;
+
ret = unw_init_remote(&c, addr_space, ui);
if (ret)
display_error(ret);
@@ -549,7 +570,6 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0;
}
- unw_destroy_addr_space(addr_space);
return ret;
}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index f03061260b4e..4b99c6280c2a 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include "event.h"
#include "symbol.h"
+#include "thread.h"
struct unwind_entry {
struct map *map;
@@ -21,6 +22,15 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
/* libunwind specific */
#ifdef HAVE_LIBUNWIND_SUPPORT
int libunwind__arch_reg_id(int regnum);
+int unwind__prepare_access(struct thread *thread);
+void unwind__finish_access(struct thread *thread);
+#else
+static inline int unwind__prepare_access(struct thread *thread)
+{
+ return 0;
+}
+
+static inline void unwind__finish_access(struct thread *thread) {}
#endif
#else
static inline int
@@ -33,5 +43,12 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
{
return 0;
}
+
+static inline int unwind__prepare_access(struct thread *thread)
+{
+ return 0;
+}
+
+static inline void unwind__finish_access(struct thread *thread) {}
#endif /* HAVE_DWARF_UNWIND_SUPPORT */
#endif /* __UNWIND_H */
--
2.1.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v2 2/2] perf callchain: Use global caching provided by libunwind
2014-09-29 4:58 [PATCH v2 1/2] perf callchain: Create an address space per thread Namhyung Kim
@ 2014-09-29 4:58 ` Namhyung Kim
2014-09-29 8:34 ` [PATCH v2 1/2] perf callchain: Create an address space per thread Jiri Olsa
1 sibling, 0 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-09-29 4:58 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: Peter Zijlstra, Ingo Molnar, Paul Mackerras, Namhyung Kim,
Namhyung Kim, LKML, Jiri Olsa, Arun Sharma, David Ahern,
Frederic Weisbecker, Jean Pihet
The libunwind provides two caching policy which are global and
per-thread. As perf unwinds callchains in a single thread, it'd
sufficient to use global caching.
This speeds up my perf report from 14s to 7s on a ~260MB data file.
Although the output sometimes contains a slight difference (~0.01% in
terms of number of lines printed) on callchains which were not
resolved.
Acked-by: Jean Pihet <jean.pihet@linaro.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/thread.c | 3 +++
tools/perf/util/unwind-libunwind.c | 9 +++++++++
tools/perf/util/unwind.h | 3 +++
3 files changed, 15 insertions(+)
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 2b7b2d91c016..c41411726c7a 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -117,6 +117,9 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
if (!new)
return -ENOMEM;
list_add(&new->list, &thread->comm_list);
+
+ if (exec)
+ unwind__flush_access(thread);
}
thread->comm_set = true;
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 76ec25663c95..6df06f0cd177 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -535,11 +535,20 @@ int unwind__prepare_access(struct thread *thread)
return -ENOMEM;
}
+ unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);
thread__set_priv(thread, addr_space);
return 0;
}
+void unwind__flush_access(struct thread *thread)
+{
+ unw_addr_space_t addr_space;
+
+ addr_space = thread__priv(thread);
+ unw_flush_cache(addr_space, 0, 0);
+}
+
void unwind__finish_access(struct thread *thread)
{
unw_addr_space_t addr_space;
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 4b99c6280c2a..d68f24d4f01b 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -23,6 +23,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
#ifdef HAVE_LIBUNWIND_SUPPORT
int libunwind__arch_reg_id(int regnum);
int unwind__prepare_access(struct thread *thread);
+void unwind__flush_access(struct thread *thread);
void unwind__finish_access(struct thread *thread);
#else
static inline int unwind__prepare_access(struct thread *thread)
@@ -30,6 +31,7 @@ static inline int unwind__prepare_access(struct thread *thread)
return 0;
}
+static inline void unwind__flush_access(struct thread *thread) {}
static inline void unwind__finish_access(struct thread *thread) {}
#endif
#else
@@ -49,6 +51,7 @@ static inline int unwind__prepare_access(struct thread *thread)
return 0;
}
+static inline void unwind__flush_access(struct thread *thread) {}
static inline void unwind__finish_access(struct thread *thread) {}
#endif /* HAVE_DWARF_UNWIND_SUPPORT */
#endif /* __UNWIND_H */
--
2.1.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v2 1/2] perf callchain: Create an address space per thread
2014-09-29 4:58 [PATCH v2 1/2] perf callchain: Create an address space per thread Namhyung Kim
2014-09-29 4:58 ` [PATCH v2 2/2] perf callchain: Use global caching provided by libunwind Namhyung Kim
@ 2014-09-29 8:34 ` Jiri Olsa
2014-09-30 6:11 ` Namhyung Kim
1 sibling, 1 reply; 6+ messages in thread
From: Jiri Olsa @ 2014-09-29 8:34 UTC (permalink / raw)
To: Namhyung Kim
Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
Paul Mackerras, Namhyung Kim, LKML, Arun Sharma, David Ahern,
Frederic Weisbecker, Jean Pihet
On Mon, Sep 29, 2014 at 01:58:11PM +0900, Namhyung Kim wrote:
> The unw_addr_space_t in libunwind represents an address space to be
> used for stack unwinding. It doesn't need to be create/destory
> everytime to unwind callchain (as in get_entries) and can have a same
> lifetime as thread (unless exec called).
>
> So move the address space construction/destruction logic to the thread
> lifetime handling functions. This is a preparation to enable caching
> in the unwind library.
>
> Note that it saves unw_addr_space_t object using thread__set_priv().
> It seems currently only used by perf trace and perf kvm stat commands
> which don't use callchain.
>
> Acked-by: Jean Pihet <jean.pihet@linaro.org>
> Cc: Jiri Olsa <jolsa@redhat.com>
> Cc: Arun Sharma <asharma@fb.com>
> Cc: David Ahern <dsahern@gmail.com>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
> tools/perf/util/thread.c | 6 ++++++
> tools/perf/util/unwind-libunwind.c | 30 +++++++++++++++++++++++++-----
> tools/perf/util/unwind.h | 17 +++++++++++++++++
> 3 files changed, 48 insertions(+), 5 deletions(-)
>
> diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
> index a9df7f2c6dc9..2b7b2d91c016 100644
> --- a/tools/perf/util/thread.c
> +++ b/tools/perf/util/thread.c
> @@ -7,6 +7,7 @@
> #include "util.h"
> #include "debug.h"
> #include "comm.h"
> +#include "unwind.h"
>
> int thread__init_map_groups(struct thread *thread, struct machine *machine)
> {
> @@ -37,6 +38,9 @@ struct thread *thread__new(pid_t pid, pid_t tid)
> thread->cpu = -1;
> INIT_LIST_HEAD(&thread->comm_list);
>
> + if (unwind__prepare_access(thread) < 0)
> + goto err_thread;
So this is something we need to do only for DWARF unwind via libunwind.
Do we want some condition to bypass this in for the rest of the cases?
I think we could check for symbol_conf.use_callchain and for the
PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER sample types in evlist,
something like:
bool has_dwarf_data_for_callchains = symbol_conf.use_callchain && evlist_sample_type_has(evlist, PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER)
;-)
thanks,
jirka
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH v2 1/2] perf callchain: Create an address space per thread
2014-09-29 8:34 ` [PATCH v2 1/2] perf callchain: Create an address space per thread Jiri Olsa
@ 2014-09-30 6:11 ` Namhyung Kim
2014-09-30 7:16 ` Jiri Olsa
2014-09-30 13:17 ` Arnaldo Carvalho de Melo
0 siblings, 2 replies; 6+ messages in thread
From: Namhyung Kim @ 2014-09-30 6:11 UTC (permalink / raw)
To: Jiri Olsa
Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
Paul Mackerras, Namhyung Kim, LKML, Arun Sharma, David Ahern,
Frederic Weisbecker, Jean Pihet
Hi Jiri,
On Mon, 29 Sep 2014 10:34:52 +0200, Jiri Olsa wrote:
> On Mon, Sep 29, 2014 at 01:58:11PM +0900, Namhyung Kim wrote:
>> @@ -37,6 +38,9 @@ struct thread *thread__new(pid_t pid, pid_t tid)
>> thread->cpu = -1;
>> INIT_LIST_HEAD(&thread->comm_list);
>>
>> + if (unwind__prepare_access(thread) < 0)
>> + goto err_thread;
>
> So this is something we need to do only for DWARF unwind via libunwind.
> Do we want some condition to bypass this in for the rest of the cases?
Ah, you're right, we need to check that before doing this.
>
> I think we could check for symbol_conf.use_callchain and for the
> PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER sample types in evlist,
> something like:
>
> bool has_dwarf_data_for_callchains = symbol_conf.use_callchain && evlist_sample_type_has(evlist, PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER)
Hmm.. it seems that it's hard to get the evlist at this point. Maybe we
need to add a field in the symbol_conf or a global variable.. :/
Thanks,
Namhyung
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] perf callchain: Create an address space per thread
2014-09-30 6:11 ` Namhyung Kim
@ 2014-09-30 7:16 ` Jiri Olsa
2014-09-30 13:17 ` Arnaldo Carvalho de Melo
1 sibling, 0 replies; 6+ messages in thread
From: Jiri Olsa @ 2014-09-30 7:16 UTC (permalink / raw)
To: Namhyung Kim
Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, Ingo Molnar,
Paul Mackerras, Namhyung Kim, LKML, Arun Sharma, David Ahern,
Frederic Weisbecker, Jean Pihet
On Tue, Sep 30, 2014 at 03:11:21PM +0900, Namhyung Kim wrote:
> Hi Jiri,
>
> On Mon, 29 Sep 2014 10:34:52 +0200, Jiri Olsa wrote:
> > On Mon, Sep 29, 2014 at 01:58:11PM +0900, Namhyung Kim wrote:
> >> @@ -37,6 +38,9 @@ struct thread *thread__new(pid_t pid, pid_t tid)
> >> thread->cpu = -1;
> >> INIT_LIST_HEAD(&thread->comm_list);
> >>
> >> + if (unwind__prepare_access(thread) < 0)
> >> + goto err_thread;
> >
> > So this is something we need to do only for DWARF unwind via libunwind.
> > Do we want some condition to bypass this in for the rest of the cases?
>
> Ah, you're right, we need to check that before doing this.
>
>
> >
> > I think we could check for symbol_conf.use_callchain and for the
> > PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER sample types in evlist,
> > something like:
> >
> > bool has_dwarf_data_for_callchains = symbol_conf.use_callchain && evlist_sample_type_has(evlist, PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER)
>
> Hmm.. it seems that it's hard to get the evlist at this point. Maybe we
> need to add a field in the symbol_conf or a global variable.. :/
yea, symbol_conf seems ok
jirka
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] perf callchain: Create an address space per thread
2014-09-30 6:11 ` Namhyung Kim
2014-09-30 7:16 ` Jiri Olsa
@ 2014-09-30 13:17 ` Arnaldo Carvalho de Melo
1 sibling, 0 replies; 6+ messages in thread
From: Arnaldo Carvalho de Melo @ 2014-09-30 13:17 UTC (permalink / raw)
To: Namhyung Kim
Cc: Jiri Olsa, Peter Zijlstra, Ingo Molnar, Paul Mackerras,
Namhyung Kim, LKML, Arun Sharma, David Ahern, Frederic Weisbecker,
Jean Pihet
Em Tue, Sep 30, 2014 at 03:11:21PM +0900, Namhyung Kim escreveu:
>
> On Mon, 29 Sep 2014 10:34:52 +0200, Jiri Olsa wrote:
> > On Mon, Sep 29, 2014 at 01:58:11PM +0900, Namhyung Kim wrote:
> >> @@ -37,6 +38,9 @@ struct thread *thread__new(pid_t pid, pid_t tid)
> >> thread->cpu = -1;
> >> INIT_LIST_HEAD(&thread->comm_list);
> >> + if (unwind__prepare_access(thread) < 0)
> >> + goto err_thread;
> > So this is something we need to do only for DWARF unwind via libunwind.
> > Do we want some condition to bypass this in for the rest of the cases?
> Ah, you're right, we need to check that before doing this.
> > I think we could check for symbol_conf.use_callchain and for the
> > PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER sample types in evlist,
> > something like:
> > bool has_dwarf_data_for_callchains = symbol_conf.use_callchain && evlist_sample_type_has(evlist, PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER)
> Hmm.. it seems that it's hard to get the evlist at this point. Maybe we
> need to add a field in the symbol_conf or a global variable.. :/
Please don't export evlist in a global way, just set some flag on
symbol_conf.
At some point we need to ditch even symbol_conf :-\
- Arnaldo
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-09-30 13:17 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-29 4:58 [PATCH v2 1/2] perf callchain: Create an address space per thread Namhyung Kim
2014-09-29 4:58 ` [PATCH v2 2/2] perf callchain: Use global caching provided by libunwind Namhyung Kim
2014-09-29 8:34 ` [PATCH v2 1/2] perf callchain: Create an address space per thread Jiri Olsa
2014-09-30 6:11 ` Namhyung Kim
2014-09-30 7:16 ` Jiri Olsa
2014-09-30 13:17 ` Arnaldo Carvalho de Melo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox