Am 06.02.2014 20:24, schrieb Kelet:
Hello,
I'm new to both asynchronous i/o and fibers. I'm trying to grok on a high-level how fiber scheduling works in vibe-d.
As I understand,
Fiber
s in DLang must becall
ed, and then somewhere within theFiber
it mustyield
or naturally end if it wants to relinquish control back to the caller. The idea is that aFiber
scheduler could take some aggregate ofFiber
s and run them in an efficient way.I'm interested in studying vibe-d's approach to this fiber scheduling problem. However, I'm a bit hazy even after reading the source code – it seems to be above my head.
My understanding, which is most definitely flawed (feel free to correct!), is that
- There is a queue of
Fiber
s (or some derivative ofFiber
s)- If a
Fiber
issues a vibesleep()
, a driver timer (say libevent) is created, and during the sleep time, events are processed (the event loop goes through some iterations). When the timer goes off, theFiber
is called again and resumes. Perhaps some other blocking operations are similar.- If a
Fiber
yields or ends, events are processed and the nextFiber
in the queue iscall
ed. If it was ayield
, it is placed in the back of the queue. If it ended, it is removed from the queue.- Each Thread probably has its own
Fiber
scheduler.
Sounds all about right.
And some things I can't figure out:
- When and where are the new
Fiber
s added to theFiber
'queue'?
They are basically added only when yield()
is explicitly called by the
user. As long as only blocking operations cause a task/fiber to yield,
it's the OS/event loop which determines which fiber will be resumed in
which order.
- Why is there so much timer code in the drivers? I can't think of much use except for making a timer for when
Fiber
s sleep.
The code guarantees that each timer uses up a minimum amount of memory
(only one OS timer is used), so that it can be guaranteed that timers
are light-weight and can be used safely in large numbers.
- Does each
Thread
have its ownFiber
queue so to speak?
Yes, also, as Stefan already said, a fiber is always exclusive to the
thread in which it was created, so fibers are never transferred between
threads. This is necessary to not break D's threading model (shared
and thread-local storage).
- How are
Fiber
s balanced betweenThread
s when worker threads are enabled?
It depends. For the normal runWorkerTask
, the first worker thread that
becomes idle will pick up the task an process it, so that usually all
threads will have a similar workload. In case of thread-distributed HTTP
request processing (HTTPServerOption.distribute
), it's again the
OS/event loop which decides what thread will accept each incoming
connection.
Now obviously I'm not looking for an exacting in-depth technical description, just a high-level description or psuedocode with the major points, because I feel like I'm really missing out on some fundamental understanding. I'm currently more interested in fiber scheduling because as it stands, I know I'm missing some significant chunks.
Regards,
Kelet
A final note that hasn't been mentioned, each fiber can be reused for
multiple tasks in sequence. So whenever a task has finished, the
corresponding fiber will be yielded and then can be reused later for
another task.
In the end the concept is really quite simple. But I'll also write up a
small article about how this works (it has been planned for a long
time), but the time currently doesn't really permit that and there are
still a few unknowns that I'd like to carve out first (mostly w.r.t
WinRT) before finally fully committing to a certain model (it's already
99% certain, though).