Given the right mix of clients competing for server time, it is possible for some of those clients to be starved. In a CPU bound system, executing clients consume their entire ScheduleSlice and are demoted for being busy. These clients then may block waiting for a reply from the XServer freeing up CPU time such that the next client will complete its task within the ScheduleSlice and not be demoted. In this manner, we progressively starve more and more clients until we have sufficient CPU time to execute the remaining ones, and under the right conditions we will have a set that can remain permanently busy, and a set that are blocked.
A simple example is to execute 16 identical copies of a rendering benchmark and measure the standard deviation in the number of frames they are able to complete within 60 seconds. (The benchmark uses client-side throttling and so frees up CPU timeslices whilst waiting for a GetImage reply after each frame. The benchmark doesn't listen to input events and so does not receive the priority boost used to reduce input latency.) Using dumbSched: 57.0 +- 0.4 fps Using smartSched: 66.4 +- 9.8 fps After patching: 65.2 +- 1.2 fps More importantly, given the right conditions it is very easy to starve clients completely. That starvation is prevented by this patch. The solution employed here is to undo the busy demotion after a period of idleness. Currently the idle boost is applied only once for a fresh client when it becomes selectable. The change is to apply that boost for all clients that remain ready for the entire duration of idle timeslice - eventually these old busy clients will be promoted sufficiently to be granted a ScheduleSlice. Signed-off-by: Chris Wilson <[email protected]> --- dix/dispatch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dix/dispatch.c b/dix/dispatch.c index 4fecfea..0da37ae 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -259,12 +259,12 @@ SmartScheduleClient(int *clientReady, int nready) for (i = 0; i < nready; i++) { client = clientReady[i]; pClient = clients[client]; - /* Praise clients which are idle */ + /* Praise clients which have been idle */ if ((now - pClient->smart_check_tick) >= idle) { if (pClient->smart_priority < 0) pClient->smart_priority++; + pClient->smart_check_tick = now; } - pClient->smart_check_tick = now; /* check priority to select best client */ robin = -- 1.8.4.rc3 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
