overlay: Track requests per-process

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-08-17 20:04:11 +01:00
parent be9937b65c
commit cbbd55af15
3 changed files with 150 additions and 35 deletions

View File

@ -30,6 +30,8 @@ struct sample_event {
uint64_t time; uint64_t time;
uint64_t id; uint64_t id;
uint32_t raw_size; uint32_t raw_size;
uint32_t raw_hdr0;
uint32_t raw_hdr1;
uint32_t raw[0]; uint32_t raw[0];
}; };
@ -117,7 +119,6 @@ static int perf_tracepoint_open(struct gpu_perf *gp,
if (gp->nr_events) if (gp->nr_events)
ioctl(fd[n], PERF_EVENT_IOC_SET_OUTPUT, gp->fd[n]); ioctl(fd[n], PERF_EVENT_IOC_SET_OUTPUT, gp->fd[n]);
} }
gp->nr_events++; gp->nr_events++;
@ -149,8 +150,53 @@ err:
return EINVAL; return EINVAL;
} }
static char *get_comm(pid_t pid, char *comm, int len)
{
char filename[1024];
int fd;
*comm = '\0';
snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
fd = open(filename, 0);
if (fd >= 0) {
len = read(fd, comm, len-1);
if (len >= 0)
comm[len-1] = '\0';
close(fd);
}
return comm;
}
static int request_add(struct gpu_perf *gp, const void *event)
{
const struct sample_event *sample = event;
struct gpu_perf_comm *comm;
for (comm = gp->comm; comm != NULL; comm = comm->next) {
if (comm->pid == sample->pid)
break;
}
if (comm == NULL) {
comm = malloc(sizeof(*comm));
if (comm == NULL)
return 0;
comm->next = gp->comm;
gp->comm = comm;
get_comm(sample->pid, comm->name, sizeof(comm->name));
comm->pid = sample->pid;
memset(comm->nr_requests, 0, sizeof(comm->nr_requests));
}
comm->nr_requests[sample->raw[1]]++;
return 1;
}
static int seqno_start(struct gpu_perf *gp, const void *event) static int seqno_start(struct gpu_perf *gp, const void *event)
{ {
printf ("seqno_start\n");
return 0; return 0;
} }
@ -171,9 +217,9 @@ void gpu_perf_init(struct gpu_perf *gp, unsigned flags)
gp->nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); gp->nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
gp->page_size = getpagesize(); gp->page_size = getpagesize();
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", seqno_end) == 0)
perf_tracepoint_open(gp, "i915", "i915_gem_ring_dispatch", seqno_start); perf_tracepoint_open(gp, "i915", "i915_gem_ring_dispatch", seqno_start);
perf_tracepoint_open(gp, "i915", "i915_flip_complete", flip_complete); perf_tracepoint_open(gp, "i915", "i915_flip_complete", flip_complete);
if (gp->nr_events == 0) if (gp->nr_events == 0)
@ -218,13 +264,18 @@ int gpu_perf_update(struct gpu_perf *gp)
struct perf_event_mmap_page *mmap = gp->map[n]; struct perf_event_mmap_page *mmap = gp->map[n];
const uint8_t *data; const uint8_t *data;
uint64_t head, tail; uint64_t head, tail;
int wrap = 0;
tail = mmap->data_tail; tail = mmap->data_tail;
head = mmap->data_head; head = mmap->data_head;
rmb(); rmb();
if (head < tail) if (head < tail) {
wrap = 1;
tail &= mask;
head &= mask;
head += size; head += size;
}
data = (uint8_t *)mmap + gp->page_size; data = (uint8_t *)mmap + gp->page_size;
while (head - tail >= sizeof (struct perf_event_header)) { while (head - tail >= sizeof (struct perf_event_header)) {
@ -259,7 +310,9 @@ int gpu_perf_update(struct gpu_perf *gp)
tail += header->size; tail += header->size;
} }
mmap->data_tail = tail & mask; if (wrap)
tail &= mask;
mmap->data_tail = tail;
} }
free(buffer); free(buffer);

View File

@ -12,6 +12,12 @@ struct gpu_perf {
} *sample; } *sample;
int flip_complete; int flip_complete;
struct gpu_perf_comm {
struct gpu_perf_comm *next;
char name[256];
pid_t pid;
int nr_requests[4];
} *comm;
}; };
void gpu_perf_init(struct gpu_perf *gp, unsigned flags); void gpu_perf_init(struct gpu_perf *gp, unsigned flags);

View File

@ -1,4 +1,3 @@
#include <X11/Xlib.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <cairo.h> #include <cairo.h>
@ -7,6 +6,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include "overlay.h" #include "overlay.h"
@ -52,6 +52,11 @@ static void overlay_hide(cairo_surface_t *surface)
} }
#endif #endif
struct overlay_context {
cairo_t *cr;
int last_y;
};
struct overlay_gpu_top { struct overlay_gpu_top {
struct gpu_top gpu_top; struct gpu_top gpu_top;
struct chart busy[MAX_RINGS]; struct chart busy[MAX_RINGS];
@ -100,7 +105,7 @@ static void init_gpu_top(struct overlay_gpu_top *gt,
} }
} }
static void show_gpu_top(cairo_t *cr, struct overlay_gpu_top *gt) static void show_gpu_top(struct overlay_context *ctx, struct overlay_gpu_top *gt)
{ {
int y, n, update; int y, n, update;
@ -109,16 +114,16 @@ static void show_gpu_top(cairo_t *cr, struct overlay_gpu_top *gt)
if (update) if (update)
chart_add_sample(&gt->wait[n], chart_add_sample(&gt->wait[n],
gt->gpu_top.ring[n].u.u.wait + gt->gpu_top.ring[n].u.u.sema); gt->gpu_top.ring[n].u.u.wait + gt->gpu_top.ring[n].u.u.sema);
chart_draw(&gt->wait[n], cr); chart_draw(&gt->wait[n], ctx->cr);
} }
for (n = 0; n < gt->gpu_top.num_rings; n++) { for (n = 0; n < gt->gpu_top.num_rings; n++) {
if (update) if (update)
chart_add_sample(&gt->busy[n], chart_add_sample(&gt->busy[n],
gt->gpu_top.ring[n].u.u.busy); gt->gpu_top.ring[n].u.u.busy);
chart_draw(&gt->busy[n], cr); chart_draw(&gt->busy[n], ctx->cr);
} }
cairo_set_source_rgb(cr, 1, 1, 1); cairo_set_source_rgb(ctx->cr, 1, 1, 1);
y = 12; y = 12;
for (n = 0; n < gt->gpu_top.num_rings; n++) { for (n = 0; n < gt->gpu_top.num_rings; n++) {
@ -135,10 +140,12 @@ static void show_gpu_top(cairo_t *cr, struct overlay_gpu_top *gt)
len += sprintf(txt + len, ", %d%% sema", len += sprintf(txt + len, ", %d%% sema",
gt->gpu_top.ring[n].u.u.sema); gt->gpu_top.ring[n].u.u.sema);
cairo_move_to(cr, 12, y); cairo_move_to(ctx->cr, 12, y);
cairo_show_text(cr, txt); cairo_show_text(ctx->cr, txt);
y += 14; y += 14;
} }
ctx->last_y = 112;
} }
struct overlay_gpu_perf { struct overlay_gpu_perf {
@ -146,29 +153,75 @@ struct overlay_gpu_perf {
}; };
static void init_gpu_perf(struct overlay_gpu_perf *gp, static void init_gpu_perf(struct overlay_gpu_perf *gp,
cairo_surface_t *surface) cairo_surface_t *surface)
{ {
gpu_perf_init(&gp->gpu_perf, 0); gpu_perf_init(&gp->gpu_perf, 0);
} }
static void show_gpu_perf(cairo_t *cr, struct overlay_gpu_perf *gp) static char *get_comm(pid_t pid, char *comm, int len)
{ {
char filename[1024];
int fd;
*comm = '\0';
snprintf(filename, sizeof(filename), "/proc/%d/comm", pid);
fd = open(filename, 0);
if (fd >= 0) {
len = read(fd, comm, len-1);
if (len >= 0)
comm[len-1] = '\0';
close(fd);
}
return comm;
}
static void show_gpu_perf(struct overlay_context *ctx, struct overlay_gpu_perf *gp)
{
struct gpu_perf_comm *comm, **prev;
const char *ring_name[] = {
"render",
"video",
"blt",
};
char buf[1024]; char buf[1024];
int y; int y, n;
gpu_perf_update(&gp->gpu_perf); gpu_perf_update(&gp->gpu_perf);
y = 130; y = ctx->last_y + 18;
for (prev = &gp->gpu_perf.comm; (comm = *prev) != NULL; ) {
cairo_move_to(ctx->cr, 12, y);
sprintf(buf, "%s:", comm->name);
cairo_show_text(ctx->cr, buf);
for (n = 0; n < 3; n++) {
if (comm->nr_requests[n] == 0)
continue;
sprintf(buf, " %d %s", comm->nr_requests[n], ring_name[n]);
cairo_show_text(ctx->cr, buf);
}
y += 14;
memset(comm->nr_requests, 0, sizeof(comm->nr_requests));
if (strcmp(comm->name, get_comm(comm->pid, buf, sizeof(buf)))) {
*prev = comm->next;
free(comm);
} else
prev = &comm->next;
}
sprintf(buf, "Flips: %d", gp->gpu_perf.flip_complete); sprintf(buf, "Flips: %d", gp->gpu_perf.flip_complete);
cairo_move_to(cr, 12, y); gp->gpu_perf.flip_complete = 0;
cairo_show_text(cr, buf); cairo_move_to(ctx->cr, 12, y);
cairo_show_text(ctx->cr, buf);
y += 14; y += 14;
gp->gpu_perf.flip_complete = 0; ctx->last_y = y;
} }
static void show_gem_objects(cairo_t *cr) static void show_gem_objects(struct overlay_context *ctx)
{ {
char gem_objects[1024], *s, *t, *end; char gem_objects[1024], *s, *t, *end;
int len, y; int len, y;
@ -177,7 +230,7 @@ static void show_gem_objects(cairo_t *cr)
if (len <= 0) if (len <= 0)
return; return;
y = 150; y = ctx->last_y + 18;
s = gem_objects; s = gem_objects;
end = s + len - 1; end = s + len - 1;
@ -187,12 +240,14 @@ static void show_gem_objects(cairo_t *cr)
t = end; t = end;
*t = '\0'; *t = '\0';
cairo_move_to(cr, 12, y); cairo_move_to(ctx->cr, 12, y);
cairo_show_text(cr, s); cairo_show_text(ctx->cr, s);
y += 14; y += 14;
s = t+1; s = t+1;
} }
ctx->last_y = y;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@ -215,32 +270,33 @@ int main(int argc, char **argv)
init_gpu_perf(&gpu_perf, surface); init_gpu_perf(&gpu_perf, surface);
while (1) { while (1) {
cairo_t *cr; struct overlay_context ctx;
usleep(500*1000); usleep(500*1000);
cr = cairo_create(surface); ctx.cr = cairo_create(surface);
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_set_operator(ctx.cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr); cairo_paint(ctx.cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_operator(ctx.cr, CAIRO_OPERATOR_OVER);
ctx.last_y = 6;
{ {
char buf[80]; char buf[80];
cairo_text_extents_t extents; cairo_text_extents_t extents;
sprintf(buf, "%d", i++); sprintf(buf, "%d", i++);
cairo_set_source_rgb(cr, .5, .5, .5); cairo_set_source_rgb(ctx.cr, .5, .5, .5);
cairo_text_extents(cr, buf, &extents); cairo_text_extents(ctx.cr, buf, &extents);
cairo_move_to(cr, cairo_move_to(ctx.cr,
cairo_image_surface_get_width(surface)-extents.width-6, cairo_image_surface_get_width(surface)-extents.width-6,
6+extents.height); 6+extents.height);
cairo_show_text(cr, buf); cairo_show_text(ctx.cr, buf);
} }
show_gpu_top(cr, &gpu_top); show_gpu_top(&ctx, &gpu_top);
show_gpu_perf(cr, &gpu_perf); show_gpu_perf(&ctx, &gpu_perf);
show_gem_objects(cr); show_gem_objects(&ctx);
cairo_destroy(cr); cairo_destroy(ctx.cr);
overlay_show(surface); overlay_show(surface);
} }