[rust-dev] Mutiplexing I/O within a task

Nat Pryce nat.pryce at gmail.com
Sun Jul 6 22:23:24 PDT 2014


Yes, I do want something like an nio Selector.

I'm trying to write it myself using epoll and eventfd on Linux. Binding to
the syscall is straightforward. However I can't work out how to get the fds
of IO objects (File struct, for example) so am stuck again.

The ioserver approach sounds promising as long as it can be easily extended
with new I/O mechanisms. One thing to keep in mind is that not all I/O can
be made non-blocking. Eg I2C and SPI communication on Linux is performed by
ioctls that block the calling thread and so would block an event loop that
relies on nonblocking IO.

--Nat

On Sunday, July 6, 2014, Tony Arcieri <bascule at gmail.com> wrote:

> On Sat, Jul 5, 2014 at 8:07 AM, Nat Pryce <nat.pryce at gmail.com
> <javascript:_e(%7B%7D,'cvml','nat.pryce at gmail.com');>> wrote:
>
>> I've been trying to write tasks that wait for both I/O and channel
>> communication. I've been told that, to maximise communication performance,
>> channels do not support selecting of both channels and I/O objects.
>>  Therefore a program should signal to a task that is waiting for I/O over
>> another I/O object, such as a pipe, not by sending a message over a
>> channel.  Fair enough.
>>
>> What API should I use to wait for multiple I/O objects within a task?  Is
>> there a runtime-independent API for this?
>>
>
> Sounds like you might want something like a Java NIO Selector. These
> Selectors bake in a pipe as a wakeup mechanism as well:
>
> http://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html
>
> However, there is more than one way to do it ;) Earlier I sent this
> message out about providing I/O "as a service" by having a dedicated task
> (or pool of tasks) that performs I/O operations for you, sending
> completions back as messages over the normal std::comm message protocol,
> ala Erlang's ioserver. Perhaps it's relevant to bring up again?
>
> ---------- Forwarded message ----------
> From: Tony Arcieri <bascule at gmail.com
> <javascript:_e(%7B%7D,'cvml','bascule at gmail.com');>>
> Date: Wed, Jan 29, 2014 at 1:40 AM
> Subject: Multiplexing I/O the Erlang way: an "ioserver"
> To: "rust-dev at mozilla.org
> <javascript:_e(%7B%7D,'cvml','rust-dev at mozilla.org');>" <
> rust-dev at mozilla.org
> <javascript:_e(%7B%7D,'cvml','rust-dev at mozilla.org');>>
>
>
> libnative (fast, low-latency native I/O) and libgreen (libuv backed and
> great for large numbers of infrequent/idle messengers) are both awesome and
> provide some great options for network server I/O, particularly since you
> can mix-and-match them.
>
> However there's a seemingly unsolved problem in Rust: multiplexing I/O
> operations with channels. I think this can be fixed in a purely additive
> manner (i.e everything else that exists today is great!) with a new feature
> borrowed from Erlang: the ioserver (noting that Erlang also implements
> libgreen-style synchronous I/O in addition to ioserver)
>
> Ignoring Erlang for a second, the naive solution to the I/O + channel
> multiplexing is magic select API that can handle both. In my experience
> (i.e. I wrote and support this approach in a system some people actually
> use) the backend implementation, especially across POSIX and Windows, ends
> up quite ugly.
>
> There's a better option though... if you want to multiplex IO with channel
> messages, turn everything into channel messages in one place: the "ioserver"
>
> Solution: Centralize I/O event loops into a separate thread (pool if
> necessary, probably not). Erlang and 0MQ work this way. Erlang implements
> an API called a "port" to talk to the ioserver. In Rust perhaps you could
> have a type that implements the same trait as channels?
>
> The ioserver becomes the central place to optimize the nitty gritty of
> taking I/O requests from the rest of the program and multiplexing them with
> other (i.e channel) events in the system. The basic formula is:
>
> - Have the ioserver block for events using libuv or what have you, and
> have an OS-specific I/O handle (i.e. a pipe) to unblock the selector in the
> event of in-process communication
> - Use lock-free mechanisms so if the selector isn't stuck in a system call
> we can use more efficient coordination of registering and unregistering I/O
> op interests
>
> (Note: libuv is an I/O completions library and not a selector library so
> the proposed solution is admittedly a bit handwavey)
>
> Mixing a pipe-based wakeup mechanism with lock-free operations to
> eliminate unnecessary system calls has been used somewhat successfully in
> the Netty I/O library for the JVM.
>
> --
> Tony Arcieri
>


-- 
http://www.natpryce.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140707/4d519289/attachment.html>


More information about the Rust-dev mailing list