diff options
author | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
commit | 3562e78743202e43aec8727005182a2558117eca (patch) | |
tree | 8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xorg-server/doc/smartsched | |
download | vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2 vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip |
Checked in the following released items:
xkeyboard-config-1.4.tar.gz
ttf-bitstream-vera-1.10.tar.gz
font-alias-1.0.1.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sony-misc-1.0.0.tar.gz
font-schumacher-misc-1.0.0.tar.gz
font-mutt-misc-1.0.0.tar.gz
font-misc-misc-1.0.0.tar.gz
font-misc-meltho-1.0.0.tar.gz
font-micro-misc-1.0.0.tar.gz
font-jis-misc-1.0.0.tar.gz
font-isas-misc-1.0.0.tar.gz
font-dec-misc-1.0.0.tar.gz
font-daewoo-misc-1.0.0.tar.gz
font-cursor-misc-1.0.0.tar.gz
font-arabic-misc-1.0.0.tar.gz
font-winitzki-cyrillic-1.0.0.tar.gz
font-misc-cyrillic-1.0.0.tar.gz
font-cronyx-cyrillic-1.0.0.tar.gz
font-screen-cyrillic-1.0.1.tar.gz
font-xfree86-type1-1.0.1.tar.gz
font-adobe-utopia-type1-1.0.1.tar.gz
font-ibm-type1-1.0.0.tar.gz
font-bitstream-type1-1.0.0.tar.gz
font-bitstream-speedo-1.0.0.tar.gz
font-bh-ttf-1.0.0.tar.gz
font-bh-type1-1.0.0.tar.gz
font-bitstream-100dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz
font-bh-100dpi-1.0.0.tar.gz
font-adobe-utopia-100dpi-1.0.1.tar.gz
font-adobe-100dpi-1.0.0.tar.gz
font-util-1.0.1.tar.gz
font-bitstream-75dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz
font-adobe-utopia-75dpi-1.0.1.tar.gz
font-bh-75dpi-1.0.0.tar.gz
bdftopcf-1.0.1.tar.gz
font-adobe-75dpi-1.0.0.tar.gz
mkfontscale-1.0.6.tar.gz
openssl-0.9.8k.tar.gz
bigreqsproto-1.0.2.tar.gz
xtrans-1.2.2.tar.gz
resourceproto-1.0.2.tar.gz
inputproto-1.4.4.tar.gz
compositeproto-0.4.tar.gz
damageproto-1.1.0.tar.gz
zlib-1.2.3.tar.gz
xkbcomp-1.0.5.tar.gz
freetype-2.3.9.tar.gz
pthreads-w32-2-8-0-release.tar.gz
pixman-0.12.0.tar.gz
kbproto-1.0.3.tar.gz
evieext-1.0.2.tar.gz
fixesproto-4.0.tar.gz
recordproto-1.13.2.tar.gz
randrproto-1.2.2.tar.gz
scrnsaverproto-1.1.0.tar.gz
renderproto-0.9.3.tar.gz
xcmiscproto-1.1.2.tar.gz
fontsproto-2.0.2.tar.gz
xextproto-7.0.3.tar.gz
xproto-7.0.14.tar.gz
libXdmcp-1.0.2.tar.gz
libxkbfile-1.0.5.tar.gz
libfontenc-1.0.4.tar.gz
libXfont-1.3.4.tar.gz
libX11-1.1.5.tar.gz
libXau-1.0.4.tar.gz
libxcb-1.1.tar.gz
xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xorg-server/doc/smartsched')
-rw-r--r-- | xorg-server/doc/smartsched | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/xorg-server/doc/smartsched b/xorg-server/doc/smartsched new file mode 100644 index 000000000..057a759fd --- /dev/null +++ b/xorg-server/doc/smartsched @@ -0,0 +1,204 @@ + Client Scheduling in X + Keith Packard + SuSE + 10/28/99 + +History: + +Since the original X server was written at Digital in 1987, the OS and DIX +layers shared responsibility for scheduling the order to service +client requests. The original design was simplistic; under the maximum +first make it work, then make it work well, this was a good idea. Now +that we have a bit more experience with X applications, it's time to +rethink the design. + +The basic dispatch loop in DIX looks like: + + for (;;) + { + nready = WaitForSomething (...); + while (nready--) + { + isItTimeToYield = FALSE; + while (!isItTimeToYield) + { + if (!ReadRequestFromClient (...)) + break; + (execute request); + } + } + } + +WaitForSomething looks like: + + for (;;) + if (ANYSET (ClientsWithInput)) + return popcount (ClientsWithInput); + select (...) + compute clientsReadable from select result; + return popcount (clientsReadable) + } + +ReadRequestFromClient looks like: + + if (!fullRequestQueued) + { + read (); + if (!fullRequestQueued) + { + remove from ClientsWithInput; + timesThisConnection = 0; + return 0; + } + } + if (twoFullRequestsQueued) + add to ClientsWithInput; + + if (++timesThisConnection >= 10) + { + isItTimeToYield = TRUE; + timesThisConnection = 0; + } + return 1; + +Here's what happens in this code: + +With a single client executing a stream of requests: + + A client sends a packet of requests to the server. + + WaitForSomething wakes up from select and returns that client + to Dispatch + + Dispatch calls ReadRequestFromClient which reads a buffer (4K) + full of requests from the client + + The server executes requests from this buffer until it emptys, + in two stages -- 10 requests at a time are executed in the + inner Dispatch loop, a buffer full of requests are executed + because WaitForSomething immediately returns if any clients + have complete requests pending in their input queues. + + When the buffer finally emptys, the next call to ReadRequest + FromClient will return zero and Dispatch will go back to + WaitForSomething; now that the client has no requests pending, + WaitForSomething will block in select again. If the client + is active, this select will immediately return that client + as ready to read. + +With multiple clients sending streams of requests, the sequence +of operations is similar, except that ReadRequestFromClient will +set isItTimeToYield after each 10 requests executed causing the +server to round-robin among the clients with available requests. + +It's important to realize here that any complete requests which have been +read from clients will be executed before the server will use select again +to discover input from other clients. A single busy client can easily +monopolize the X server. + +So, the X server doesn't share well with clients which are more interactive +in nature. + +The X server executes at most a buffer full of requests before again heading +into select; ReadRequestFromClient causes the server to yield when the +client request buffer doesn't contain a complete request. When +that buffer is executed quickly, the server spends a lot of time +in select discovering that the same client again has input ready. Thus +the server also runs busy clients less efficiently than is would be +possible. + +What to do. + +There are several things evident from the above discussion: + + 1 The server has a poor metric for deciding how much work it + should do at one time on behalf of a particular client. + + 2 The server doesn't call select often enough to detect less + aggressive clients in the face of busy clients, especially + when those clients are executing slow requests. + + 3 The server calls select too often when executing fast requests. + + 4 Some priority scheme is needed to keep interactive clients + responding to the user. + +And, there are some assumptions about how X applications work: + + 1 Each X request is executed relatively quickly; a request-granularity + is good enough for interactive response almost all of the time. + + 2 X applications receiving mouse/keyboard events are likely to + warrant additional attention from the X server. + +Instead of a request-count metric for work, a time-based metric should be +used. The server should select a reasonable time slice for each client +and execute requests for the entire timeslice before yielding to +another client. + +Instead of returning immediately from WaitForSomething if clients have +complete requests queued, the server should go through select each +time and gather as many ready clients as possible. This involves +polling instead of blocking and adding the ClientsWithInput to +clientsReadable after the select returns. + +Instead of yielding when the request buffer is empty for a particular +client, leave the yielding to the upper level scheduling and allow +the server to try and read again from the socket. If the client +is busy, another buffer full of requests will already be waiting +to be delivered thus avoiding the call through select and the +additional overhead in WaitForSomething. + +Finally, the dispatch loop should not simply execute requests from the +first available client, instead each client should be prioritized with +busy clients penalized and clients receiving user events praised. + +How it's done: + +Polling the current time of day from the OS is too expensive to +be done at each request boundary, so instead an interval timer is +set allowing the server to track time changes by counting invocations +of the related signal handler. Instead of using the wall time for +this purpose, the process CPU time is used instead. This serves +two purposes -- first, it allows the server to consume no CPU cycles +when idle, second it avoids conflicts with SIGALRM usage in other +parts of the server code. It's not without problems though; other +CPU intensive processes on the same machine can reduce interactive +response time within the X server. The dispatch loop can now +calculate an approximate time value using the number of signals +received. The granularity of the timer sets the scheduling jitter, +at 20ms it's only occasionally noticeable. + +The changes to WaitForSomething and ReadRequestFromClient are +straightforward, adjusting when select is called and avoiding +setting isItTimeToYield too often. + +The dispatch loop changes are more extensive, now instead of +executing requests from all available clients, a single client +is chosen after each call to WaitForSomething, requests are +executed for that client and WaitForSomething is called again. + +Each client is assigned a priority, the dispatch loop chooses the +client with the highest priority to execute. Priorities are +updated in three ways: + + 1. Clients which consume their entire slice are penalized + by having their priority reduced by one until they + reach some minimum value. + + 2. Clients which have executed no requests for some time + are praised by having their priority raised until they + return to normal priority. + + 3. Clients which receive user input are praised by having + their priority rased until they reach some maximal + value, above normal priority. + +The effect of these changes is to both improve interactive application +response and benchmark numbers at the same time. + + + + + +$XFree86: $ |