mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
perf timechart: Add a process filter
During the Kernel Summit demo of perf/ftrace/timechart, there was a feature request to have a process filter for timechart so that you can zoom into one or a few processes that you are really interested in. This patch adds basic support for this feature, the -p (--process) option now can select a PID or a process name to be shown. Multiple -p options are allowed, and the combined set will be included in the output. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20091020070939.7d0fb8a7@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
c258449bc9
commit
bbe2987bea
2 changed files with 106 additions and 4 deletions
|
@ -31,9 +31,12 @@ OPTIONS
|
||||||
-w::
|
-w::
|
||||||
--width=::
|
--width=::
|
||||||
Select the width of the SVG file (default: 1000)
|
Select the width of the SVG file (default: 1000)
|
||||||
-p::
|
-P::
|
||||||
--power-only::
|
--power-only::
|
||||||
Only output the CPU power section of the diagram
|
Only output the CPU power section of the diagram
|
||||||
|
-p::
|
||||||
|
--process::
|
||||||
|
Select the processes to display, by name or PID
|
||||||
|
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
|
|
|
@ -153,6 +153,17 @@ static struct wake_event *wake_events;
|
||||||
|
|
||||||
struct sample_wrapper *all_samples;
|
struct sample_wrapper *all_samples;
|
||||||
|
|
||||||
|
|
||||||
|
struct process_filter;
|
||||||
|
struct process_filter {
|
||||||
|
char *name;
|
||||||
|
int pid;
|
||||||
|
struct process_filter *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct process_filter *process_filter;
|
||||||
|
|
||||||
|
|
||||||
static struct per_pid *find_create_pid(int pid)
|
static struct per_pid *find_create_pid(int pid)
|
||||||
{
|
{
|
||||||
struct per_pid *cursor = all_data;
|
struct per_pid *cursor = all_data;
|
||||||
|
@ -763,11 +774,11 @@ static void draw_wakeups(void)
|
||||||
c = p->all;
|
c = p->all;
|
||||||
while (c) {
|
while (c) {
|
||||||
if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
|
if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
|
||||||
if (p->pid == we->waker) {
|
if (p->pid == we->waker && !from) {
|
||||||
from = c->Y;
|
from = c->Y;
|
||||||
task_from = strdup(c->comm);
|
task_from = strdup(c->comm);
|
||||||
}
|
}
|
||||||
if (p->pid == we->wakee) {
|
if (p->pid == we->wakee && !to) {
|
||||||
to = c->Y;
|
to = c->Y;
|
||||||
task_to = strdup(c->comm);
|
task_to = strdup(c->comm);
|
||||||
}
|
}
|
||||||
|
@ -882,12 +893,89 @@ static void draw_process_bars(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_process_filter(const char *string)
|
||||||
|
{
|
||||||
|
struct process_filter *filt;
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
pid = strtoull(string, NULL, 10);
|
||||||
|
filt = malloc(sizeof(struct process_filter));
|
||||||
|
if (!filt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
filt->name = strdup(string);
|
||||||
|
filt->pid = pid;
|
||||||
|
filt->next = process_filter;
|
||||||
|
|
||||||
|
process_filter = filt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
|
||||||
|
{
|
||||||
|
struct process_filter *filt;
|
||||||
|
if (!process_filter)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
filt = process_filter;
|
||||||
|
while (filt) {
|
||||||
|
if (filt->pid && p->pid == filt->pid)
|
||||||
|
return 1;
|
||||||
|
if (strcmp(filt->name, c->comm) == 0)
|
||||||
|
return 1;
|
||||||
|
filt = filt->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int determine_display_tasks_filtered(void)
|
||||||
|
{
|
||||||
|
struct per_pid *p;
|
||||||
|
struct per_pidcomm *c;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
p = all_data;
|
||||||
|
while (p) {
|
||||||
|
p->display = 0;
|
||||||
|
if (p->start_time == 1)
|
||||||
|
p->start_time = first_time;
|
||||||
|
|
||||||
|
/* no exit marker, task kept running to the end */
|
||||||
|
if (p->end_time == 0)
|
||||||
|
p->end_time = last_time;
|
||||||
|
|
||||||
|
c = p->all;
|
||||||
|
|
||||||
|
while (c) {
|
||||||
|
c->display = 0;
|
||||||
|
|
||||||
|
if (c->start_time == 1)
|
||||||
|
c->start_time = first_time;
|
||||||
|
|
||||||
|
if (passes_filter(p, c)) {
|
||||||
|
c->display = 1;
|
||||||
|
p->display = 1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->end_time == 0)
|
||||||
|
c->end_time = last_time;
|
||||||
|
|
||||||
|
c = c->next;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static int determine_display_tasks(u64 threshold)
|
static int determine_display_tasks(u64 threshold)
|
||||||
{
|
{
|
||||||
struct per_pid *p;
|
struct per_pid *p;
|
||||||
struct per_pidcomm *c;
|
struct per_pidcomm *c;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
if (process_filter)
|
||||||
|
return determine_display_tasks_filtered();
|
||||||
|
|
||||||
p = all_data;
|
p = all_data;
|
||||||
while (p) {
|
while (p) {
|
||||||
p->display = 0;
|
p->display = 0;
|
||||||
|
@ -1153,6 +1241,14 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
return cmd_record(i, rec_argv, NULL);
|
return cmd_record(i, rec_argv, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
parse_process(const struct option *opt __used, const char *arg, int __used unset)
|
||||||
|
{
|
||||||
|
if (arg)
|
||||||
|
add_process_filter(arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
OPT_STRING('i', "input", &input_name, "file",
|
OPT_STRING('i', "input", &input_name, "file",
|
||||||
"input file name"),
|
"input file name"),
|
||||||
|
@ -1160,8 +1256,11 @@ static const struct option options[] = {
|
||||||
"output file name"),
|
"output file name"),
|
||||||
OPT_INTEGER('w', "width", &svg_page_width,
|
OPT_INTEGER('w', "width", &svg_page_width,
|
||||||
"page width"),
|
"page width"),
|
||||||
OPT_BOOLEAN('p', "power-only", &power_only,
|
OPT_BOOLEAN('P', "power-only", &power_only,
|
||||||
"output power data only"),
|
"output power data only"),
|
||||||
|
OPT_CALLBACK('p', "process", NULL, "process",
|
||||||
|
"process selector. Pass a pid or process name.",
|
||||||
|
parse_process),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue