2009-06-02 14:37:05 -07:00
|
|
|
/*
|
|
|
|
* builtin-report.c
|
|
|
|
*
|
|
|
|
* Builtin report command: Analyze the perf.data input file,
|
|
|
|
* look up and read DSOs and symbol information and display
|
|
|
|
* a histogram of results, along various sorting keys.
|
|
|
|
*/
|
2009-05-27 00:10:38 -07:00
|
|
|
#include "builtin.h"
|
2009-05-26 00:17:18 -07:00
|
|
|
|
2009-06-02 14:37:05 -07:00
|
|
|
#include "util/util.h"
|
|
|
|
|
2009-06-04 06:19:47 -07:00
|
|
|
#include "util/color.h"
|
2009-07-01 10:46:08 -07:00
|
|
|
#include <linux/list.h>
|
2009-05-27 00:50:13 -07:00
|
|
|
#include "util/cache.h"
|
2009-07-01 08:28:37 -07:00
|
|
|
#include <linux/rbtree.h>
|
2009-05-28 10:55:04 -07:00
|
|
|
#include "util/symbol.h"
|
2009-06-01 13:50:19 -07:00
|
|
|
#include "util/string.h"
|
2009-06-26 07:28:01 -07:00
|
|
|
#include "util/callchain.h"
|
2009-06-30 15:01:20 -07:00
|
|
|
#include "util/strlist.h"
|
2009-08-07 04:55:24 -07:00
|
|
|
#include "util/values.h"
|
2009-05-18 08:45:42 -07:00
|
|
|
|
2009-05-26 00:17:18 -07:00
|
|
|
#include "perf.h"
|
2009-08-16 13:05:48 -07:00
|
|
|
#include "util/debug.h"
|
2009-06-25 08:05:54 -07:00
|
|
|
#include "util/header.h"
|
2009-12-11 16:24:02 -07:00
|
|
|
#include "util/session.h"
|
2009-05-26 00:17:18 -07:00
|
|
|
|
|
|
|
#include "util/parse-options.h"
|
|
|
|
#include "util/parse-events.h"
|
|
|
|
|
2009-10-07 03:47:31 -07:00
|
|
|
#include "util/data_map.h"
|
2009-08-14 03:21:53 -07:00
|
|
|
#include "util/thread.h"
|
2009-09-24 09:02:49 -07:00
|
|
|
#include "util/sort.h"
|
2009-09-28 06:32:55 -07:00
|
|
|
#include "util/hist.h"
|
2009-08-14 03:21:53 -07:00
|
|
|
|
2009-05-27 00:33:18 -07:00
|
|
|
static char const *input_name = "perf.data";
|
2009-06-04 05:13:04 -07:00
|
|
|
|
2009-07-10 18:47:28 -07:00
|
|
|
static char *dso_list_str, *comm_list_str, *sym_list_str,
|
|
|
|
*col_width_list_str;
|
2009-06-30 15:01:22 -07:00
|
|
|
static struct strlist *dso_list, *comm_list, *sym_list;
|
2009-06-04 05:13:04 -07:00
|
|
|
|
2009-08-19 02:18:26 -07:00
|
|
|
static int force;
|
2009-05-18 08:45:42 -07:00
|
|
|
|
2009-05-29 09:48:59 -07:00
|
|
|
static int full_paths;
|
2009-07-11 08:18:37 -07:00
|
|
|
static int show_nr_samples;
|
2009-05-26 09:48:58 -07:00
|
|
|
|
2009-08-07 04:55:24 -07:00
|
|
|
static int show_threads;
|
|
|
|
static struct perf_read_values show_threads_values;
|
|
|
|
|
2009-08-10 06:26:32 -07:00
|
|
|
static char default_pretty_printing_style[] = "normal";
|
|
|
|
static char *pretty_printing_style = default_pretty_printing_style;
|
|
|
|
|
2009-06-18 05:32:19 -07:00
|
|
|
static int exclude_other = 1;
|
2009-07-04 22:39:18 -07:00
|
|
|
|
2009-07-04 22:39:21 -07:00
|
|
|
static char callchain_default_opt[] = "fractal,0.5";
|
|
|
|
|
2009-12-11 16:24:02 -07:00
|
|
|
static struct perf_session *session;
|
2009-08-16 11:56:37 -07:00
|
|
|
|
2009-06-25 02:27:12 -07:00
|
|
|
static u64 sample_type;
|
|
|
|
|
2009-11-24 07:05:15 -07:00
|
|
|
struct symbol_conf symbol_conf;
|
|
|
|
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
|
|
|
|
static size_t
|
|
|
|
callchain__fprintf_left_margin(FILE *fp, int left_margin)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = fprintf(fp, " ");
|
|
|
|
|
|
|
|
for (i = 0; i < left_margin; i++)
|
|
|
|
ret += fprintf(fp, " ");
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
|
|
|
|
int left_margin)
|
2009-07-02 08:58:21 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
size_t ret = 0;
|
|
|
|
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
ret += callchain__fprintf_left_margin(fp, left_margin);
|
2009-07-02 08:58:21 -07:00
|
|
|
|
|
|
|
for (i = 0; i < depth; i++)
|
|
|
|
if (depth_mask & (1 << i))
|
|
|
|
ret += fprintf(fp, "| ");
|
|
|
|
else
|
|
|
|
ret += fprintf(fp, " ");
|
|
|
|
|
|
|
|
ret += fprintf(fp, "\n");
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2009-06-26 07:28:01 -07:00
|
|
|
static size_t
|
2009-07-02 08:58:21 -07:00
|
|
|
ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, int depth,
|
|
|
|
int depth_mask, int count, u64 total_samples,
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
int hits, int left_margin)
|
2009-07-02 08:58:21 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
size_t ret = 0;
|
|
|
|
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
ret += callchain__fprintf_left_margin(fp, left_margin);
|
2009-07-02 08:58:21 -07:00
|
|
|
for (i = 0; i < depth; i++) {
|
|
|
|
if (depth_mask & (1 << i))
|
|
|
|
ret += fprintf(fp, "|");
|
|
|
|
else
|
|
|
|
ret += fprintf(fp, " ");
|
|
|
|
if (!count && i == depth - 1) {
|
|
|
|
double percent;
|
|
|
|
|
|
|
|
percent = hits * 100.0 / total_samples;
|
2009-07-02 11:14:35 -07:00
|
|
|
ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
|
2009-07-02 08:58:21 -07:00
|
|
|
} else
|
|
|
|
ret += fprintf(fp, "%s", " ");
|
|
|
|
}
|
|
|
|
if (chain->sym)
|
|
|
|
ret += fprintf(fp, "%s\n", chain->sym->name);
|
|
|
|
else
|
|
|
|
ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-08-07 17:16:25 -07:00
|
|
|
static struct symbol *rem_sq_bracket;
|
|
|
|
static struct callchain_list rem_hits;
|
|
|
|
|
|
|
|
static void init_rem_hits(void)
|
|
|
|
{
|
|
|
|
rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
|
|
|
|
if (!rem_sq_bracket) {
|
|
|
|
fprintf(stderr, "Not enough memory to display remaining hits\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(rem_sq_bracket->name, "[...]");
|
|
|
|
rem_hits.sym = rem_sq_bracket;
|
|
|
|
}
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
static size_t
|
2009-10-22 14:23:22 -07:00
|
|
|
__callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
u64 total_samples, int depth, int depth_mask,
|
|
|
|
int left_margin)
|
2009-07-02 08:58:21 -07:00
|
|
|
{
|
|
|
|
struct rb_node *node, *next;
|
|
|
|
struct callchain_node *child;
|
|
|
|
struct callchain_list *chain;
|
|
|
|
int new_depth_mask = depth_mask;
|
2009-07-04 22:39:21 -07:00
|
|
|
u64 new_total;
|
2009-08-07 17:16:25 -07:00
|
|
|
u64 remaining;
|
2009-07-02 08:58:21 -07:00
|
|
|
size_t ret = 0;
|
|
|
|
int i;
|
|
|
|
|
2009-07-04 22:39:21 -07:00
|
|
|
if (callchain_param.mode == CHAIN_GRAPH_REL)
|
2009-08-06 22:11:05 -07:00
|
|
|
new_total = self->children_hit;
|
2009-07-04 22:39:21 -07:00
|
|
|
else
|
|
|
|
new_total = total_samples;
|
|
|
|
|
2009-08-07 17:16:25 -07:00
|
|
|
remaining = new_total;
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
node = rb_first(&self->rb_root);
|
|
|
|
while (node) {
|
2009-08-07 17:16:25 -07:00
|
|
|
u64 cumul;
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
child = rb_entry(node, struct callchain_node, rb_node);
|
2009-08-07 17:16:25 -07:00
|
|
|
cumul = cumul_hits(child);
|
|
|
|
remaining -= cumul;
|
2009-07-02 08:58:21 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The depth mask manages the output of pipes that show
|
|
|
|
* the depth. We don't want to keep the pipes of the current
|
2009-08-07 17:16:25 -07:00
|
|
|
* level for the last child of this depth.
|
|
|
|
* Except if we have remaining filtered hits. They will
|
|
|
|
* supersede the last child
|
2009-07-02 08:58:21 -07:00
|
|
|
*/
|
|
|
|
next = rb_next(node);
|
2009-08-07 17:16:25 -07:00
|
|
|
if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
|
2009-07-02 08:58:21 -07:00
|
|
|
new_depth_mask &= ~(1 << (depth - 1));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* But we keep the older depth mask for the line seperator
|
|
|
|
* to keep the level link until we reach the last child
|
|
|
|
*/
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
|
|
|
|
left_margin);
|
2009-07-02 08:58:21 -07:00
|
|
|
i = 0;
|
|
|
|
list_for_each_entry(chain, &child->val, list) {
|
|
|
|
if (chain->ip >= PERF_CONTEXT_MAX)
|
|
|
|
continue;
|
|
|
|
ret += ipchain__fprintf_graph(fp, chain, depth,
|
|
|
|
new_depth_mask, i++,
|
2009-07-04 22:39:21 -07:00
|
|
|
new_total,
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
cumul,
|
|
|
|
left_margin);
|
2009-07-02 08:58:21 -07:00
|
|
|
}
|
2009-10-22 14:23:22 -07:00
|
|
|
ret += __callchain__fprintf_graph(fp, child, new_total,
|
|
|
|
depth + 1,
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
new_depth_mask | (1 << depth),
|
|
|
|
left_margin);
|
2009-07-02 08:58:21 -07:00
|
|
|
node = next;
|
|
|
|
}
|
|
|
|
|
2009-08-07 17:16:25 -07:00
|
|
|
if (callchain_param.mode == CHAIN_GRAPH_REL &&
|
|
|
|
remaining && remaining != new_total) {
|
|
|
|
|
|
|
|
if (!rem_sq_bracket)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
new_depth_mask &= ~(1 << (depth - 1));
|
|
|
|
|
|
|
|
ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
|
|
|
|
new_depth_mask, 0, new_total,
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
remaining, left_margin);
|
2009-08-07 17:16:25 -07:00
|
|
|
}
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
|
2009-10-22 14:23:22 -07:00
|
|
|
static size_t
|
|
|
|
callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
u64 total_samples, int left_margin)
|
2009-10-22 14:23:22 -07:00
|
|
|
{
|
|
|
|
struct callchain_list *chain;
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
bool printed = false;
|
2009-10-22 14:23:22 -07:00
|
|
|
int i = 0;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
list_for_each_entry(chain, &self->val, list) {
|
|
|
|
if (chain->ip >= PERF_CONTEXT_MAX)
|
|
|
|
continue;
|
|
|
|
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
if (!i++ && sort__first_dimension == SORT_SYM)
|
2009-10-22 14:23:22 -07:00
|
|
|
continue;
|
|
|
|
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
if (!printed) {
|
|
|
|
ret += callchain__fprintf_left_margin(fp, left_margin);
|
|
|
|
ret += fprintf(fp, "|\n");
|
|
|
|
ret += callchain__fprintf_left_margin(fp, left_margin);
|
|
|
|
ret += fprintf(fp, "---");
|
|
|
|
|
|
|
|
left_margin += 3;
|
|
|
|
printed = true;
|
|
|
|
} else
|
|
|
|
ret += callchain__fprintf_left_margin(fp, left_margin);
|
|
|
|
|
2009-10-22 14:23:22 -07:00
|
|
|
if (chain->sym)
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
ret += fprintf(fp, " %s\n", chain->sym->name);
|
2009-10-22 14:23:22 -07:00
|
|
|
else
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
|
2009-10-22 14:23:22 -07:00
|
|
|
}
|
|
|
|
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
|
2009-10-22 14:23:22 -07:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
static size_t
|
|
|
|
callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
|
|
|
|
u64 total_samples)
|
2009-06-26 07:28:01 -07:00
|
|
|
{
|
|
|
|
struct callchain_list *chain;
|
|
|
|
size_t ret = 0;
|
|
|
|
|
|
|
|
if (!self)
|
|
|
|
return 0;
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
ret += callchain__fprintf_flat(fp, self->parent, total_samples);
|
2009-06-26 07:28:01 -07:00
|
|
|
|
|
|
|
|
2009-06-30 20:35:14 -07:00
|
|
|
list_for_each_entry(chain, &self->val, list) {
|
|
|
|
if (chain->ip >= PERF_CONTEXT_MAX)
|
|
|
|
continue;
|
|
|
|
if (chain->sym)
|
|
|
|
ret += fprintf(fp, " %s\n", chain->sym->name);
|
|
|
|
else
|
|
|
|
ret += fprintf(fp, " %p\n",
|
2009-07-01 03:37:06 -07:00
|
|
|
(void *)(long)chain->ip);
|
2009-06-30 20:35:14 -07:00
|
|
|
}
|
2009-06-26 07:28:01 -07:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t
|
|
|
|
hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
u64 total_samples, int left_margin)
|
2009-06-26 07:28:01 -07:00
|
|
|
{
|
|
|
|
struct rb_node *rb_node;
|
|
|
|
struct callchain_node *chain;
|
|
|
|
size_t ret = 0;
|
|
|
|
|
|
|
|
rb_node = rb_first(&self->sorted_chain);
|
|
|
|
while (rb_node) {
|
|
|
|
double percent;
|
|
|
|
|
|
|
|
chain = rb_entry(rb_node, struct callchain_node, rb_node);
|
|
|
|
percent = chain->hit * 100.0 / total_samples;
|
2009-07-04 22:39:21 -07:00
|
|
|
switch (callchain_param.mode) {
|
|
|
|
case CHAIN_FLAT:
|
2009-07-02 11:14:35 -07:00
|
|
|
ret += percent_color_fprintf(fp, " %6.2f%%\n",
|
|
|
|
percent);
|
2009-07-02 08:58:21 -07:00
|
|
|
ret += callchain__fprintf_flat(fp, chain, total_samples);
|
2009-07-04 22:39:21 -07:00
|
|
|
break;
|
|
|
|
case CHAIN_GRAPH_ABS: /* Falldown */
|
|
|
|
case CHAIN_GRAPH_REL:
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
ret += callchain__fprintf_graph(fp, chain, total_samples,
|
|
|
|
left_margin);
|
2009-08-15 03:26:57 -07:00
|
|
|
case CHAIN_NONE:
|
2009-07-04 22:39:21 -07:00
|
|
|
default:
|
|
|
|
break;
|
2009-07-02 08:58:21 -07:00
|
|
|
}
|
2009-06-26 07:28:01 -07:00
|
|
|
ret += fprintf(fp, "\n");
|
|
|
|
rb_node = rb_next(rb_node);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-05-27 11:20:25 -07:00
|
|
|
static size_t
|
perf_counter tools: Define and use our own u64, s64 etc. definitions
On 64-bit powerpc, __u64 is defined to be unsigned long rather than
unsigned long long. This causes compiler warnings every time we
print a __u64 value with %Lx.
Rather than changing __u64, we define our own u64 to be unsigned long
long on all architectures, and similarly s64 as signed long long.
For consistency we also define u32, s32, u16, s16, u8 and s8. These
definitions are put in a new header, types.h, because these definitions
are needed in util/string.h and util/symbol.h.
The main change here is the mechanical change of __[us]{64,32,16,8}
to remove the "__". The other changes are:
* Create types.h
* Include types.h in perf.h, util/string.h and util/symbol.h
* Add types.h to the LIB_H definition in Makefile
* Added (u64) casts in process_overflow_event() and print_sym_table()
to kill two remaining warnings.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: benh@kernel.crashing.org
LKML-Reference: <19003.33494.495844.956580@cargo.ozlabs.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-06-19 05:21:42 -07:00
|
|
|
hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
|
2009-05-27 11:20:25 -07:00
|
|
|
{
|
|
|
|
struct sort_entry *se;
|
|
|
|
size_t ret;
|
|
|
|
|
2009-06-18 05:32:19 -07:00
|
|
|
if (exclude_other && !self->parent)
|
|
|
|
return 0;
|
|
|
|
|
2009-07-02 11:14:34 -07:00
|
|
|
if (total_samples)
|
2009-07-10 18:47:28 -07:00
|
|
|
ret = percent_color_fprintf(fp,
|
|
|
|
field_sep ? "%.2f" : " %6.2f%%",
|
|
|
|
(self->count * 100.0) / total_samples);
|
2009-07-02 11:14:34 -07:00
|
|
|
else
|
2009-07-10 18:47:28 -07:00
|
|
|
ret = fprintf(fp, field_sep ? "%lld" : "%12lld ", self->count);
|
2009-05-27 11:20:25 -07:00
|
|
|
|
2009-07-11 08:18:37 -07:00
|
|
|
if (show_nr_samples) {
|
|
|
|
if (field_sep)
|
|
|
|
fprintf(fp, "%c%lld", *field_sep, self->count);
|
|
|
|
else
|
|
|
|
fprintf(fp, "%11lld", self->count);
|
|
|
|
}
|
2009-05-27 11:20:25 -07:00
|
|
|
|
2009-06-04 06:16:56 -07:00
|
|
|
list_for_each_entry(se, &hist_entry__sort_list, list) {
|
2009-07-11 08:18:35 -07:00
|
|
|
if (se->elide)
|
2009-06-18 05:32:19 -07:00
|
|
|
continue;
|
|
|
|
|
2009-07-10 18:47:28 -07:00
|
|
|
fprintf(fp, "%s", field_sep ?: " ");
|
|
|
|
ret += se->print(fp, self, se->width ? *se->width : 0);
|
2009-06-04 06:16:56 -07:00
|
|
|
}
|
2009-05-27 11:20:25 -07:00
|
|
|
|
|
|
|
ret += fprintf(fp, "\n");
|
|
|
|
|
perf tools: Bind callchains to the first sort dimension column
Currently, the callchains are displayed using a constant left
margin. So depending on the current sort dimension
configuration, callchains may appear to be well attached to the
first sort dimension column field which is mostly the case,
except when the first dimension of sorting is done by comm,
because these are right aligned.
This patch binds the callchain to the first letter in the first
column, whatever type of column it is (dso, comm, symbol).
Before:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
After:
0.80% perf [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
| | __fsnotify_parent
Also, for clarity, we don't put anymore the callchain as is but:
- If we have a top level ancestor in the callchain, start it
with a first ascii hook.
Before:
0.80% perf [kernel] [k] __lock_acquire
__lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
After:
0.80% perf [kernel] [k] __lock_acquire
|
--- __lock_acquire
lock_acquire
|
|--58.33%-- _spin_lock
| |
| |--28.57%-- inotify_should_send_event
| | fsnotify
[..] [..]
- Otherwise, if we have several top level ancestors, then
display these like we did before:
1.69% Xorg
|
|--21.21%-- vread_hpet
| 0x7fffd85b46fc
| 0x7fffd85b494d
| 0x7f4fafb4e54d
|
|--15.15%-- exaOffscreenAlloc
|
|--9.09%-- I830WaitLpRing
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Anton Blanchard <anton@samba.org>
LKML-Reference: <1256246604-17156-2-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-10-22 14:23:23 -07:00
|
|
|
if (callchain) {
|
|
|
|
int left_margin = 0;
|
|
|
|
|
|
|
|
if (sort__first_dimension == SORT_COMM) {
|
|
|
|
se = list_first_entry(&hist_entry__sort_list, typeof(*se),
|
|
|
|
list);
|
|
|
|
left_margin = se->width ? *se->width : 0;
|
|
|
|
left_margin -= thread__comm_len(self->thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
hist_entry_callchain__fprintf(fp, self, total_samples,
|
|
|
|
left_margin);
|
|
|
|
}
|
2009-06-26 07:28:01 -07:00
|
|
|
|
2009-05-27 11:20:25 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-06-17 06:51:44 -07:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2009-07-10 18:47:28 -07:00
|
|
|
static void dso__calc_col_width(struct dso *self)
|
|
|
|
{
|
|
|
|
if (!col_width_list_str && !field_sep &&
|
|
|
|
(!dso_list || strlist__has_entry(dso_list, self->name))) {
|
|
|
|
unsigned int slen = strlen(self->name);
|
|
|
|
if (slen > dsos__col_width)
|
|
|
|
dsos__col_width = slen;
|
|
|
|
}
|
|
|
|
|
|
|
|
self->slen_calculated = 1;
|
|
|
|
}
|
|
|
|
|
2009-08-30 21:45:18 -07:00
|
|
|
static void thread__comm_adjust(struct thread *self)
|
2009-08-18 07:03:46 -07:00
|
|
|
{
|
2009-08-30 21:45:18 -07:00
|
|
|
char *comm = self->comm;
|
2009-08-18 07:03:46 -07:00
|
|
|
|
|
|
|
if (!col_width_list_str && !field_sep &&
|
|
|
|
(!comm_list || strlist__has_entry(comm_list, comm))) {
|
|
|
|
unsigned int slen = strlen(comm);
|
|
|
|
|
|
|
|
if (slen > comms__col_width) {
|
|
|
|
comms__col_width = slen;
|
|
|
|
threads__col_width = slen + 6;
|
|
|
|
}
|
|
|
|
}
|
2009-08-30 21:45:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int thread__set_comm_adjust(struct thread *self, const char *comm)
|
|
|
|
{
|
|
|
|
int ret = thread__set_comm(self, comm);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
thread__comm_adjust(self);
|
2009-08-18 07:03:46 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-06-18 13:20:45 -07:00
|
|
|
static int call__match(struct symbol *sym)
|
2009-06-17 06:51:44 -07:00
|
|
|
{
|
2009-06-17 22:01:03 -07:00
|
|
|
if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
|
2009-06-18 13:20:45 -07:00
|
|
|
return 1;
|
2009-06-17 06:51:44 -07:00
|
|
|
|
2009-06-18 13:20:45 -07:00
|
|
|
return 0;
|
2009-06-17 06:51:44 -07:00
|
|
|
}
|
|
|
|
|
2009-11-22 09:59:22 -07:00
|
|
|
static struct symbol **resolve_callchain(struct thread *thread,
|
2009-10-03 06:42:45 -07:00
|
|
|
struct ip_callchain *chain,
|
|
|
|
struct symbol **parent)
|
2009-06-30 20:35:14 -07:00
|
|
|
{
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
u8 cpumode = PERF_RECORD_MISC_USER;
|
2009-07-03 04:17:28 -07:00
|
|
|
struct symbol **syms = NULL;
|
2009-07-01 03:37:06 -07:00
|
|
|
unsigned int i;
|
2009-06-30 20:35:14 -07:00
|
|
|
|
|
|
|
if (callchain) {
|
|
|
|
syms = calloc(chain->nr, sizeof(*syms));
|
|
|
|
if (!syms) {
|
|
|
|
fprintf(stderr, "Can't allocate memory for symbols\n");
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < chain->nr; i++) {
|
|
|
|
u64 ip = chain->ips[i];
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
struct addr_location al;
|
2009-06-30 20:35:14 -07:00
|
|
|
|
|
|
|
if (ip >= PERF_CONTEXT_MAX) {
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
switch (ip) {
|
|
|
|
case PERF_CONTEXT_HV:
|
|
|
|
cpumode = PERF_RECORD_MISC_HYPERVISOR; break;
|
|
|
|
case PERF_CONTEXT_KERNEL:
|
|
|
|
cpumode = PERF_RECORD_MISC_KERNEL; break;
|
|
|
|
case PERF_CONTEXT_USER:
|
|
|
|
cpumode = PERF_RECORD_MISC_USER; break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2009-06-30 20:35:14 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
|
|
|
|
ip, &al, NULL);
|
|
|
|
if (al.sym != NULL) {
|
|
|
|
if (sort__has_parent && !*parent &&
|
|
|
|
call__match(al.sym))
|
|
|
|
*parent = al.sym;
|
2009-06-30 20:35:14 -07:00
|
|
|
if (!callchain)
|
|
|
|
break;
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
syms[i] = al.sym;
|
2009-06-30 20:35:14 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return syms;
|
|
|
|
}
|
|
|
|
|
2009-05-27 11:20:25 -07:00
|
|
|
/*
|
|
|
|
* collect histogram counts
|
|
|
|
*/
|
|
|
|
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
static int hist_entry__add(struct addr_location *al,
|
|
|
|
struct ip_callchain *chain, u64 count)
|
2009-05-18 08:45:42 -07:00
|
|
|
{
|
2009-10-03 06:42:45 -07:00
|
|
|
struct symbol **syms = NULL, *parent = NULL;
|
|
|
|
bool hit;
|
2009-05-27 11:20:24 -07:00
|
|
|
struct hist_entry *he;
|
|
|
|
|
2009-06-30 20:35:14 -07:00
|
|
|
if ((sort__has_parent || callchain) && chain)
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
syms = resolve_callchain(al->thread, chain, &parent);
|
2009-05-27 11:20:24 -07:00
|
|
|
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
he = __hist_entry__add(al, parent, count, &hit);
|
2009-10-03 06:42:45 -07:00
|
|
|
if (he == NULL)
|
|
|
|
return -ENOMEM;
|
2009-05-27 11:20:24 -07:00
|
|
|
|
2009-10-03 06:42:45 -07:00
|
|
|
if (hit)
|
|
|
|
he->count += count;
|
2009-05-27 11:20:24 -07:00
|
|
|
|
2009-06-26 07:28:01 -07:00
|
|
|
if (callchain) {
|
2009-10-03 06:42:45 -07:00
|
|
|
if (!hit)
|
|
|
|
callchain_init(&he->callchain);
|
2009-06-30 20:35:14 -07:00
|
|
|
append_chain(&he->callchain, chain, syms);
|
|
|
|
free(syms);
|
2009-06-26 07:28:01 -07:00
|
|
|
}
|
2009-05-27 11:20:24 -07:00
|
|
|
|
|
|
|
return 0;
|
2009-05-18 08:45:42 -07:00
|
|
|
}
|
|
|
|
|
perf_counter tools: Define and use our own u64, s64 etc. definitions
On 64-bit powerpc, __u64 is defined to be unsigned long rather than
unsigned long long. This causes compiler warnings every time we
print a __u64 value with %Lx.
Rather than changing __u64, we define our own u64 to be unsigned long
long on all architectures, and similarly s64 as signed long long.
For consistency we also define u32, s32, u16, s16, u8 and s8. These
definitions are put in a new header, types.h, because these definitions
are needed in util/string.h and util/symbol.h.
The main change here is the mechanical change of __[us]{64,32,16,8}
to remove the "__". The other changes are:
* Create types.h
* Include types.h in perf.h, util/string.h and util/symbol.h
* Add types.h to the LIB_H definition in Makefile
* Added (u64) casts in process_overflow_event() and print_sym_table()
to kill two remaining warnings.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: benh@kernel.crashing.org
LKML-Reference: <19003.33494.495844.956580@cargo.ozlabs.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-06-19 05:21:42 -07:00
|
|
|
static size_t output__fprintf(FILE *fp, u64 total_samples)
|
2009-05-26 12:19:04 -07:00
|
|
|
{
|
2009-05-27 11:20:24 -07:00
|
|
|
struct hist_entry *pos;
|
2009-05-27 12:36:22 -07:00
|
|
|
struct sort_entry *se;
|
2009-05-26 12:19:04 -07:00
|
|
|
struct rb_node *nd;
|
|
|
|
size_t ret = 0;
|
2009-07-10 18:47:28 -07:00
|
|
|
unsigned int width;
|
|
|
|
char *col_width = col_width_list_str;
|
2009-08-10 06:26:32 -07:00
|
|
|
int raw_printing_style;
|
|
|
|
|
|
|
|
raw_printing_style = !strcmp(pretty_printing_style, "raw");
|
2009-05-26 12:19:04 -07:00
|
|
|
|
2009-08-07 17:16:25 -07:00
|
|
|
init_rem_hits();
|
|
|
|
|
2009-07-11 08:18:35 -07:00
|
|
|
fprintf(fp, "# Samples: %Ld\n", (u64)total_samples);
|
2009-05-28 02:08:33 -07:00
|
|
|
fprintf(fp, "#\n");
|
|
|
|
|
|
|
|
fprintf(fp, "# Overhead");
|
2009-07-11 08:18:37 -07:00
|
|
|
if (show_nr_samples) {
|
|
|
|
if (field_sep)
|
|
|
|
fprintf(fp, "%cSamples", *field_sep);
|
|
|
|
else
|
|
|
|
fputs(" Samples ", fp);
|
|
|
|
}
|
2009-06-18 05:32:19 -07:00
|
|
|
list_for_each_entry(se, &hist_entry__sort_list, list) {
|
2009-07-11 08:18:35 -07:00
|
|
|
if (se->elide)
|
2009-06-18 05:32:19 -07:00
|
|
|
continue;
|
2009-07-10 18:47:28 -07:00
|
|
|
if (field_sep) {
|
|
|
|
fprintf(fp, "%c%s", *field_sep, se->header);
|
2009-06-18 05:32:19 -07:00
|
|
|
continue;
|
2009-07-10 18:47:28 -07:00
|
|
|
}
|
|
|
|
width = strlen(se->header);
|
|
|
|
if (se->width) {
|
|
|
|
if (col_width_list_str) {
|
|
|
|
if (col_width) {
|
|
|
|
*se->width = atoi(col_width);
|
|
|
|
col_width = strchr(col_width, ',');
|
|
|
|
if (col_width)
|
|
|
|
++col_width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
width = *se->width = max(*se->width, width);
|
|
|
|
}
|
|
|
|
fprintf(fp, " %*s", width, se->header);
|
2009-06-18 05:32:19 -07:00
|
|
|
}
|
2009-05-28 02:08:33 -07:00
|
|
|
fprintf(fp, "\n");
|
|
|
|
|
2009-07-10 18:47:28 -07:00
|
|
|
if (field_sep)
|
|
|
|
goto print_entries;
|
|
|
|
|
2009-05-28 02:08:33 -07:00
|
|
|
fprintf(fp, "# ........");
|
2009-07-11 08:18:37 -07:00
|
|
|
if (show_nr_samples)
|
|
|
|
fprintf(fp, " ..........");
|
2009-05-27 12:36:22 -07:00
|
|
|
list_for_each_entry(se, &hist_entry__sort_list, list) {
|
2009-07-01 03:37:06 -07:00
|
|
|
unsigned int i;
|
2009-05-28 02:08:33 -07:00
|
|
|
|
2009-07-11 08:18:35 -07:00
|
|
|
if (se->elide)
|
2009-06-18 05:32:19 -07:00
|
|
|
continue;
|
|
|
|
|
2009-06-02 06:34:25 -07:00
|
|
|
fprintf(fp, " ");
|
2009-07-10 18:47:28 -07:00
|
|
|
if (se->width)
|
|
|
|
width = *se->width;
|
|
|
|
else
|
|
|
|
width = strlen(se->header);
|
|
|
|
for (i = 0; i < width; i++)
|
2009-05-28 02:08:33 -07:00
|
|
|
fprintf(fp, ".");
|
2009-05-27 12:36:22 -07:00
|
|
|
}
|
2009-05-28 02:08:33 -07:00
|
|
|
fprintf(fp, "\n");
|
|
|
|
|
|
|
|
fprintf(fp, "#\n");
|
2009-05-27 12:36:22 -07:00
|
|
|
|
2009-07-10 18:47:28 -07:00
|
|
|
print_entries:
|
2009-05-27 11:20:24 -07:00
|
|
|
for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
|
|
|
|
pos = rb_entry(nd, struct hist_entry, rb_node);
|
|
|
|
ret += hist_entry__fprintf(fp, pos, total_samples);
|
2009-05-26 12:19:04 -07:00
|
|
|
}
|
|
|
|
|
2009-06-18 05:32:19 -07:00
|
|
|
if (sort_order == default_sort_order &&
|
|
|
|
parent_pattern == default_parent_pattern) {
|
2009-06-04 05:13:04 -07:00
|
|
|
fprintf(fp, "#\n");
|
2009-08-05 03:25:21 -07:00
|
|
|
fprintf(fp, "# (For a higher level overview, try: perf report --sort comm,dso)\n");
|
2009-06-04 05:13:04 -07:00
|
|
|
fprintf(fp, "#\n");
|
|
|
|
}
|
2009-06-04 06:16:56 -07:00
|
|
|
fprintf(fp, "\n");
|
2009-06-04 05:13:04 -07:00
|
|
|
|
2009-08-07 17:16:25 -07:00
|
|
|
free(rem_sq_bracket);
|
|
|
|
|
2009-08-07 04:55:24 -07:00
|
|
|
if (show_threads)
|
2009-08-10 06:26:32 -07:00
|
|
|
perf_read_values_display(fp, &show_threads_values,
|
|
|
|
raw_printing_style);
|
2009-08-07 04:55:24 -07:00
|
|
|
|
2009-05-26 12:19:04 -07:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-06-18 13:20:45 -07:00
|
|
|
static int validate_chain(struct ip_callchain *chain, event_t *event)
|
2009-06-17 23:00:17 -07:00
|
|
|
{
|
|
|
|
unsigned int chain_size;
|
|
|
|
|
|
|
|
chain_size = event->header.size;
|
|
|
|
chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
|
|
|
|
|
perf_counter tools: Define and use our own u64, s64 etc. definitions
On 64-bit powerpc, __u64 is defined to be unsigned long rather than
unsigned long long. This causes compiler warnings every time we
print a __u64 value with %Lx.
Rather than changing __u64, we define our own u64 to be unsigned long
long on all architectures, and similarly s64 as signed long long.
For consistency we also define u32, s32, u16, s16, u8 and s8. These
definitions are put in a new header, types.h, because these definitions
are needed in util/string.h and util/symbol.h.
The main change here is the mechanical change of __[us]{64,32,16,8}
to remove the "__". The other changes are:
* Create types.h
* Include types.h in perf.h, util/string.h and util/symbol.h
* Add types.h to the LIB_H definition in Makefile
* Added (u64) casts in process_overflow_event() and print_sym_table()
to kill two remaining warnings.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: benh@kernel.crashing.org
LKML-Reference: <19003.33494.495844.956580@cargo.ozlabs.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-06-19 05:21:42 -07:00
|
|
|
if (chain->nr*sizeof(u64) > chain_size)
|
2009-06-17 23:00:17 -07:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-11-27 11:29:22 -07:00
|
|
|
static int process_sample_event(event_t *event)
|
2009-06-03 14:14:49 -07:00
|
|
|
{
|
2009-12-06 04:08:24 -07:00
|
|
|
struct sample_data data;
|
2009-06-30 16:00:48 -07:00
|
|
|
int cpumode;
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
struct addr_location al;
|
2009-12-06 04:08:24 -07:00
|
|
|
struct thread *thread;
|
2009-08-14 03:21:53 -07:00
|
|
|
|
2009-12-06 04:08:24 -07:00
|
|
|
memset(&data, 0, sizeof(data));
|
|
|
|
data.period = 1;
|
|
|
|
|
|
|
|
event__parse_sample(event, sample_type, &data);
|
2009-06-10 12:45:22 -07:00
|
|
|
|
2009-11-27 11:29:22 -07:00
|
|
|
dump_printf("(IP, %d): %d/%d: %p period: %Ld\n",
|
2009-06-03 14:14:49 -07:00
|
|
|
event->header.misc,
|
2009-12-06 04:08:24 -07:00
|
|
|
data.pid, data.tid,
|
|
|
|
(void *)(long)data.ip,
|
|
|
|
(long long)data.period);
|
2009-06-03 14:14:49 -07:00
|
|
|
|
2009-06-25 02:27:12 -07:00
|
|
|
if (sample_type & PERF_SAMPLE_CALLCHAIN) {
|
2009-07-01 03:37:06 -07:00
|
|
|
unsigned int i;
|
2009-06-14 06:04:15 -07:00
|
|
|
|
2009-12-06 04:08:24 -07:00
|
|
|
dump_printf("... chain: nr:%Lu\n", data.callchain->nr);
|
2009-06-14 06:04:15 -07:00
|
|
|
|
2009-12-06 04:08:24 -07:00
|
|
|
if (validate_chain(data.callchain, event) < 0) {
|
2009-10-21 12:34:06 -07:00
|
|
|
pr_debug("call-chain problem with event, "
|
|
|
|
"skipping it.\n");
|
2009-06-17 23:00:17 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dump_trace) {
|
2009-12-06 04:08:24 -07:00
|
|
|
for (i = 0; i < data.callchain->nr; i++)
|
|
|
|
dump_printf("..... %2d: %016Lx\n",
|
|
|
|
i, data.callchain->ips[i]);
|
2009-06-14 06:04:15 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-06 04:08:24 -07:00
|
|
|
thread = threads__findnew(data.pid);
|
2009-06-03 14:14:49 -07:00
|
|
|
if (thread == NULL) {
|
2009-10-21 12:34:06 -07:00
|
|
|
pr_debug("problem processing %d event, skipping it.\n",
|
2009-06-03 14:14:49 -07:00
|
|
|
event->header.type);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-05-27 11:20:24 -07:00
|
|
|
|
2009-10-16 23:43:17 -07:00
|
|
|
dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
|
|
|
|
|
2009-06-30 15:01:21 -07:00
|
|
|
if (comm_list && !strlist__has_entry(comm_list, thread->comm))
|
|
|
|
return 0;
|
|
|
|
|
perf: Do the big rename: Performance Counters -> Performance Events
Bye-bye Performance Counters, welcome Performance Events!
In the past few months the perfcounters subsystem has grown out its
initial role of counting hardware events, and has become (and is
becoming) a much broader generic event enumeration, reporting, logging,
monitoring, analysis facility.
Naming its core object 'perf_counter' and naming the subsystem
'perfcounters' has become more and more of a misnomer. With pending
code like hw-breakpoints support the 'counter' name is less and
less appropriate.
All in one, we've decided to rename the subsystem to 'performance
events' and to propagate this rename through all fields, variables
and API names. (in an ABI compatible fashion)
The word 'event' is also a bit shorter than 'counter' - which makes
it slightly more convenient to write/handle as well.
Thanks goes to Stephane Eranian who first observed this misnomer and
suggested a rename.
User-space tooling and ABI compatibility is not affected - this patch
should be function-invariant. (Also, defconfigs were not touched to
keep the size down.)
This patch has been generated via the following script:
FILES=$(find * -type f | grep -vE 'oprofile|[^K]config')
sed -i \
-e 's/PERF_EVENT_/PERF_RECORD_/g' \
-e 's/PERF_COUNTER/PERF_EVENT/g' \
-e 's/perf_counter/perf_event/g' \
-e 's/nb_counters/nb_events/g' \
-e 's/swcounter/swevent/g' \
-e 's/tpcounter_event/tp_event/g' \
$FILES
for N in $(find . -name perf_counter.[ch]); do
M=$(echo $N | sed 's/perf_counter/perf_event/g')
mv $N $M
done
FILES=$(find . -name perf_event.*)
sed -i \
-e 's/COUNTER_MASK/REG_MASK/g' \
-e 's/COUNTER/EVENT/g' \
-e 's/\<event\>/event_id/g' \
-e 's/counter/event/g' \
-e 's/Counter/Event/g' \
$FILES
... to keep it as correct as possible. This script can also be
used by anyone who has pending perfcounters patches - it converts
a Linux kernel tree over to the new naming. We tried to time this
change to the point in time where the amount of pending patches
is the smallest: the end of the merge window.
Namespace clashes were fixed up in a preparatory patch - and some
stylistic fallout will be fixed up in a subsequent patch.
( NOTE: 'counters' are still the proper terminology when we deal
with hardware registers - and these sed scripts are a bit
over-eager in renaming them. I've undone some of that, but
in case there's something left where 'counter' would be
better than 'event' we can undo that on an individual basis
instead of touching an otherwise nicely automated patch. )
Suggested-by: Stephane Eranian <eranian@google.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <linux-arch@vger.kernel.org>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-21 03:02:48 -07:00
|
|
|
cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
|
2009-06-30 16:00:48 -07:00
|
|
|
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
thread__find_addr_location(thread, cpumode,
|
2009-12-06 04:08:24 -07:00
|
|
|
MAP__FUNCTION, data.ip, &al, NULL);
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
/*
|
|
|
|
* We have to do this here as we may have a dso with no symbol hit that
|
|
|
|
* has a name longer than the ones with symbols sampled.
|
|
|
|
*/
|
|
|
|
if (al.map && !sort_dso.elide && !al.map->dso->slen_calculated)
|
|
|
|
dso__calc_col_width(al.map->dso);
|
2009-05-18 08:45:42 -07:00
|
|
|
|
2009-10-03 16:30:48 -07:00
|
|
|
if (dso_list &&
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
(!al.map || !al.map->dso ||
|
|
|
|
!(strlist__has_entry(dso_list, al.map->dso->short_name) ||
|
|
|
|
(al.map->dso->short_name != al.map->dso->long_name &&
|
|
|
|
strlist__has_entry(dso_list, al.map->dso->long_name)))))
|
2009-10-03 16:30:48 -07:00
|
|
|
return 0;
|
2009-06-30 15:01:20 -07:00
|
|
|
|
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to
process IP sample events:
int event__preprocess_sample(const event_t *self,
struct addr_location *al,
symbol_filter_t filter)
It receives the event itself and will insert new threads in the
global threads list and resolve the map and symbol, filling all
this info into the new addr_location struct, so that tools like
annotate and report can further process the event by creating
hist_entries in their specific way (with or without callgraphs,
etc).
It in turn uses the new next layer function:
void thread__find_addr_location(struct thread *self, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
This one will, given a thread (userspace or the kernel kthread
one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE
too in the near future) at the given cpumode, taking vdsos into
account (userspace hit, but kernel symbol) and will fill all
these details in the addr_location given.
Tools that need a more compact API for plain function
resolution, like 'kmem', can use this other one:
struct symbol *thread__find_function(struct thread *self, u64 addr,
symbol_filter_t filter)
So, to resolve a kernel symbol, that is all the 'kmem' tool
needs, its just a matter of calling:
sym = thread__find_function(kthread, addr, NULL);
The 'filter' parameter is needed because we do lazy
parsing/loading of ELF symtabs or /proc/kallsyms.
With this we remove more code duplication all around, which is
always good, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-11-27 11:29:23 -07:00
|
|
|
if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
|
2009-10-03 16:30:48 -07:00
|
|
|
return 0;
|
2009-06-30 15:01:22 -07:00
|
|
|
|
2009-12-06 04:08:24 -07:00
|
|
|
if (hist_entry__add(&al, data.callchain, data.period)) {
|
2009-10-21 12:34:06 -07:00
|
|
|
pr_debug("problem incrementing symbol count, skipping event\n");
|
2009-10-03 16:30:48 -07:00
|
|
|
return -1;
|
2009-05-18 08:45:42 -07:00
|
|
|
}
|
2009-10-03 16:30:48 -07:00
|
|
|
|
2009-12-06 04:08:24 -07:00
|
|
|
event__stats.total += data.period;
|
2009-05-18 08:45:42 -07:00
|
|
|
|
2009-06-03 14:14:49 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2009-06-03 00:38:58 -07:00
|
|
|
|
2009-11-27 11:29:22 -07:00
|
|
|
static int process_comm_event(event_t *event)
|
2009-06-03 14:14:49 -07:00
|
|
|
{
|
2009-10-13 07:16:29 -07:00
|
|
|
struct thread *thread = threads__findnew(event->comm.pid);
|
2009-06-03 14:14:49 -07:00
|
|
|
|
2009-11-27 11:29:22 -07:00
|
|
|
dump_printf(": %s:%d\n", event->comm.comm, event->comm.pid);
|
2009-06-03 14:14:49 -07:00
|
|
|
|
|
|
|
if (thread == NULL ||
|
2009-08-18 07:03:46 -07:00
|
|
|
thread__set_comm_adjust(thread, event->comm.comm)) {
|
perf: Do the big rename: Performance Counters -> Performance Events
Bye-bye Performance Counters, welcome Performance Events!
In the past few months the perfcounters subsystem has grown out its
initial role of counting hardware events, and has become (and is
becoming) a much broader generic event enumeration, reporting, logging,
monitoring, analysis facility.
Naming its core object 'perf_counter' and naming the subsystem
'perfcounters' has become more and more of a misnomer. With pending
code like hw-breakpoints support the 'counter' name is less and
less appropriate.
All in one, we've decided to rename the subsystem to 'performance
events' and to propagate this rename through all fields, variables
and API names. (in an ABI compatible fashion)
The word 'event' is also a bit shorter than 'counter' - which makes
it slightly more convenient to write/handle as well.
Thanks goes to Stephane Eranian who first observed this misnomer and
suggested a rename.
User-space tooling and ABI compatibility is not affected - this patch
should be function-invariant. (Also, defconfigs were not touched to
keep the size down.)
This patch has been generated via the following script:
FILES=$(find * -type f | grep -vE 'oprofile|[^K]config')
sed -i \
-e 's/PERF_EVENT_/PERF_RECORD_/g' \
-e 's/PERF_COUNTER/PERF_EVENT/g' \
-e 's/perf_counter/perf_event/g' \
-e 's/nb_counters/nb_events/g' \
-e 's/swcounter/swevent/g' \
-e 's/tpcounter_event/tp_event/g' \
$FILES
for N in $(find . -name perf_counter.[ch]); do
M=$(echo $N | sed 's/perf_counter/perf_event/g')
mv $N $M
done
FILES=$(find . -name perf_event.*)
sed -i \
-e 's/COUNTER_MASK/REG_MASK/g' \
-e 's/COUNTER/EVENT/g' \
-e 's/\<event\>/event_id/g' \
-e 's/counter/event/g' \
-e 's/Counter/Event/g' \
$FILES
... to keep it as correct as possible. This script can also be
used by anyone who has pending perfcounters patches - it converts
a Linux kernel tree over to the new naming. We tried to time this
change to the point in time where the amount of pending patches
is the smallest: the end of the merge window.
Namespace clashes were fixed up in a preparatory patch - and some
stylistic fallout will be fixed up in a subsequent patch.
( NOTE: 'counters' are still the proper terminology when we deal
with hardware registers - and these sed scripts are a bit
over-eager in renaming them. I've undone some of that, but
in case there's something left where 'counter' would be
better than 'event' we can undo that on an individual basis
instead of touching an otherwise nicely automated patch. )
Suggested-by: Stephane Eranian <eranian@google.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <linux-arch@vger.kernel.org>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-21 03:02:48 -07:00
|
|
|
dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
|
2009-06-03 14:14:49 -07:00
|
|
|
return -1;
|
2009-05-18 08:45:42 -07:00
|
|
|
}
|
2009-06-18 02:40:28 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-11-27 11:29:22 -07:00
|
|
|
static int process_read_event(event_t *event)
|
2009-06-24 13:46:04 -07:00
|
|
|
{
|
perf: Do the big rename: Performance Counters -> Performance Events
Bye-bye Performance Counters, welcome Performance Events!
In the past few months the perfcounters subsystem has grown out its
initial role of counting hardware events, and has become (and is
becoming) a much broader generic event enumeration, reporting, logging,
monitoring, analysis facility.
Naming its core object 'perf_counter' and naming the subsystem
'perfcounters' has become more and more of a misnomer. With pending
code like hw-breakpoints support the 'counter' name is less and
less appropriate.
All in one, we've decided to rename the subsystem to 'performance
events' and to propagate this rename through all fields, variables
and API names. (in an ABI compatible fashion)
The word 'event' is also a bit shorter than 'counter' - which makes
it slightly more convenient to write/handle as well.
Thanks goes to Stephane Eranian who first observed this misnomer and
suggested a rename.
User-space tooling and ABI compatibility is not affected - this patch
should be function-invariant. (Also, defconfigs were not touched to
keep the size down.)
This patch has been generated via the following script:
FILES=$(find * -type f | grep -vE 'oprofile|[^K]config')
sed -i \
-e 's/PERF_EVENT_/PERF_RECORD_/g' \
-e 's/PERF_COUNTER/PERF_EVENT/g' \
-e 's/perf_counter/perf_event/g' \
-e 's/nb_counters/nb_events/g' \
-e 's/swcounter/swevent/g' \
-e 's/tpcounter_event/tp_event/g' \
$FILES
for N in $(find . -name perf_counter.[ch]); do
M=$(echo $N | sed 's/perf_counter/perf_event/g')
mv $N $M
done
FILES=$(find . -name perf_event.*)
sed -i \
-e 's/COUNTER_MASK/REG_MASK/g' \
-e 's/COUNTER/EVENT/g' \
-e 's/\<event\>/event_id/g' \
-e 's/counter/event/g' \
-e 's/Counter/Event/g' \
$FILES
... to keep it as correct as possible. This script can also be
used by anyone who has pending perfcounters patches - it converts
a Linux kernel tree over to the new naming. We tried to time this
change to the point in time where the amount of pending patches
is the smallest: the end of the merge window.
Namespace clashes were fixed up in a preparatory patch - and some
stylistic fallout will be fixed up in a subsequent patch.
( NOTE: 'counters' are still the proper terminology when we deal
with hardware registers - and these sed scripts are a bit
over-eager in renaming them. I've undone some of that, but
in case there's something left where 'counter' would be
better than 'event' we can undo that on an individual basis
instead of touching an otherwise nicely automated patch. )
Suggested-by: Stephane Eranian <eranian@google.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Arjan van de Ven <arjan@linux.intel.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: David Howells <dhowells@redhat.com>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <linux-arch@vger.kernel.org>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-09-21 03:02:48 -07:00
|
|
|
struct perf_event_attr *attr;
|
2009-08-16 11:56:37 -07:00
|
|
|
|
2009-12-11 16:24:02 -07:00
|
|
|
attr = perf_header__find_attr(event->read.id, &session->header);
|
2009-08-06 10:40:28 -07:00
|
|
|
|
2009-08-07 04:55:24 -07:00
|
|
|
if (show_threads) {
|
2009-08-15 03:26:57 -07:00
|
|
|
const char *name = attr ? __event_name(attr->type, attr->config)
|
2009-08-07 04:55:24 -07:00
|
|
|
: "unknown";
|
|
|
|
perf_read_values_add_value(&show_threads_values,
|
|
|
|
event->read.pid, event->read.tid,
|
|
|
|
event->read.id,
|
|
|
|
name,
|
|
|
|
event->read.value);
|
|
|
|
}
|
|
|
|
|
2009-11-27 11:29:22 -07:00
|
|
|
dump_printf(": %d %d %s %Lu\n", event->read.pid, event->read.tid,
|
|
|
|
attr ? __event_name(attr->type, attr->config) : "FAIL",
|
|
|
|
event->read.value);
|
2009-06-24 13:46:04 -07:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-10-07 03:47:31 -07:00
|
|
|
static int sample_type_check(u64 type)
|
2009-06-03 14:14:49 -07:00
|
|
|
{
|
2009-10-07 03:47:31 -07:00
|
|
|
sample_type = type;
|
2009-06-25 02:27:12 -07:00
|
|
|
|
2009-07-04 22:39:17 -07:00
|
|
|
if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
|
|
|
|
if (sort__has_parent) {
|
|
|
|
fprintf(stderr, "selected --sort parent, but no"
|
|
|
|
" callchain data. Did you call"
|
|
|
|
" perf record without -g?\n");
|
2009-10-07 03:47:31 -07:00
|
|
|
return -1;
|
2009-07-04 22:39:17 -07:00
|
|
|
}
|
|
|
|
if (callchain) {
|
2009-08-17 14:07:48 -07:00
|
|
|
fprintf(stderr, "selected -g but no callchain data."
|
2009-07-04 22:39:17 -07:00
|
|
|
" Did you call perf record without"
|
|
|
|
" -g?\n");
|
2009-10-07 03:47:31 -07:00
|
|
|
return -1;
|
2009-07-04 22:39:17 -07:00
|
|
|
}
|
2009-08-07 17:16:24 -07:00
|
|
|
} else if (callchain_param.mode != CHAIN_NONE && !callchain) {
|
|
|
|
callchain = 1;
|
|
|
|
if (register_callchain_param(&callchain_param) < 0) {
|
|
|
|
fprintf(stderr, "Can't register callchain"
|
|
|
|
" params\n");
|
2009-10-07 03:47:31 -07:00
|
|
|
return -1;
|
2009-08-07 17:16:24 -07:00
|
|
|
}
|
2009-06-18 14:22:55 -07:00
|
|
|
}
|
|
|
|
|
2009-10-07 03:47:31 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2009-05-26 11:51:47 -07:00
|
|
|
|
2009-10-07 03:47:31 -07:00
|
|
|
static struct perf_file_handler file_handler = {
|
|
|
|
.process_sample_event = process_sample_event,
|
2009-11-27 11:29:22 -07:00
|
|
|
.process_mmap_event = event__process_mmap,
|
2009-10-07 03:47:31 -07:00
|
|
|
.process_comm_event = process_comm_event,
|
2009-11-27 11:29:22 -07:00
|
|
|
.process_exit_event = event__process_task,
|
|
|
|
.process_fork_event = event__process_task,
|
|
|
|
.process_lost_event = event__process_lost,
|
2009-10-07 03:47:31 -07:00
|
|
|
.process_read_event = process_read_event,
|
|
|
|
.sample_type_check = sample_type_check,
|
|
|
|
};
|
2009-05-26 11:51:47 -07:00
|
|
|
|
|
|
|
|
2009-10-07 03:47:31 -07:00
|
|
|
static int __cmd_report(void)
|
|
|
|
{
|
|
|
|
struct thread *idle;
|
|
|
|
int ret;
|
2009-05-18 08:45:42 -07:00
|
|
|
|
2009-12-11 16:24:02 -07:00
|
|
|
session = perf_session__new(input_name, O_RDONLY, force);
|
|
|
|
if (session == NULL)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2009-10-13 07:16:29 -07:00
|
|
|
idle = register_idle_thread();
|
2009-10-07 03:47:31 -07:00
|
|
|
thread__comm_adjust(idle);
|
2009-05-26 10:03:36 -07:00
|
|
|
|
2009-10-07 03:47:31 -07:00
|
|
|
if (show_threads)
|
|
|
|
perf_read_values_init(&show_threads_values);
|
2009-06-18 14:22:55 -07:00
|
|
|
|
2009-10-07 03:47:31 -07:00
|
|
|
register_perf_file_handler(&file_handler);
|
2009-05-18 08:45:42 -07:00
|
|
|
|
2009-12-11 16:24:02 -07:00
|
|
|
ret = perf_session__process_events(session, full_paths,
|
|
|
|
&event__cwdlen, &event__cwd);
|
2009-10-07 03:47:31 -07:00
|
|
|
if (ret)
|
2009-12-11 16:24:02 -07:00
|
|
|
goto out_delete;
|
2009-05-26 09:48:58 -07:00
|
|
|
|
2009-11-27 11:29:22 -07:00
|
|
|
if (dump_trace) {
|
|
|
|
event__print_totals();
|
2009-12-11 16:24:02 -07:00
|
|
|
goto out_delete;
|
2009-11-27 11:29:22 -07:00
|
|
|
}
|
2009-05-26 09:48:58 -07:00
|
|
|
|
2009-10-07 06:49:00 -07:00
|
|
|
if (verbose > 3)
|
2009-10-13 07:16:29 -07:00
|
|
|
threads__fprintf(stdout);
|
2009-06-04 09:54:00 -07:00
|
|
|
|
2009-10-07 06:49:00 -07:00
|
|
|
if (verbose > 2)
|
2009-05-27 00:10:38 -07:00
|
|
|
dsos__fprintf(stdout);
|
|
|
|
|
2009-06-03 03:37:36 -07:00
|
|
|
collapse__resort();
|
2009-11-27 11:29:22 -07:00
|
|
|
output__resort(event__stats.total);
|
|
|
|
output__fprintf(stdout, event__stats.total);
|
2009-05-18 08:45:42 -07:00
|
|
|
|
2009-08-07 04:55:24 -07:00
|
|
|
if (show_threads)
|
|
|
|
perf_read_values_destroy(&show_threads_values);
|
2009-12-11 16:24:02 -07:00
|
|
|
out_delete:
|
|
|
|
perf_session__delete(session);
|
2009-10-07 03:47:31 -07:00
|
|
|
return ret;
|
2009-05-18 08:45:42 -07:00
|
|
|
}
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
static int
|
|
|
|
parse_callchain_opt(const struct option *opt __used, const char *arg,
|
|
|
|
int unset __used)
|
|
|
|
{
|
2009-07-02 11:14:33 -07:00
|
|
|
char *tok;
|
|
|
|
char *endptr;
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
callchain = 1;
|
|
|
|
|
|
|
|
if (!arg)
|
|
|
|
return 0;
|
|
|
|
|
2009-07-02 11:14:33 -07:00
|
|
|
tok = strtok((char *)arg, ",");
|
|
|
|
if (!tok)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* get the output mode */
|
|
|
|
if (!strncmp(tok, "graph", strlen(arg)))
|
2009-07-04 22:39:21 -07:00
|
|
|
callchain_param.mode = CHAIN_GRAPH_ABS;
|
2009-07-02 08:58:21 -07:00
|
|
|
|
2009-07-02 11:14:33 -07:00
|
|
|
else if (!strncmp(tok, "flat", strlen(arg)))
|
2009-07-04 22:39:21 -07:00
|
|
|
callchain_param.mode = CHAIN_FLAT;
|
|
|
|
|
|
|
|
else if (!strncmp(tok, "fractal", strlen(arg)))
|
|
|
|
callchain_param.mode = CHAIN_GRAPH_REL;
|
|
|
|
|
2009-08-07 17:16:24 -07:00
|
|
|
else if (!strncmp(tok, "none", strlen(arg))) {
|
|
|
|
callchain_param.mode = CHAIN_NONE;
|
|
|
|
callchain = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-07-02 08:58:21 -07:00
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
|
2009-07-02 11:14:33 -07:00
|
|
|
/* get the min percentage */
|
|
|
|
tok = strtok(NULL, ",");
|
|
|
|
if (!tok)
|
2009-07-04 22:39:21 -07:00
|
|
|
goto setup;
|
2009-07-02 11:14:33 -07:00
|
|
|
|
2009-07-04 22:39:21 -07:00
|
|
|
callchain_param.min_percent = strtod(tok, &endptr);
|
2009-07-02 11:14:33 -07:00
|
|
|
if (tok == endptr)
|
|
|
|
return -1;
|
|
|
|
|
2009-07-04 22:39:21 -07:00
|
|
|
setup:
|
|
|
|
if (register_callchain_param(&callchain_param) < 0) {
|
|
|
|
fprintf(stderr, "Can't register callchain params\n");
|
|
|
|
return -1;
|
|
|
|
}
|
2009-07-02 08:58:21 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-24 09:02:49 -07:00
|
|
|
//static const char * const report_usage[] = {
|
|
|
|
const char * const report_usage[] = {
|
2009-05-26 00:17:18 -07:00
|
|
|
"perf report [<options>] <command>",
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct option options[] = {
|
|
|
|
OPT_STRING('i', "input", &input_name, "file",
|
|
|
|
"input file name"),
|
2009-05-26 15:46:14 -07:00
|
|
|
OPT_BOOLEAN('v', "verbose", &verbose,
|
|
|
|
"be more verbose (show symbol address, etc)"),
|
2009-05-26 09:48:58 -07:00
|
|
|
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
|
|
|
|
"dump raw trace in ASCII"),
|
2009-11-24 07:05:15 -07:00
|
|
|
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
|
|
|
|
"file", "vmlinux pathname"),
|
2009-08-19 02:18:26 -07:00
|
|
|
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
|
2009-11-24 07:05:15 -07:00
|
|
|
OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
|
2009-07-01 23:09:46 -07:00
|
|
|
"load module symbols - WARNING: use only with -k and LIVE kernel"),
|
2009-07-11 08:18:37 -07:00
|
|
|
OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples,
|
|
|
|
"Show a column with the number of samples"),
|
2009-08-07 04:55:24 -07:00
|
|
|
OPT_BOOLEAN('T', "threads", &show_threads,
|
|
|
|
"Show per-thread event counters"),
|
2009-08-10 06:26:32 -07:00
|
|
|
OPT_STRING(0, "pretty", &pretty_printing_style, "key",
|
|
|
|
"pretty printing style key: normal raw"),
|
2009-05-28 01:52:00 -07:00
|
|
|
OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
|
2009-06-17 22:01:03 -07:00
|
|
|
"sort by key(s): pid, comm, dso, symbol, parent"),
|
2009-05-29 09:48:59 -07:00
|
|
|
OPT_BOOLEAN('P', "full-paths", &full_paths,
|
|
|
|
"Don't shorten the pathnames taking into account the cwd"),
|
2009-06-17 22:01:03 -07:00
|
|
|
OPT_STRING('p', "parent", &parent_pattern, "regex",
|
|
|
|
"regex filter to identify parent, see: '--sort parent'"),
|
2009-06-18 05:32:19 -07:00
|
|
|
OPT_BOOLEAN('x', "exclude-other", &exclude_other,
|
|
|
|
"Only display entries with parent-match"),
|
2009-07-16 06:44:29 -07:00
|
|
|
OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent",
|
2009-07-02 11:14:33 -07:00
|
|
|
"Display callchains using output_type and min percent threshold. "
|
2009-07-16 06:44:29 -07:00
|
|
|
"Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt),
|
2009-06-30 15:01:20 -07:00
|
|
|
OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
|
|
|
|
"only consider symbols in these dsos"),
|
2009-06-30 15:01:21 -07:00
|
|
|
OPT_STRING('C', "comms", &comm_list_str, "comm[,comm...]",
|
|
|
|
"only consider symbols in these comms"),
|
2009-06-30 15:01:22 -07:00
|
|
|
OPT_STRING('S', "symbols", &sym_list_str, "symbol[,symbol...]",
|
|
|
|
"only consider these symbols"),
|
2009-07-10 18:47:28 -07:00
|
|
|
OPT_STRING('w', "column-widths", &col_width_list_str,
|
|
|
|
"width[,width...]",
|
|
|
|
"don't try to adjust column width, use these fixed values"),
|
|
|
|
OPT_STRING('t', "field-separator", &field_sep, "separator",
|
|
|
|
"separator for columns, no spaces will be added between "
|
|
|
|
"columns '.' is reserved."),
|
2009-05-26 00:17:18 -07:00
|
|
|
OPT_END()
|
|
|
|
};
|
|
|
|
|
2009-06-03 01:07:39 -07:00
|
|
|
static void setup_sorting(void)
|
|
|
|
{
|
|
|
|
char *tmp, *tok, *str = strdup(sort_order);
|
|
|
|
|
|
|
|
for (tok = strtok_r(str, ", ", &tmp);
|
|
|
|
tok; tok = strtok_r(NULL, ", ", &tmp)) {
|
|
|
|
if (sort_dimension__add(tok) < 0) {
|
|
|
|
error("Unknown --sort key: `%s'", tok);
|
|
|
|
usage_with_options(report_usage, options);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(str);
|
|
|
|
}
|
|
|
|
|
2009-06-30 15:01:21 -07:00
|
|
|
static void setup_list(struct strlist **list, const char *list_str,
|
2009-07-11 08:18:35 -07:00
|
|
|
struct sort_entry *se, const char *list_name,
|
|
|
|
FILE *fp)
|
2009-06-30 15:01:21 -07:00
|
|
|
{
|
|
|
|
if (list_str) {
|
|
|
|
*list = strlist__new(true, list_str);
|
|
|
|
if (!*list) {
|
|
|
|
fprintf(stderr, "problems parsing %s list\n",
|
|
|
|
list_name);
|
|
|
|
exit(129);
|
|
|
|
}
|
2009-07-11 08:18:35 -07:00
|
|
|
if (strlist__nr_entries(*list) == 1) {
|
|
|
|
fprintf(fp, "# %s: %s\n", list_name,
|
|
|
|
strlist__entry(*list, 0)->s);
|
|
|
|
se->elide = true;
|
|
|
|
}
|
2009-06-30 15:01:21 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-01 03:37:06 -07:00
|
|
|
int cmd_report(int argc, const char **argv, const char *prefix __used)
|
2009-05-26 00:17:18 -07:00
|
|
|
{
|
2009-11-24 07:05:15 -07:00
|
|
|
if (symbol__init(&symbol_conf) < 0)
|
|
|
|
return -1;
|
2009-05-26 00:17:18 -07:00
|
|
|
|
2009-06-04 07:24:37 -07:00
|
|
|
argc = parse_options(argc, argv, options, report_usage, 0);
|
2009-05-26 00:17:18 -07:00
|
|
|
|
2009-05-27 11:20:25 -07:00
|
|
|
setup_sorting();
|
|
|
|
|
2009-07-11 08:18:35 -07:00
|
|
|
if (parent_pattern != default_parent_pattern) {
|
2009-06-18 05:32:19 -07:00
|
|
|
sort_dimension__add("parent");
|
2009-07-11 08:18:35 -07:00
|
|
|
sort_parent.elide = 1;
|
|
|
|
} else
|
2009-06-18 05:32:19 -07:00
|
|
|
exclude_other = 0;
|
|
|
|
|
2009-06-04 07:24:37 -07:00
|
|
|
/*
|
|
|
|
* Any (unrecognized) arguments left?
|
|
|
|
*/
|
|
|
|
if (argc)
|
|
|
|
usage_with_options(report_usage, options);
|
|
|
|
|
2009-05-27 00:50:13 -07:00
|
|
|
setup_pager();
|
|
|
|
|
2009-07-11 08:18:35 -07:00
|
|
|
setup_list(&dso_list, dso_list_str, &sort_dso, "dso", stdout);
|
|
|
|
setup_list(&comm_list, comm_list_str, &sort_comm, "comm", stdout);
|
|
|
|
setup_list(&sym_list, sym_list_str, &sort_sym, "symbol", stdout);
|
2009-06-30 15:01:20 -07:00
|
|
|
|
2009-07-10 18:47:28 -07:00
|
|
|
if (field_sep && *field_sep == '.') {
|
|
|
|
fputs("'.' is the only non valid --field-separator argument\n",
|
|
|
|
stderr);
|
|
|
|
exit(129);
|
|
|
|
}
|
|
|
|
|
2009-05-26 00:17:18 -07:00
|
|
|
return __cmd_report();
|
|
|
|
}
|