mirror of
https://github.com/tiagovignatti/intel-gpu-tools.git
synced 2025-06-10 17:36:11 +00:00
overlay: Parse gem objects
Condense the information and begin graphing it. Remaining todo for memory is to measure bind/evict flux, and perhaps clflush. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
de2c97b27f
commit
e1ed5606c6
@ -1,19 +1,134 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gem-objects.h"
|
||||
|
||||
int gem_objects_update(char *buf, int buflen)
|
||||
/* /sys/kernel/debug/dri/0/i915_gem_objects:
|
||||
* 46 objects, 20107264 bytes
|
||||
* 42 [42] objects, 15863808 [15863808] bytes in gtt
|
||||
* 0 [0] active objects, 0 [0] bytes
|
||||
* 42 [42] inactive objects, 15863808 [15863808] bytes
|
||||
* 0 unbound objects, 0 bytes
|
||||
* 3 purgeable objects, 4456448 bytes
|
||||
* 30 pinned mappable objects, 3821568 bytes
|
||||
* 1 fault mappable objects, 3145728 bytes
|
||||
* 2145386496 [536870912] gtt total
|
||||
*
|
||||
* Xorg: 35 objects, 16347136 bytes (0 active, 12103680 inactive, 0 unbound)
|
||||
*/
|
||||
|
||||
int gem_objects_init(struct gem_objects *obj)
|
||||
{
|
||||
int fd, len = -1;
|
||||
char buf[8192], *b;
|
||||
int fd, len;
|
||||
|
||||
memset(obj, 0, sizeof(*obj));
|
||||
|
||||
fd = open("/sys/kernel/debug/dri/0/i915_gem_objects", 0);
|
||||
if (fd >= 0) {
|
||||
len = read(fd, buf, buflen-1);
|
||||
if (len >= 0)
|
||||
buf[len] = '\0';
|
||||
close(fd);
|
||||
if (fd < 0)
|
||||
return errno;
|
||||
len = read(fd, buf, sizeof(buf)-1);
|
||||
close(fd);
|
||||
|
||||
if (len < 0)
|
||||
return EIO;
|
||||
|
||||
b = strstr(buf, "gtt total");
|
||||
if (b == NULL)
|
||||
return EIO;
|
||||
|
||||
while (*b != '\n')
|
||||
b--;
|
||||
|
||||
sscanf(b, "%ld [%ld]",
|
||||
&obj->max_gtt, &obj->max_aperture);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void insert_sorted(struct gem_objects *obj,
|
||||
struct gem_objects_comm *comm)
|
||||
{
|
||||
struct gem_objects_comm *next, **prev;
|
||||
|
||||
for (prev = &obj->comm; (next = *prev) != NULL; prev = &next->next)
|
||||
if (comm->bytes > next->bytes)
|
||||
break;
|
||||
|
||||
comm->next = *prev;
|
||||
*prev = comm;
|
||||
}
|
||||
|
||||
int gem_objects_update(struct gem_objects *obj)
|
||||
{
|
||||
char buf[8192], *b;
|
||||
struct gem_objects_comm *comm;
|
||||
struct gem_objects_comm *freed;
|
||||
int fd, len, ret;
|
||||
|
||||
freed = obj->comm;
|
||||
obj->comm = NULL;
|
||||
|
||||
fd = open("/sys/kernel/debug/dri/0/i915_gem_objects", 0);
|
||||
if (fd < 0) {
|
||||
ret = errno;
|
||||
goto done;
|
||||
}
|
||||
len = read(fd, buf, sizeof(buf)-1);
|
||||
close(fd);
|
||||
|
||||
if (len < 0) {
|
||||
ret = EIO;
|
||||
goto done;
|
||||
}
|
||||
|
||||
return len;
|
||||
buf[len] = '\0';
|
||||
while (buf[--len] == '\n')
|
||||
buf[len] = '\0';
|
||||
|
||||
b = buf;
|
||||
|
||||
sscanf(b, "%d objects, %ld bytes",
|
||||
&obj->total_count, &obj->total_bytes);
|
||||
|
||||
b = strchr(b, '\n');
|
||||
sscanf(b, "%*d [%*d] objects, %ld [%ld] bytes in gtt",
|
||||
&obj->total_gtt, &obj->total_aperture);
|
||||
|
||||
ret = 0;
|
||||
b = strchr(b, ':');
|
||||
if (b == NULL)
|
||||
goto done;
|
||||
|
||||
while (*b != '\n')
|
||||
b--;
|
||||
|
||||
do {
|
||||
comm = freed;
|
||||
if (comm)
|
||||
freed = comm->next;
|
||||
else
|
||||
comm = malloc(sizeof(*comm));
|
||||
if (comm == NULL)
|
||||
break;
|
||||
|
||||
/* Xorg: 35 objects, 16347136 bytes (0 active, 12103680 inactive, 0 unbound) */
|
||||
sscanf(++b, "%256s %u objects, %lu bytes",
|
||||
comm->name, &comm->count, &comm->bytes);
|
||||
|
||||
insert_sorted(obj, comm);
|
||||
} while ((b = strchr(b, '\n')) != NULL);
|
||||
|
||||
done:
|
||||
while (freed) {
|
||||
comm = freed;
|
||||
freed = comm->next;
|
||||
free(comm);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1 +1,17 @@
|
||||
int gem_objects_update(char *buf, int buflen);
|
||||
#include <stdint.h>
|
||||
|
||||
struct gem_objects {
|
||||
uint64_t total_bytes;
|
||||
uint32_t total_count;
|
||||
uint64_t total_gtt, total_aperture;
|
||||
uint64_t max_gtt, max_aperture;
|
||||
struct gem_objects_comm {
|
||||
struct gem_objects_comm *next;
|
||||
char name[256];
|
||||
uint64_t bytes;
|
||||
uint32_t count;
|
||||
} *comm;
|
||||
};
|
||||
|
||||
int gem_objects_init(struct gem_objects *obj);
|
||||
int gem_objects_update(struct gem_objects *obj);
|
||||
|
@ -435,33 +435,76 @@ static void show_gpu_freq(struct overlay_context *ctx, struct overlay_gpu_freq *
|
||||
ctx->last_y += 112;
|
||||
}
|
||||
|
||||
static void show_gem_objects(struct overlay_context *ctx)
|
||||
{
|
||||
char gem_objects[1024], *s, *t, *end;
|
||||
int len, y;
|
||||
struct overlay_gem_objects {
|
||||
struct gem_objects gem_objects;
|
||||
struct chart aperture;
|
||||
struct chart gtt;
|
||||
int error;
|
||||
};
|
||||
|
||||
len = gem_objects_update(gem_objects, sizeof(gem_objects));
|
||||
if (len <= 0)
|
||||
static void init_gem_objects(struct overlay_gem_objects *go,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
go->error = gem_objects_init(&go->gem_objects);
|
||||
if (go->error)
|
||||
return;
|
||||
|
||||
y = ctx->last_y + 18;
|
||||
chart_init(&go->aperture, "aperture", 120);
|
||||
chart_set_size(&go->aperture,
|
||||
cairo_image_surface_get_width(surface)-24,
|
||||
100);
|
||||
chart_set_stroke_rgba(&go->aperture, 0.75, 0.25, 0.50, 1.);
|
||||
chart_set_mode(&go->aperture, CHART_STROKE);
|
||||
chart_set_range(&go->aperture, 0, go->gem_objects.max_gtt);
|
||||
|
||||
s = gem_objects;
|
||||
end = s + len - 1;
|
||||
while (s < end) {
|
||||
t = strchr(s, '\n');
|
||||
if (t == NULL)
|
||||
t = end;
|
||||
*t = '\0';
|
||||
chart_init(&go->gtt, "gtt", 120);
|
||||
chart_set_size(&go->gtt,
|
||||
cairo_image_surface_get_width(surface)-24,
|
||||
100);
|
||||
chart_set_fill_rgba(&go->gtt, 0.25, 0.75, 0.50, 1.);
|
||||
chart_set_mode(&go->gtt, CHART_FILL);
|
||||
chart_set_range(&go->gtt, 0, go->gem_objects.max_gtt);
|
||||
}
|
||||
|
||||
static void show_gem_objects(struct overlay_context *ctx, struct overlay_gem_objects *go)
|
||||
{
|
||||
struct gem_objects_comm *comm;
|
||||
char buf[160];
|
||||
int y;
|
||||
|
||||
if (go->error == 0)
|
||||
go->error = gem_objects_update(&go->gem_objects);
|
||||
if (go->error)
|
||||
return;
|
||||
|
||||
chart_add_sample(&go->gtt, go->gem_objects.total_gtt);
|
||||
chart_add_sample(&go->aperture, go->gem_objects.total_aperture);
|
||||
|
||||
y = ctx->last_y + 6;
|
||||
|
||||
chart_set_position(&go->gtt, 12, y);
|
||||
chart_set_position(&go->aperture, 12, y);
|
||||
|
||||
chart_draw(&go->gtt, ctx->cr);
|
||||
chart_draw(&go->aperture, ctx->cr);
|
||||
|
||||
sprintf(buf, "Total: %ld bytes, %d objects",
|
||||
go->gem_objects.total_bytes, go->gem_objects.total_count);
|
||||
cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
|
||||
cairo_move_to(ctx->cr, 12, y);
|
||||
cairo_show_text(ctx->cr, buf);
|
||||
y += 14;
|
||||
|
||||
for (comm = go->gem_objects.comm; comm; comm = comm->next) {
|
||||
sprintf(buf, " %s: %ld bytes, %d objects",
|
||||
comm->name, comm->bytes, comm->count);
|
||||
cairo_set_source_rgba(ctx->cr, 1, 1, 1, 1);
|
||||
cairo_move_to(ctx->cr, 12, y);
|
||||
cairo_show_text(ctx->cr, s);
|
||||
cairo_show_text(ctx->cr, buf);
|
||||
y += 14;
|
||||
|
||||
s = t+1;
|
||||
}
|
||||
|
||||
ctx->last_y = y;
|
||||
ctx->last_y += 112;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@ -470,6 +513,7 @@ int main(int argc, char **argv)
|
||||
struct overlay_gpu_top gpu_top;
|
||||
struct overlay_gpu_perf gpu_perf;
|
||||
struct overlay_gpu_freq gpu_freq;
|
||||
struct overlay_gem_objects gem_objects;
|
||||
int i = 0;
|
||||
|
||||
if (argc > 1) {
|
||||
@ -484,6 +528,7 @@ int main(int argc, char **argv)
|
||||
init_gpu_top(&gpu_top, surface);
|
||||
init_gpu_perf(&gpu_perf, surface);
|
||||
init_gpu_freq(&gpu_freq, surface);
|
||||
init_gem_objects(&gem_objects, surface);
|
||||
|
||||
while (1) {
|
||||
struct overlay_context ctx;
|
||||
@ -511,7 +556,7 @@ int main(int argc, char **argv)
|
||||
show_gpu_top(&ctx, &gpu_top);
|
||||
show_gpu_perf(&ctx, &gpu_perf);
|
||||
show_gpu_freq(&ctx, &gpu_freq);
|
||||
show_gem_objects(&ctx);
|
||||
show_gem_objects(&ctx, &gem_objects);
|
||||
|
||||
cairo_destroy(ctx.cr);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user