One of the benefits of providing preemption at the language level is
that you are not restricted to using timers as the metric for
suspending a process (although this is an option). You can also
preempt after a process has performed a number of operations.

One way to do this is for the compiler to inject yield hints for tasks
executed as a green thread. These suggest to the scheduler that now is
a decent time to suspend the process and if appropriate, the scheduler
will do so. However, these hints will need to be very lightweight and
regularly frequent. Again, the point of this feature would be to
increase safety and reduce tail latency, not overall throughput. I
would make this an option. This is more or less how the Erlang
scheduler works and why it is, to date, the only VM I am aware of that
optimizes for latency.

For handling I/O, obviously you cannot inject yields directly in an
I/O task. Better is to have an async task pool. If task A wishes to do
some I/O, it fires a message to an async task and periodically checks
if the task has returned. The checking can be finished immediately if
it is something quick, but if not, task A can hint to suspend itself
as above.

In the scheme I am mentioning above, I would propose several
configurable parameters.

1. Choice of scheduling algorithm to use.
2. Yield frequency (lower means lower tail latencies at the expense of
mean response time and vice versa)
3. Async task pool max size. Bounds the amount of I/O tasks that can
be run concurrently.

I should mention that as a caveat, I have never implemented a
scheduler before so I may be wildly off the mark. The bulk of my
experience (in non-scripting languages) is in C++, Haskell, and Erlang
so much of my thinking is borrowed from how things are thought of in
those universes. I will attempt to review some of the literature today
and see what I can come up with. Again, it would be great if the dev
team could chime in with their thoughts on this.

Cheers,
J

On Sat, Apr 12, 2014 at 4:07 AM, Matthieu Monrocq
<[email protected]> wrote:
> Hello,
>
> As far as I know in Rust, a thread (green or not) that enters an infinite
> loop without I/O is forever stuck. The only available option to stop it is
> to have the OS kill the process (CTRL+C).
>
> In my day job, all our servers services are time-bounded and any that
> exceeds its time bound is killed. To do so requires one process per service
> for the exact same reason than Rust, which has the unfortunate effect of
> requiring a large memory footprint because "utility threads" (such as
> timers, and notably the watch-dog timer) are replicated in each and every
> process.
>
> The most common source of time-slips are disk accesses and database accesses
> which is covered by Rust under I/O, however I've already seen infinite loops
> (or very long ones) and there seems to be no way to protect against those.
> Of course one could recommend that such loops check a flag or something, but
> if we knew those loops were going to "diverge" we would fix them, not
> instrument them.
>
>
> I was hoping that with Rust (which already rids us of good-bye to dangling
> pointers & data races) we could move toward a single process with a lot of
> concurrent (green) tasks for better efficiency and ease of development,
> however the latter seems unattainable because of infinite loops or otherwise
> diverging code right now.
>
>
> I would thus also appreciate if anybody had an idea how to preempt a
> misbehaving task, even if the only option is to trigger this task failure;
> the goal at this point is to salvage the system without losing the current
> workload.
>
> -- Matthieu
>
>
>
> On Sat, Apr 12, 2014 at 11:04 AM, Jeremy Ong <[email protected]> wrote:
>>
>> I am considering authoring a webserver (think nginx, apache, cowboy,
>> etc) in Rust. From a user point of view, mapping tasks (green) to web
>> requests makes the most sense as the tasks could be long running,
>> perform their own I/O, sessions, or what have you. It would also allow
>> the user to do per-request in memory caching.
>>
>> My main concern is obviously the cooperative scheduler. Given that the
>> mantra of Rust seems to be safety, I'm curious about how feasible it
>> would be to provide the option for task safety as well. Preemptive
>> scheduling provides two things:
>>
>> 1. If preemption is used aggressively, the user can opt for a lower
>> latency system (a la Erlang style round robin preemptive scheduling)
>> 2. Preemption of any sort can be used as a safety net to isolate bugs
>> or blocks in tasks for long running systems, or at least mitigate
>> damage until the developer intervenes.
>>
>> I noticed in issue 5731[1] on the repo, it was pointed out that this
>> was possible, albeit difficult. The issue was closed with a comment
>> that the user should use OS threads instead. I really think this
>> misses the point as it no longer allows preemption on a smaller
>> granularity scale. Could any devs chime in on the scope and difficulty
>> of this project? Could any users/devs chime in on any of the points
>> above?
>>
>> tl;dr I think preemptive scheduling is a must for safe concurrency in
>> long running executables at the bottom of the stack. Opinions?
>>
>>
>> [1] https://github.com/mozilla/rust/issues/5731
>> _______________________________________________
>> Rust-dev mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/rust-dev
>
>
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to