Pondering a "threadless" VCL execution model
Dridi Boukelmoune
dridi at varni.sh
Mon Aug 24 15:39:20 UTC 2026
On Wed, Aug 19, 2026 at 11:50 AM Nils Goroll <nils.goroll at uplex.de> wrote:
>
> Hi,
>
> as many of you reading this will probably know, a colleague and me have been
> working on async I/O for Vinyl Cache for ~2 years and we are going to publish
> what we have this year.
>
> The following concerns the client side only.
>
> The model we are following so far is basically one I/O thread per core, which
> can be thought of the acceptor and waiter combined, plus doing most of the I/O.
> When VCL needs to run, the I/O thread would dispatch the req parsing and VCL FSM
> to run on a worker. This would ultimately call the transport's vtr_deliver_f,
> which would return VTR_D_DISEMBARK to leave the actual delivery with the I/O thread.
>
> The reason to switch to a worker thread is that VCL could do anything, in
> particular block on I/O, and we certainly would not want the I/O thread to halt
> neglect other work just because some vmod calls sleep(10).
>
> Now this is all good and well, except that the thread switching has a cost, and
> there are many cases where VCL never blocks. And, obviously, for these cases not
> dispatching VCL and running it in the I/O thread would be more efficient.
>
> Also, at the moment, we might still block waiting for a backend thread, but
> handling this differently does not look like a relevant problem.
>
> I have been pondering ideas on and off how we could achieve to keep the
> dedicated worker thread for VCL if/when we need it, and get rid of it where we can.
>
> The obvious way would be for vmod functions to announce "I will block" when they
> do, and core code would implement some kind of "coroutine" context swapping
> using swapcontext. This looks to me like the right solution, but it comes with
> complexity and potential pitfalls, like if Thread Local Storage is used.
>
> The other idea is just to have VMODs announce globally that they "need a thread"
> (or maybe the inverse, rather). This way, as soon as a VMOD using blocking I/O
> was imported, processing would switch from "single worker" to "dedicated
> thread". I am skeptical about this idea, because it might render the whole
> optimization useless in practice.
You could also track non-blockability at the subroutine level, such
that one may include a "utility" VCL relying on blocking VMOD code,
but not necessarily call offending subs. With dynamic subroutine
calls, assume that they are blocking, possibly if one blocking sub is
passed to a VMOD, or at least one blocking sub simply exists,
depending on what is feasible with libvcc today.
Anyway, you would find out at individual VCL steps whether you need a
dedicated worker. One blocking call would not entirely defeat such a
change.
> Now my question is if anyone has any better ideas on this?
>
> Nils
>
> --
>
> Nils Goroll (he/him)
>
> ** * * UPLEX - Nils Goroll Systemoptimierung
>
> Scheffelstraße 32
> 22301 Hamburg
>
> tel +49 40 28805731
> mob +49 170 2723133
> fax +49 40 42949753
>
> xmpp://slink@jabber.int.uplex.de/
>
> http://uplex.de/
>
> _______________________________________________
> vinyl-dev mailing list
> vinyl-dev at vinyl-cache.org
> https://vinyl-cache.org/lists/mailman/listinfo/vinyl-dev
More information about the vinyl-dev
mailing list