overlay: Track requests per-process
authorChris Wilson <chris@chris-wilson.co.uk>
Sat, 17 Aug 2013 19:04:11 +0000 (20:04 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Sat, 17 Aug 2013 19:04:11 +0000 (20:04 +0100)
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
overlay/gpu-perf.c
overlay/gpu-perf.h
overlay/overlay.c

index 59176f9..8717437 100644 (file)
@@ -30,6 +30,8 @@ struct sample_event {
        uint64_t time;
        uint64_t id;
        uint32_t raw_size;
+       uint32_t raw_hdr0;
+       uint32_t raw_hdr1;
        uint32_t raw[0];
 };
 
@@ -117,7 +119,6 @@ static int perf_tracepoint_open(struct gpu_perf *gp,
 
                if (gp->nr_events)
                        ioctl(fd[n], PERF_EVENT_IOC_SET_OUTPUT, gp->fd[n]);
-
        }
 
        gp->nr_events++;
@@ -149,8 +150,53 @@ err:
        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)
 {
+       printf ("seqno_start\n");
        return 0;
 }
 
@@ -171,9 +217,9 @@ void gpu_perf_init(struct gpu_perf *gp, unsigned flags)
        gp->nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
        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)
                perf_tracepoint_open(gp, "i915", "i915_gem_ring_dispatch", seqno_start);
-
        perf_tracepoint_open(gp, "i915", "i915_flip_complete", flip_complete);
 
        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];
                const uint8_t *data;
                uint64_t head, tail;
+               int wrap = 0;
 
                tail = mmap->data_tail;
                head = mmap->data_head;
                rmb();
 
-               if (head < tail)
+               if (head < tail) {
+                       wrap = 1;
+                       tail &= mask;
+                       head &= mask;
                        head += size;
+               }
 
                data = (uint8_t *)mmap + gp->page_size;
                while (head - tail >= sizeof (struct perf_event_header)) {
@@ -259,7 +310,9 @@ int gpu_perf_update(struct gpu_perf *gp)
                        tail += header->size;
                }
 
-               mmap->data_tail = tail & mask;
+               if (wrap)
+                       tail &= mask;
+               mmap->data_tail = tail;
        }
 
        free(buffer);
index 6a3e00d..95debc9 100644 (file)
@@ -12,6 +12,12 @@ struct gpu_perf {
        } *sample;
 
        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);
index c079004..0bd5792 100644 (file)
@@ -1,4 +1,3 @@
-#include <X11/Xlib.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <cairo.h>
@@ -7,6 +6,7 @@
 #include <stdbool.h>
 #include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <errno.h>
 
 #include "overlay.h"
@@ -52,6 +52,11 @@ static void overlay_hide(cairo_surface_t *surface)
 }
 #endif
 
+struct overlay_context {
+       cairo_t *cr;
+       int last_y;
+};
+
 struct overlay_gpu_top {
        struct gpu_top gpu_top;
        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;
 
@@ -109,16 +114,16 @@ static void show_gpu_top(cairo_t *cr, struct overlay_gpu_top *gt)
                if (update)
                        chart_add_sample(&gt->wait[n],
                                         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++) {
                if (update)
                        chart_add_sample(&gt->busy[n],
                                         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;
        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",
                                       gt->gpu_top.ring[n].u.u.sema);
 
-               cairo_move_to(cr, 12, y);
-               cairo_show_text(cr, txt);
+               cairo_move_to(ctx->cr, 12, y);
+               cairo_show_text(ctx->cr, txt);
                y += 14;
        }
+
+       ctx->last_y = 112;
 }
 
 struct overlay_gpu_perf {
@@ -146,29 +153,75 @@ struct overlay_gpu_perf {
 };
 
 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);
 }
 
-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];
-       int y;
+       int y, n;
 
        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);
-       cairo_move_to(cr, 12, y);
-       cairo_show_text(cr, buf);
+       gp->gpu_perf.flip_complete = 0;
+       cairo_move_to(ctx->cr, 12, y);
+       cairo_show_text(ctx->cr, buf);
        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;
        int len, y;
@@ -177,7 +230,7 @@ static void show_gem_objects(cairo_t *cr)
        if (len <= 0)
                return;
 
-       y = 150;
+       y = ctx->last_y + 18;
 
        s = gem_objects;
        end = s + len - 1;
@@ -187,12 +240,14 @@ static void show_gem_objects(cairo_t *cr)
                        t = end;
                *t = '\0';
 
-               cairo_move_to(cr, 12, y);
-               cairo_show_text(cr, s);
+               cairo_move_to(ctx->cr, 12, y);
+               cairo_show_text(ctx->cr, s);
                y += 14;
 
                s = t+1;
        }
+
+       ctx->last_y = y;
 }
 
 int main(int argc, char **argv)
@@ -215,32 +270,33 @@ int main(int argc, char **argv)
        init_gpu_perf(&gpu_perf, surface);
 
        while (1) {
-               cairo_t *cr;
+               struct overlay_context ctx;
 
                usleep(500*1000);
 
-               cr = cairo_create(surface);
-               cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
-               cairo_paint(cr);
-               cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+               ctx.cr = cairo_create(surface);
+               cairo_set_operator(ctx.cr, CAIRO_OPERATOR_CLEAR);
+               cairo_paint(ctx.cr);
+               cairo_set_operator(ctx.cr, CAIRO_OPERATOR_OVER);
+               ctx.last_y = 6;
 
                {
                        char buf[80];
                        cairo_text_extents_t extents;
                        sprintf(buf, "%d", i++);
-                       cairo_set_source_rgb(cr, .5, .5, .5);
-                       cairo_text_extents(cr, buf, &extents);
-                       cairo_move_to(cr,
+                       cairo_set_source_rgb(ctx.cr, .5, .5, .5);
+                       cairo_text_extents(ctx.cr, buf, &extents);
+                       cairo_move_to(ctx.cr,
                                      cairo_image_surface_get_width(surface)-extents.width-6,
                                      6+extents.height);
-                       cairo_show_text(cr, buf);
+                       cairo_show_text(ctx.cr, buf);
                }
 
-               show_gpu_top(cr, &gpu_top);
-               show_gpu_perf(cr, &gpu_perf);
-               show_gem_objects(cr);
+               show_gpu_top(&ctx, &gpu_top);
+               show_gpu_perf(&ctx, &gpu_perf);
+               show_gem_objects(&ctx);
 
-               cairo_destroy(cr);
+               cairo_destroy(ctx.cr);
 
                overlay_show(surface);
        }