struct thread;
-static const char *thread__name(struct thread *self, char *bf, size_t size);
-
struct thread {
struct rb_node rb_node;
struct list_head maps;
char *comm;
};
-static const char *thread__name(struct thread *self, char *bf, size_t size)
-{
- if (self->comm)
- return self->comm;
-
- snprintf(bf, sizeof(bf), ":%u", self->pid);
- return bf;
-}
-
static struct thread *thread__new(pid_t pid)
{
struct thread *self = malloc(sizeof(*self));
struct sort_entry {
struct list_head list;
+ char *header;
+
int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
size_t (*print)(FILE *fp, struct hist_entry *);
};
static size_t
sort__thread_print(FILE *fp, struct hist_entry *self)
{
- char bf[32];
-
- return fprintf(fp, "%14s ",
- thread__name(self->thread, bf, sizeof(bf)));
+ return fprintf(fp, " %16s:%5d", self->thread->comm ?: "", self->thread->pid);
}
static struct sort_entry sort_thread = {
+ .header = " Command: Pid ",
.cmp = sort__thread_cmp,
.print = sort__thread_print,
};
static size_t
sort__comm_print(FILE *fp, struct hist_entry *self)
{
- return fprintf(fp, "%20s ", self->thread->comm ?: "<unknown>");
+ return fprintf(fp, " %16s", self->thread->comm ?: "<unknown>");
}
static struct sort_entry sort_comm = {
+ .header = " Command",
.cmp = sort__comm_cmp,
.print = sort__comm_print,
};
+static int64_t
+sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+ struct dso *dso_l = left->dso;
+ struct dso *dso_r = right->dso;
+
+ if (!dso_l || !dso_r) {
+ if (!dso_l && !dso_r)
+ return 0;
+ else if (!dso_l)
+ return -1;
+ else
+ return 1;
+ }
+
+ return strcmp(dso_l->name, dso_r->name);
+}
+
+static size_t
+sort__dso_print(FILE *fp, struct hist_entry *self)
+{
+ return fprintf(fp, " %64s", self->dso ? self->dso->name : "<unknown>");
+}
+
+static struct sort_entry sort_dso = {
+ .header = " Shared Object",
+ .cmp = sort__dso_cmp,
+ .print = sort__dso_print,
+};
+
static int64_t
sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
{
{
size_t ret = 0;
- ret += fprintf(fp, "[%c] ", self->level);
-
if (verbose)
- ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
+ ret += fprintf(fp, " %#018llx", (unsigned long long)self->ip);
- if (self->level != '.')
- ret += fprintf(fp, "%s ",
- self->sym ? self->sym->name : "<unknown>");
- else
- ret += fprintf(fp, "%s: %s ",
- self->dso ? self->dso->name : "<unknown>",
- self->sym ? self->sym->name : "<unknown>");
+ ret += fprintf(fp, " %s: %s",
+ self->dso ? self->dso->name : "<unknown>",
+ self->sym ? self->sym->name : "<unknown>");
return ret;
}
static struct sort_entry sort_sym = {
+ .header = "Shared Object: Symbol",
.cmp = sort__sym_cmp,
.print = sort__sym_print,
};
static struct sort_dimension sort_dimensions[] = {
{ .name = "pid", .entry = &sort_thread, },
{ .name = "comm", .entry = &sort_comm, },
+ { .name = "dso", .entry = &sort_dso, },
{ .name = "symbol", .entry = &sort_sym, },
};
size_t ret;
if (total_samples) {
- ret = fprintf(fp, "%5.2f%% ",
+ ret = fprintf(fp, " %5.2f%%",
(self->count * 100.0) / total_samples);
} else
ret = fprintf(fp, "%12d ", self->count);
static size_t output__fprintf(FILE *fp, uint64_t total_samples)
{
struct hist_entry *pos;
+ struct sort_entry *se;
struct rb_node *nd;
size_t ret = 0;
+ fprintf(fp, "#\n");
+
+ fprintf(fp, "# Overhead");
+ list_for_each_entry(se, &hist_entry__sort_list, list)
+ fprintf(fp, " %s", se->header);
+ fprintf(fp, "\n");
+
+ fprintf(fp, "# ........");
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ int i;
+
+ fprintf(fp, " ");
+ for (i = 0; i < strlen(se->header); i++)
+ fprintf(fp, ".");
+ }
+ fprintf(fp, "\n");
+
+ fprintf(fp, "#\n");
+
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);
}
if (thread == NULL) {
- fprintf(stderr, "problem processing %d event, bailing out\n",
+ fprintf(stderr, "problem processing %d event, skipping it.\n",
event->header.type);
- goto done;
+ goto broken_event;
}
if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
if (hist_entry__add(thread, map, dso, sym, ip, level)) {
fprintf(stderr,
- "problem incrementing symbol count, bailing out\n");
- goto done;
+ "problem incrementing symbol count, skipping event\n");
+ goto broken_event;
}
}
total++;
event->mmap.filename);
}
if (thread == NULL || map == NULL) {
- fprintf(stderr, "problem processing PERF_EVENT_MMAP, bailing out\n");
- goto done;
+ fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n");
+ goto broken_event;
}
thread__insert_map(thread, map);
total_mmap++;
}
if (thread == NULL ||
thread__set_comm(thread, event->comm.comm)) {
- fprintf(stderr, "problem processing PERF_EVENT_COMM, bailing out\n");
- goto done;
+ fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n");
+ goto broken_event;
}
total_comm++;
break;
goto more;
rc = EXIT_SUCCESS;
-done:
close(input);
if (dump_trace) {