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

Commit d243144a authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Jiri Olsa
Browse files

perf timechart: Add more options to IO mode



--io-skip-eagain - don't show EAGAIN errors
--io-min-time    - make small io bursts visible
--io-merge-dist  - merge adjacent events

Signed-off-by: default avatarStanislav Fomichev <stfomichev@yandex-team.ru>
Acked-by: default avatarNamhyung Kim <namhyung@kernel.org>
Link: http://lkml.kernel.org/n/1404835423-23098-5-git-send-email-stfomichev@yandex-team.ru


Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
parent 962e310a
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -64,6 +64,19 @@ TIMECHART OPTIONS
	duration or tasks with given name. If number is given it's interpreted
	as number of nanoseconds. If non-numeric string is given it's
	interpreted as task name.
--io-skip-eagain::
	Don't draw EAGAIN IO events.
--io-min-time=<nsecs>::
	Draw small events as if they lasted min-time. Useful when you need
	to see very small and fast IO. It's possible to specify ms or us
	suffix to specify time in milliseconds or microseconds.
	Default value is 1ms.
--io-merge-dist=<nsecs>::
	Merge events that are merge-dist nanoseconds apart.
	Reduces number of figures on the SVG and makes it more render-friendly.
	It's possible to specify ms or us suffix to specify time in
	milliseconds or microseconds.
	Default value is 1us.

RECORD OPTIONS
--------------
+73 −2
Original line number Diff line number Diff line
@@ -62,7 +62,10 @@ struct timechart {
				topology;
	/* IO related settings */
	u64			io_events;
	bool			io_only;
	bool			io_only,
				skip_eagain;
	u64			min_time,
				merge_dist;
};

struct per_pidcomm;
@@ -761,7 +764,7 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
{
	struct per_pid *p = find_create_pid(tchart, pid);
	struct per_pidcomm *c = p->current;
	struct io_sample *sample;
	struct io_sample *sample, *prev;

	if (!c) {
		pr_warning("Invalid pidcomm!\n");
@@ -785,6 +788,18 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
	}

	sample->end_time = end;
	prev = sample->next;

	/* we want to be able to see small and fast transfers, so make them
	 * at least min_time long, but don't overlap them */
	if (sample->end_time - sample->start_time < tchart->min_time)
		sample->end_time = sample->start_time + tchart->min_time;
	if (prev && sample->start_time < prev->end_time) {
		if (prev->err) /* try to make errors more visible */
			sample->start_time = prev->end_time;
		else
			prev->end_time = sample->start_time;
	}

	if (ret < 0) {
		sample->err = ret;
@@ -799,6 +814,24 @@ static int pid_end_io_sample(struct timechart *tchart, int pid, int type,
		sample->bytes = ret;
	}

	/* merge two requests to make svg smaller and render-friendly */
	if (prev &&
	    prev->type == sample->type &&
	    prev->err == sample->err &&
	    prev->fd == sample->fd &&
	    prev->end_time + tchart->merge_dist >= sample->start_time) {

		sample->bytes += prev->bytes;
		sample->merges += prev->merges + 1;

		sample->start_time = prev->start_time;
		sample->next = prev->next;
		free(prev);

		if (!sample->err && sample->bytes > c->max_bytes)
			c->max_bytes = sample->bytes;
	}

	tchart->io_events++;

	return 0;
@@ -1119,6 +1152,10 @@ static void draw_io_bars(struct timechart *tchart)
			for (sample = c->io_samples; sample; sample = sample->next) {
				double h = (double)sample->bytes / c->max_bytes;

				if (tchart->skip_eagain &&
				    sample->err == -EAGAIN)
					continue;

				if (sample->err)
					h = 1;

@@ -1849,6 +1886,30 @@ parse_highlight(const struct option *opt __maybe_unused, const char *arg,
	return 0;
}

static int
parse_time(const struct option *opt, const char *arg, int __maybe_unused unset)
{
	char unit = 'n';
	u64 *value = opt->value;

	if (sscanf(arg, "%" PRIu64 "%cs", value, &unit) > 0) {
		switch (unit) {
		case 'm':
			*value *= 1000000;
			break;
		case 'u':
			*value *= 1000;
			break;
		case 'n':
			break;
		default:
			return -1;
		}
	}

	return 0;
}

int cmd_timechart(int argc, const char **argv,
		  const char *prefix __maybe_unused)
{
@@ -1861,6 +1922,8 @@ int cmd_timechart(int argc, const char **argv,
			.ordered_samples = true,
		},
		.proc_num = 15,
		.min_time = 1000000,
		.merge_dist = 1000,
	};
	const char *output_name = "output.svg";
	const struct option timechart_options[] = {
@@ -1882,6 +1945,14 @@ int cmd_timechart(int argc, const char **argv,
		    "min. number of tasks to print"),
	OPT_BOOLEAN('t', "topology", &tchart.topology,
		    "sort CPUs according to topology"),
	OPT_BOOLEAN(0, "io-skip-eagain", &tchart.skip_eagain,
		    "skip EAGAIN errors"),
	OPT_CALLBACK(0, "io-min-time", &tchart.min_time, "time",
		     "all IO faster than min-time will visually appear longer",
		     parse_time),
	OPT_CALLBACK(0, "io-merge-dist", &tchart.merge_dist, "time",
		     "merge events that are merge-dist us apart",
		     parse_time),
	OPT_END()
	};
	const char * const timechart_usage[] = {