overlay: Accumulate busy times

Still a little too course as we add multiple overlapping seqnos and
waits.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-08-17 22:33:35 +01:00
parent 6233cac9c9
commit 67f533f836
3 changed files with 83 additions and 26 deletions

View File

@ -154,7 +154,7 @@ err:
return EINVAL; return EINVAL;
} }
static char *get_comm(pid_t pid, char *comm, int len) static int get_comm(pid_t pid, char *comm, int len)
{ {
char filename[1024]; char filename[1024];
int fd; int fd;
@ -168,9 +168,10 @@ static char *get_comm(pid_t pid, char *comm, int len)
if (len >= 0) if (len >= 0)
comm[len-1] = '\0'; comm[len-1] = '\0';
close(fd); close(fd);
} } else
len = -1;
return comm; return len;
} }
static struct gpu_perf_comm * static struct gpu_perf_comm *
@ -178,6 +179,9 @@ lookup_comm(struct gpu_perf *gp, pid_t pid)
{ {
struct gpu_perf_comm *comm; struct gpu_perf_comm *comm;
if (pid == 0)
return NULL;
for (comm = gp->comm; comm != NULL; comm = comm->next) { for (comm = gp->comm; comm != NULL; comm = comm->next) {
if (comm->pid == pid) if (comm->pid == pid)
break; break;
@ -187,10 +191,14 @@ lookup_comm(struct gpu_perf *gp, pid_t pid)
if (comm == NULL) if (comm == NULL)
return NULL; return NULL;
if (get_comm(pid, comm->name, sizeof(comm->name)) < 0) {
free(comm);
return NULL;
}
comm->pid = pid;
comm->next = gp->comm; comm->next = gp->comm;
gp->comm = comm; gp->comm = comm;
get_comm(pid, comm->name, sizeof(comm->name));
comm->pid = pid;
} }
return comm; return comm;
@ -209,13 +217,44 @@ static int request_add(struct gpu_perf *gp, const void *event)
return 1; return 1;
} }
static int seqno_start(struct gpu_perf *gp, const void *event) static int busy_start(struct gpu_perf *gp, const void *event)
{ {
const struct sample_event *sample = event;
struct gpu_perf_comm *comm;
struct gpu_perf_time *busy;
comm = lookup_comm(gp, sample->pid);
if (comm == NULL)
return 0;
busy = malloc(sizeof(*busy));
if (busy == NULL)
return 0;
busy->seqno = sample->raw[2];
busy->time = sample->time;
busy->comm = comm;
busy->next = gp->busy;
gp->busy = busy;
return 0; return 0;
} }
static int seqno_end(struct gpu_perf *gp, const void *event) static int busy_end(struct gpu_perf *gp, const void *event)
{ {
const struct sample_event *sample = event;
struct gpu_perf_time *busy, **prev;
for (prev = &gp->busy; (busy = *prev) != NULL; prev = &busy->next) {
if (busy->seqno != sample->raw[2])
continue;
busy->comm->busy_time += sample->time - busy->time;
*prev = busy->next;
free(busy);
return 1;
}
return 0; return 0;
} }
@ -229,7 +268,7 @@ static int wait_begin(struct gpu_perf *gp, const void *event)
{ {
const struct sample_event *sample = event; const struct sample_event *sample = event;
struct gpu_perf_comm *comm; struct gpu_perf_comm *comm;
struct gpu_perf_wait *wait; struct gpu_perf_time *wait;
comm = lookup_comm(gp, sample->pid); comm = lookup_comm(gp, sample->pid);
if (comm == NULL) if (comm == NULL)
@ -239,10 +278,11 @@ static int wait_begin(struct gpu_perf *gp, const void *event)
if (wait == NULL) if (wait == NULL)
return 0; return 0;
wait->comm = comm;
wait->seqno = sample->raw[3]; wait->seqno = sample->raw[3];
wait->time = sample->time; wait->time = sample->time;
wait->next = comm->wait; wait->next = gp->wait;
comm->wait = wait; gp->wait = wait;
return 0; return 0;
} }
@ -250,18 +290,13 @@ static int wait_begin(struct gpu_perf *gp, const void *event)
static int wait_end(struct gpu_perf *gp, const void *event) static int wait_end(struct gpu_perf *gp, const void *event)
{ {
const struct sample_event *sample = event; const struct sample_event *sample = event;
struct gpu_perf_comm *comm; struct gpu_perf_time *wait, **prev;
struct gpu_perf_wait *wait, **prev;
comm = lookup_comm(gp, sample->pid); for (prev = &gp->wait; (wait = *prev) != NULL; prev = &wait->next) {
if (comm == NULL)
return 0;
for (prev = &comm->wait; (wait = *prev) != NULL; prev = &wait->next) {
if (wait->seqno != sample->raw[3]) if (wait->seqno != sample->raw[3])
continue; continue;
comm->wait_time += sample->time - wait->time; wait->comm->wait_time += sample->time - wait->time;
*prev = wait->next; *prev = wait->next;
free(wait); free(wait);
return 1; return 1;
@ -277,8 +312,8 @@ void gpu_perf_init(struct gpu_perf *gp, unsigned flags)
gp->page_size = getpagesize(); gp->page_size = getpagesize();
perf_tracepoint_open(gp, "i915", "i915_gem_request_add", request_add); perf_tracepoint_open(gp, "i915", "i915_gem_request_add", request_add);
if (perf_tracepoint_open(gp, "i915", "i915_gem_ring_complete", seqno_end) == 0) if (perf_tracepoint_open(gp, "i915", "i915_gem_ring_complete", busy_end) == 0)
perf_tracepoint_open(gp, "i915", "i915_gem_ring_dispatch", seqno_start); perf_tracepoint_open(gp, "i915", "i915_gem_ring_dispatch", busy_start);
if (perf_tracepoint_open(gp, "i915", "i915_gem_request_wait_begin", wait_begin) == 0) if (perf_tracepoint_open(gp, "i915", "i915_gem_request_wait_begin", wait_begin) == 0)
perf_tracepoint_open(gp, "i915", "i915_gem_request_wait_end", wait_end); perf_tracepoint_open(gp, "i915", "i915_gem_request_wait_end", wait_end);
perf_tracepoint_open(gp, "i915", "i915_flip_complete", flip_complete); perf_tracepoint_open(gp, "i915", "i915_flip_complete", flip_complete);

View File

@ -14,19 +14,20 @@ struct gpu_perf {
int flip_complete; int flip_complete;
struct gpu_perf_comm { struct gpu_perf_comm {
struct gpu_perf_comm *next; struct gpu_perf_comm *next;
struct gpu_perf_wait {
struct gpu_perf_wait *next;
uint32_t seqno;
uint64_t time;
} *wait;
char name[256]; char name[256];
pid_t pid; pid_t pid;
int nr_requests[4]; int nr_requests[4];
void *user_data; void *user_data;
uint64_t wait_begin;
uint64_t wait_time; uint64_t wait_time;
uint64_t busy_time;
} *comm; } *comm;
struct gpu_perf_time {
struct gpu_perf_time *next;
struct gpu_perf_comm *comm;
uint32_t seqno;
uint64_t time;
} *wait, *busy;
}; };
void gpu_perf_init(struct gpu_perf *gp, unsigned flags); void gpu_perf_init(struct gpu_perf *gp, unsigned flags);

View File

@ -286,6 +286,27 @@ static void show_gpu_perf(struct overlay_context *ctx, struct overlay_gpu_perf *
} }
comm->wait_time = 0; comm->wait_time = 0;
} }
if (comm->busy_time) {
buf[0] = '\0';
if (comm->busy_time > 1000*1000) {
sprintf(buf, "%s %.1f ms busy",
need_comma ? "," : "",
comm->busy_time / (1000*1000.));
} else if (comm->busy_time > 100) {
sprintf(buf, "%s %.1f us busy",
need_comma ? "," : "",
comm->busy_time / 1000.);
} else {
sprintf(buf, "%s %.0f ns busy",
need_comma ? "," : "",
(double)comm->busy_time);
}
if (buf[0] != '\0') {
cairo_show_text(ctx->cr, buf);
need_comma = true;
}
comm->busy_time = 0;
}
y += 14; y += 14;
memset(comm->nr_requests, 0, sizeof(comm->nr_requests)); memset(comm->nr_requests, 0, sizeof(comm->nr_requests));