Skip to content

Commit

Permalink
perf newt: Make <- zoom out filters
Browse files Browse the repository at this point in the history
After we use the filters to zoom into DSOs or threads, we can use <-
(left arrow) to zoom out from the last filter applied.

It is still possible to zoom out of order by using the popup menu.

With this we now have the zoom out operation on the browsing fast path,
by allowing fast navigation using just the four arrors and the enter key
to expand collapse callchains.

Suggested-by: Ingo Molnar <mingo@elte.hu>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Arnaldo Carvalho de Melo committed May 14, 2010
1 parent c82ee82 commit 3e1bbdc
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 3 deletions.
2 changes: 2 additions & 0 deletions tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ LIB_H += util/thread.h
LIB_H += util/trace-event.h
LIB_H += util/probe-finder.h
LIB_H += util/probe-event.h
LIB_H += util/pstack.h
LIB_H += util/cpumap.h

LIB_OBJS += $(OUTPUT)util/abspath.o
Expand Down Expand Up @@ -451,6 +452,7 @@ LIB_OBJS += $(OUTPUT)util/callchain.o
LIB_OBJS += $(OUTPUT)util/values.o
LIB_OBJS += $(OUTPUT)util/debug.o
LIB_OBJS += $(OUTPUT)util/map.o
LIB_OBJS += $(OUTPUT)util/pstack.o
LIB_OBJS += $(OUTPUT)util/session.o
LIB_OBJS += $(OUTPUT)util/thread.o
LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
Expand Down
34 changes: 31 additions & 3 deletions tools/perf/util/newt.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "cache.h"
#include "hist.h"
#include "pstack.h"
#include "session.h"
#include "sort.h"
#include "symbol.h"
Expand Down Expand Up @@ -750,6 +751,7 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
newtFormAddHotKey(self->form, 'A');
newtFormAddHotKey(self->form, 'a');
newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
newtFormAddHotKey(self->form, NEWT_KEY_LEFT);
newtFormAddComponents(self->form, self->tree, NULL);
self->selection = newt__symbol_tree_get_current(self->tree);

Expand Down Expand Up @@ -801,6 +803,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
int hists__browse(struct hists *self, const char *helpline, const char *input_name)
{
struct hist_browser *browser = hist_browser__new();
struct pstack *fstack = pstack__new(2);
const struct thread *thread_filter = NULL;
const struct dso *dso_filter = NULL;
struct newtExitStruct es;
Expand All @@ -810,12 +813,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
if (browser == NULL)
return -1;

fstack = pstack__new(2);
if (fstack == NULL)
goto out;

ui_helpline__push(helpline);

hist_browser__title(msg, sizeof(msg), input_name,
dso_filter, thread_filter);
if (hist_browser__populate(browser, self, msg) < 0)
goto out;
goto out_free_stack;

while (1) {
const struct thread *thread;
Expand All @@ -836,6 +843,19 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
else
continue;
}

if (es.u.key == NEWT_KEY_LEFT) {
const void *top;

if (pstack__empty(fstack))
continue;
top = pstack__pop(fstack);
if (top == &dso_filter)
goto zoom_out_dso;
if (top == &thread_filter)
goto zoom_out_thread;
continue;
}
}

if (browser->selection->sym != NULL &&
Expand Down Expand Up @@ -888,12 +908,15 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
hist_entry__annotate_browser(he);
} else if (choice == zoom_dso) {
if (dso_filter) {
pstack__remove(fstack, &dso_filter);
zoom_out_dso:
ui_helpline__pop();
dso_filter = NULL;
} else {
ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s DSO\"",
ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
dso->kernel ? "the Kernel" : dso->short_name);
dso_filter = dso;
pstack__push(fstack, &dso_filter);
}
hists__filter_by_dso(self, dso_filter);
hist_browser__title(msg, sizeof(msg), input_name,
Expand All @@ -902,13 +925,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
goto out;
} else if (choice == zoom_thread) {
if (thread_filter) {
pstack__remove(fstack, &thread_filter);
zoom_out_thread:
ui_helpline__pop();
thread_filter = NULL;
} else {
ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s(%d) thread\"",
ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
thread->comm_set ? thread->comm : "",
thread->pid);
thread_filter = thread;
pstack__push(fstack, &thread_filter);
}
hists__filter_by_thread(self, thread_filter);
hist_browser__title(msg, sizeof(msg), input_name,
Expand All @@ -918,6 +944,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
}
}
err = 0;
out_free_stack:
pstack__delete(fstack);
out:
hist_browser__delete(browser);
return err;
Expand Down
75 changes: 75 additions & 0 deletions tools/perf/util/pstack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Simple pointer stack
*
* (c) 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
*/

#include "util.h"
#include "pstack.h"
#include <linux/kernel.h>
#include <stdlib.h>

struct pstack {
unsigned short top;
unsigned short max_nr_entries;
void *entries[0];
};

struct pstack *pstack__new(unsigned short max_nr_entries)
{
struct pstack *self = zalloc((sizeof(*self) +
max_nr_entries * sizeof(void *)));
if (self != NULL)
self->max_nr_entries = max_nr_entries;
return self;
}

void pstack__delete(struct pstack *self)
{
free(self);
}

bool pstack__empty(const struct pstack *self)
{
return self->top == 0;
}

void pstack__remove(struct pstack *self, void *key)
{
unsigned short i = self->top, last_index = self->top - 1;

while (i-- != 0) {
if (self->entries[i] == key) {
if (i < last_index)
memmove(self->entries + i,
self->entries + i + 1,
(last_index - i) * sizeof(void *));
--self->top;
return;
}
}
pr_err("%s: %p not on the pstack!\n", __func__, key);
}

void pstack__push(struct pstack *self, void *key)
{
if (self->top == self->max_nr_entries) {
pr_err("%s: top=%d, overflow!\n", __func__, self->top);
return;
}
self->entries[self->top++] = key;
}

void *pstack__pop(struct pstack *self)
{
void *ret;

if (self->top == 0) {
pr_err("%s: underflow!\n", __func__);
return NULL;
}

ret = self->entries[--self->top];
self->entries[self->top] = NULL;
return ret;
}
12 changes: 12 additions & 0 deletions tools/perf/util/pstack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef _PERF_PSTACK_
#define _PERF_PSTACK_

struct pstack;
struct pstack *pstack__new(unsigned short max_nr_entries);
void pstack__delete(struct pstack *self);
bool pstack__empty(const struct pstack *self);
void pstack__remove(struct pstack *self, void *key);
void pstack__push(struct pstack *self, void *key);
void *pstack__pop(struct pstack *self);

#endif /* _PERF_PSTACK_ */

0 comments on commit 3e1bbdc

Please sign in to comment.