yimmo-wsgi¶
Developer documentation for yimmo-wsgi.
Contents
Source Layout¶
The yimmo-wsgi
source is laid out like so:
Source |
Contents |
---|---|
|
Runtime entrypoint. |
|
Common macros and type declarations. |
|
Process startup and control. |
|
Thread worker implementation. |
|
IO thread implmenentation. |
|
HTTP Exchange type and functions. |
|
Yimmo WSGI session type and functions. |
|
C implementation of the python |
|
Defines the |
|
Miscelaneous utility functions. |
|
Command line interface. |
Thread Interaction¶
Every worker process has at least two threads:
One “server thread” that does I/O using yimmo, ev, and bsat.
One or more “worker threads” that handle requests (providing the PEP3333 interface to the application).
There are some locks and some reference counting involved. It is tolerable. Don’t worry.
Queues (ymo_queue_t
) are used to ferry HTTP information between the
two. Each worker thread has two queues, one for input, one for output. Each
queue has an associated lock (pthread_mutex_t
).
The WSGI module implements an HTTP request handler callback
(ymo_http_cb_t
) which combines the request (ymo_http_request_t
)
and response (ymo_http_response_t
) into a single unit, the exchange
(ymo_wsgi_exchange_t
).
After creating the exchange, the callback locks the input queue for the worker associated with the connection, enqueueus the exchange, and signals the worker thread using a pthread condition variable.
Upon waking (or after completing the task at hand — the worker may have been
handling another request in parallel while libyimmo_http
was doing IO) the
worker thread acquires the input queue lock, dequeues the exchange, acquires the
GIL, packages the encapsulated information up as a python yimmo.Context
,
and invokes the WSGI application, passing environ
and
yimmo.Context.start_response()
.
Multi-Processing¶
If YIMMO_WSGO_NO_PROC==1
: you get the two threads described above.
If YIMMO_WSGI_NO_PROC > 1
, a “manager process” starts which spawns
YIMMO_WSGI_NO_PROC
worker processes, handles signals, and restarts failed
worker processes. This results in YIMMO_WSGI_NO_PROC + 1
total processes,
but the main process spends most of its time sleeping.
Multi-processing reduces GIL contention. Generally, the GIL is really a
non-issue. On the other hand, it does take time to acquire and can be a real
bottleneck for CPU-bound tasks. In this case, Python is the CPU-bound task —
best bet is to set YIMMO_WSGI_NO_PROC
to the number of cores you wish to
allow yimmo-wsgi
to use at the same time.
Multi-Threading¶
As stated earlier, every process has at least two threads. The
YIMMO_WSGI_NO_THREADS
environment variable is used to control the
number of worker threads per process.
Multi-threading slightly reduces the overall throughput (the threads can do
a lot in parallel, but they will still access the Python VM core serially, due
to the GIL). On the flip side, it distributes the HTTP request latency and
response times more equally — i.e. long-running requests are less likely to
block shorter requests, but some short requests will suffer here and there
from a context switch. With YIMMO_WSGI_NO_PROC < 12
you won’t notice too
much, though — if your load is consistent and requests are handled quickly —
you will definitely get your highest throughput by pinning threads to 1
.