diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-09-20 11:49:23 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2016-09-20 14:07:19 +0100 |
commit | 8d6c8191e5c7e9f06e488576af2d59e2c7669e44 (patch) | |
tree | 08f7309b4a7aacf8df770101041dd0db978a1d1e | |
parent | f0fbead9f24009c4d9900f28d4e5b3c07a93f560 (diff) |
test/present: Stress multiple threads sending present requests
At the kernel level, threads and processes are identical - they each get
a fair share of CPU time. From this we can surmise the cause of any
variation between threads and processes. If the threads are balanced
(each thread completing the same number of requests), but the processes
have unbalanced numbers, we know that X is not as fair.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | test/Makefile.am | 1 | ||||
-rw-r--r-- | test/present-speed.c | 86 |
2 files changed, 73 insertions, 14 deletions
diff --git a/test/Makefile.am b/test/Makefile.am index 7bda948e..12b5d5d8 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -50,6 +50,7 @@ stress_TESTS += \ present-speed \ present-test \ $(NULL) +present_speed_CFLAGS = ${AM_CFLAGS} -pthread endif check_PROGRAMS = $(stress_TESTS) diff --git a/test/present-speed.c b/test/present-speed.c index 1e6e48be..bcaa6238 100644 --- a/test/present-speed.c +++ b/test/present-speed.c @@ -149,6 +149,7 @@ struct buffer { #define DRI3 1 #define NOCOPY 2 +#define ASYNC 4 static void run(Display *dpy, Window win, const char *name, unsigned options) { xcb_connection_t *c = XGetXCBConnection(dpy); @@ -160,7 +161,7 @@ static void run(Display *dpy, Window win, const char *name, unsigned options) Window root; unsigned int width, height; unsigned border, depth; - unsigned present_flags = XCB_PRESENT_OPTION_ASYNC; + unsigned present_flags = 0; xcb_xfixes_region_t update = 0; int completed = 0; int queued = 0; @@ -203,6 +204,8 @@ static void run(Display *dpy, Window win, const char *name, unsigned options) buffer[n].busy = 0; list_add(&buffer[n].link, &mru); } + if (options & ASYNC) + present_flags |= XCB_PRESENT_OPTION_ASYNC; if (options & NOCOPY) { update = xcb_generate_id(c); xcb_xfixes_create_region(c, update, 0, NULL); @@ -312,20 +315,16 @@ static void run(Display *dpy, Window win, const char *name, unsigned options) XFreePixmap(dpy, buffer[n].pixmap); } - XSync(dpy, True); - if (_x_error_occurred) - abort(); - - _x_error_occurred = -1; - xcb_present_select_input(c, eid, win, 0); + xcb_discard_reply(c, xcb_present_select_input_checked(c, eid, win, 0).sequence); XSync(dpy, True); xcb_unregister_for_special_event(c, Q); test_name[0] = '\0'; if (options) { - snprintf(test_name, sizeof(test_name), "(%s%s )", + snprintf(test_name, sizeof(test_name), "(%s%s%s )", options & NOCOPY ? " no-copy" : "", - options & DRI3 ? " dri3" : ""); + options & DRI3 ? " dri3" : "", + options & ASYNC ? " async" : ""); } printf("%s%s: Completed %d presents in %.1fs, %.3fus each (%.1f FPS)\n", name, test_name, @@ -343,7 +342,56 @@ static int isqrt(int x) return i; } -static void siblings(int max_width, int max_height, int ncpus, unsigned options) +struct sibling { + pthread_t thread; + Display *dpy; + int x, y; + int width, height; + unsigned options; +}; + +static void *sibling(void *arg) +{ + struct sibling *s = arg; + XSetWindowAttributes attr = { .override_redirect = 1 }; + Window win = XCreateWindow(s->dpy, DefaultRootWindow(s->dpy), + s->x, s->y, s->width, s->height, 0, + DefaultDepth(s->dpy, DefaultScreen(s->dpy)), + InputOutput, + DefaultVisual(s->dpy, DefaultScreen(s->dpy)), + CWOverrideRedirect, &attr); + XMapWindow(s->dpy, win); + run(s->dpy, win, "sibling", s->options); + return NULL; +} + +static void siblings(Display *dpy, + int max_width, int max_height, int ncpus, unsigned options) +{ + int sq_ncpus = isqrt(ncpus); + int width = max_width / sq_ncpus; + int height = max_height/ sq_ncpus; + struct sibling s[ncpus]; + int child; + + if (ncpus <= 1) + return; + + for (child = 0; child < ncpus; child++) { + s[child].dpy = dpy; + s[child].x = (child % sq_ncpus) * width; + s[child].y = (child / sq_ncpus) * height; + s[child].width = width; + s[child].height = height; + s[child].options = options; + pthread_create(&s[child].thread, NULL, sibling, &s[child]); + } + + for (child = 0; child < ncpus; child++) + pthread_join(s[child].thread, NULL); +} + +static void cousins(int max_width, int max_height, int ncpus, unsigned options) { int sq_ncpus = isqrt(ncpus); int width = max_width / sq_ncpus; @@ -366,7 +414,7 @@ static void siblings(int max_width, int max_height, int ncpus, unsigned options) DefaultVisual(dpy, DefaultScreen(dpy)), CWOverrideRedirect, &attr); XMapWindow(dpy, win); - run(dpy, win, "sibling", options); + run(dpy, win, "cousin", options); } } @@ -580,7 +628,7 @@ static void loop(Display *dpy, XRRScreenResources *res, unsigned options) DefaultVisual(dpy, DefaultScreen(dpy)), CWOverrideRedirect, &attr); XCompositeRedirectWindow(dpy, win, CompositeRedirectManual); - damage = XDamageCreate(dpy, win, XDamageReportRawRectangles); + damage = XDamageCreate(dpy, win, XDamageReportNonEmpty); XMapWindow(dpy, win); XSync(dpy, True); if (!_x_error_occurred) @@ -601,16 +649,21 @@ static void loop(Display *dpy, XRRScreenResources *res, unsigned options) XDestroyWindow(dpy, win); XSync(dpy, True); - siblings(mode->width, mode->height, + siblings(dpy, mode->width, mode->height, sysconf(_SC_NPROCESSORS_ONLN), options); + cousins(mode->width, mode->height, + sysconf(_SC_NPROCESSORS_ONLN), + options); + XRRSetCrtcConfig(dpy, res, output->crtcs[c], CurrentTime, 0, 0, None, RR_Rotate_0, NULL, 0); } XRRFreeOutputInfo(output); } + } int main(void) @@ -620,6 +673,8 @@ int main(void) XRRCrtcInfo **original_crtc; int i; + XInitThreads(); + dpy = XOpenDisplay(NULL); if (dpy == NULL) return 77; @@ -649,10 +704,13 @@ int main(void) 0, 0, None, RR_Rotate_0, NULL, 0); loop(dpy, res, 0); + loop(dpy, res, ASYNC); if (has_xfixes(dpy)) loop(dpy, res, NOCOPY); - if (has_dri3(dpy)) + if (has_dri3(dpy)) { loop(dpy, res, DRI3); + loop(dpy, res, DRI3 | ASYNC); + } for (i = 0; i < res->ncrtc; i++) XRRSetCrtcConfig(dpy, res, res->crtcs[i], CurrentTime, |