Skip to content

Commit

Permalink
perf tools: Add latency format to trace output
Browse files Browse the repository at this point in the history
Add the irqs disabled, preemption count, need resched, and other
info that is shown in the latency format of ftrace.

 # perf trace -l
    perf-16457   2..s2. 53636.260344: kmem_cache_free: call_site=ffffffff811198f
    perf-16457   2..s2. 53636.264330: kmem_cache_free: call_site=ffffffff811198f
    perf-16457   2d.s4. 53636.300006: kmem_cache_free: call_site=ffffffff810d889

Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <20091014194400.076588953@goodmis.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Steven Rostedt authored and Ingo Molnar committed Oct 15, 2009
1 parent 0d1da91 commit cda4846
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 19 deletions.
2 changes: 2 additions & 0 deletions tools/perf/builtin-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ static const struct option options[] = {
"dump raw trace in ASCII"),
OPT_BOOLEAN('v', "verbose", &verbose,
"be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('l', "latency", &latency_format,
"show latency attributes (irqs/preemption disabled, etc)"),
OPT_END()
};

Expand Down
120 changes: 101 additions & 19 deletions tools/perf/util/trace-event-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ int header_page_size_size;
int header_page_data_offset;
int header_page_data_size;

int latency_format;

static char *input_buf;
static unsigned long long input_buf_ptr;
static unsigned long long input_buf_siz;
Expand Down Expand Up @@ -1928,37 +1930,67 @@ static int get_common_info(const char *type, int *offset, int *size)
return 0;
}

int trace_parse_common_type(void *data)
static int __parse_common(void *data, int *size, int *offset,
char *name)
{
static int type_offset;
static int type_size;
int ret;

if (!type_size) {
ret = get_common_info("common_type",
&type_offset,
&type_size);
if (!*size) {
ret = get_common_info(name, offset, size);
if (ret < 0)
return ret;
}
return read_size(data + type_offset, type_size);
return read_size(data + *offset, *size);
}

int trace_parse_common_type(void *data)
{
static int type_offset;
static int type_size;

return __parse_common(data, &type_size, &type_offset,
(char *)"common_type");
}

static int parse_common_pid(void *data)
{
static int pid_offset;
static int pid_size;

return __parse_common(data, &pid_size, &pid_offset,
(char *)"common_pid");
}

static int parse_common_pc(void *data)
{
static int pc_offset;
static int pc_size;

return __parse_common(data, &pc_size, &pc_offset,
(char *)"common_preempt_count");
}

static int parse_common_flags(void *data)
{
static int flags_offset;
static int flags_size;

return __parse_common(data, &flags_size, &flags_offset,
(char *)"common_flags");
}

static int parse_common_lock_depth(void *data)
{
static int ld_offset;
static int ld_size;
int ret;

if (!pid_size) {
ret = get_common_info("common_pid",
&pid_offset,
&pid_size);
if (ret < 0)
return ret;
}
ret = __parse_common(data, &ld_size, &ld_offset,
(char *)"common_lock_depth");
if (ret < 0)
return -1;

return read_size(data + pid_offset, pid_size);
return ret;
}

struct event *trace_find_event(int id)
Expand Down Expand Up @@ -2525,6 +2557,41 @@ static inline int log10_cpu(int nb)
return 1;
}

static void print_lat_fmt(void *data, int size __unused)
{
unsigned int lat_flags;
unsigned int pc;
int lock_depth;
int hardirq;
int softirq;

lat_flags = parse_common_flags(data);
pc = parse_common_pc(data);
lock_depth = parse_common_lock_depth(data);

hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
softirq = lat_flags & TRACE_FLAG_SOFTIRQ;

printf("%c%c%c",
(lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
(lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
'X' : '.',
(lat_flags & TRACE_FLAG_NEED_RESCHED) ?
'N' : '.',
(hardirq && softirq) ? 'H' :
hardirq ? 'h' : softirq ? 's' : '.');

if (pc)
printf("%x", pc);
else
printf(".");

if (lock_depth < 0)
printf(".");
else
printf("%d", lock_depth);
}

/* taken from Linux, written by Frederic Weisbecker */
static void print_graph_cpu(int cpu)
{
Expand Down Expand Up @@ -2768,6 +2835,11 @@ pretty_print_func_ent(void *data, int size, struct event *event,

printf(" | ");

if (latency_format) {
print_lat_fmt(data, size);
printf(" | ");
}

field = find_field(event, "func");
if (!field)
die("function entry does not have func field");
Expand Down Expand Up @@ -2811,6 +2883,11 @@ pretty_print_func_ret(void *data, int size __unused, struct event *event,

printf(" | ");

if (latency_format) {
print_lat_fmt(data, size);
printf(" | ");
}

field = find_field(event, "rettime");
if (!field)
die("can't find rettime in return graph");
Expand Down Expand Up @@ -2882,9 +2959,14 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
return pretty_print_func_graph(data, size, event, cpu,
pid, comm, secs, usecs);

printf("%16s-%-5d [%03d] %5lu.%09Lu: %s: ",
comm, pid, cpu,
secs, nsecs, event->name);
if (latency_format) {
printf("%8.8s-%-5d %3d",
comm, pid, cpu);
print_lat_fmt(data, size);
} else
printf("%16s-%-5d [%03d]", comm, pid, cpu);

printf(" %5lu.%06lu: %s: ", secs, usecs, event->name);

if (event->flags & EVENT_FL_FAILED) {
printf("EVENT '%s' FAILED TO PARSE\n",
Expand Down
11 changes: 11 additions & 0 deletions tools/perf/util/trace-event.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ extern int header_page_size_size;
extern int header_page_data_offset;
extern int header_page_data_size;

extern int latency_format;

int parse_header_page(char *buf, unsigned long size);
int trace_parse_common_type(void *data);
struct event *trace_find_event(int id);
Expand All @@ -248,4 +250,13 @@ void *raw_field_ptr(struct event *event, const char *name, void *data);

void read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events);

/* taken from kernel/trace/trace.h */
enum trace_flag_type {
TRACE_FLAG_IRQS_OFF = 0x01,
TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
TRACE_FLAG_NEED_RESCHED = 0x04,
TRACE_FLAG_HARDIRQ = 0x08,
TRACE_FLAG_SOFTIRQ = 0x10,
};

#endif /* __PERF_TRACE_EVENTS_H */

0 comments on commit cda4846

Please sign in to comment.