Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbe2987b authored by Arjan van de Ven's avatar Arjan van de Ven Committed by Ingo Molnar
Browse files

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: default avatarArjan 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: default avatarIngo Molnar <mingo@elte.hu>
parent c258449b
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -31,9 +31,12 @@ OPTIONS
-w::
--width=::
        Select the width of the SVG file (default: 1000)
-p::
-P::
--power-only::
        Only output the CPU power section of the diagram
-p::
--process::
        Select the processes to display, by name or PID


SEE ALSO
+102 −3
Original line number Diff line number Diff line
@@ -153,6 +153,17 @@ static struct wake_event *wake_events;

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)
{
	struct per_pid *cursor = all_data;
@@ -763,11 +774,11 @@ static void draw_wakeups(void)
				c = p->all;
				while (c) {
					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;
							task_from = strdup(c->comm);
						}
						if (p->pid == we->wakee) {
						if (p->pid == we->wakee && !to) {
							to = c->Y;
							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)
{
	struct per_pid *p;
	struct per_pidcomm *c;
	int count = 0;

	if (process_filter)
		return determine_display_tasks_filtered();

	p = all_data;
	while (p) {
		p->display = 0;
@@ -1153,6 +1241,14 @@ static int __cmd_record(int argc, const char **argv)
	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[] = {
	OPT_STRING('i', "input", &input_name, "file",
		    "input file name"),
@@ -1160,8 +1256,11 @@ static const struct option options[] = {
		    "output file name"),
	OPT_INTEGER('w', "width", &svg_page_width,
		    "page width"),
	OPT_BOOLEAN('p', "power-only", &power_only,
	OPT_BOOLEAN('P', "power-only", &power_only,
		    "output power data only"),
	OPT_CALLBACK('p', "process", NULL, "process",
		      "process selector. Pass a pid or process name.",
		       parse_process),
	OPT_END()
};