Skip to content

Consider implementing Singularity's channel contracts #2157

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
brson opened this issue Apr 8, 2012 · 5 comments
Closed

Consider implementing Singularity's channel contracts #2157

brson opened this issue Apr 8, 2012 · 5 comments
Labels
A-concurrency Area: Concurrency A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows

Comments

@brson
Copy link
Contributor

brson commented Apr 8, 2012

In Singularity channels have the useful property that sending never allocates and never blocks. This should allow for a very simple implementation that our semantics don't.

There are some additional enabling properties (or limitations):

  • Each channel has one sender and one receiver
  • Each channel has a defined protocol (channel contract) that must be obeyed

Based on the contract they statically know the maximum number of elements that any queue will hold so they always allocate exactly the right amount. The contract is verified dynamically.

Adopting Singularity-style channels has two potential benefits:

First, contracts on their own are a useful thing, particularly in a language that aims to be 'safe'.

More importantly though it allows the port to use a lock-free circular buffer for the queue. Improving messaging performance is really the only reason we would want to impose more restrictions on channels. Whether this optimization will really pay off in practice I am not sure - there are several other locks on the send and receive paths.

Still not sure this is the right thing to do as it will create more barriers in channel usability, but maybe higher-level abstractions could be built on top.

@boggle
Copy link
Contributor

boggle commented Apr 8, 2012

I see the implementation benefits but in this approach

  1. sending can block badly and in order to avoid this, the user needs to explicitly add its own buffer tasks. This would be in line with rust's idea of being explicit and giving control to the programmer /but/ it is also can be quite difficult to get right without experience with these things. I always liked how erlang's runtime handles these things for the unexperienced developer and manages queue size, processor load and back pressure quite intelligently. So this pushes concerns into user code that may be better left to the runtime.
  2. Concerning distributed channels, this channel contract does not really carry over, as it does not model what happens on the network appropriately, for example:
    • sending the next message before having received an acknowledgement of the last one
    • true multicast/broadcast support of the underlying network
    • I'm even tending to be against FIFO guarantees as that is not a good match for UDP

Sure these things can be emulated with helper tasks. However channel semantics that directly correspond to network realities simplify re-using of existing code in a distributed setting. If channel and network semantics differ, it can be very hard to put existing software on the network that relies on channel guarantees the network cannot provide without difficulties.

A middle ground may be providing different channel types that at least document what guarantees are expected.

@nikomatsakis
Copy link
Contributor

This doesn't seem to me that it has to be an "either/or" thing. We can have a simple but flexible form of channels (as in #2158) and a highly optimized, contract-driven form of channels. I don't think it'd be too much of a burden to maintain two channel implementations---or maybe one can be based on the other, as brson suggested---but I'd want to make sure we have a need for both of them. I'd be inclined to start with the simple, flexible form (perhaps as in #2158) and wait until we hit a roadblock for Servo or some other project where messaging performance is a bottleneck. At that point, we might think about refactoring.

@boggle
Copy link
Contributor

boggle commented Apr 8, 2012

Yes, I agree. I just think it is quite important to get the set of operations over channels right from the start as much as possible (#1255, broadcasts, timeouts), attach precise and reasonable semantics to the abstraction (perhaps using interfaces) that does not leak the implementation strategy, and provide enough support for using it without being a queueing theory expert ;). These are different issues but I think it is critical to get them right and a good idea to look more at erlang (which has proven that it works) than to look at go (which kind-of still has to).

From that angle, I'd like rust to somehow (flags, types, interfaces, typestate) differentiate between wether

  • a channel provides FIFO delivery or not,
  • a channel is lossy or not,
  • a channel send may block or not

and provide a few additional ops (timeouts, broadcasts).

@ghost ghost assigned eholk Jul 6, 2012
@eholk
Copy link
Contributor

eholk commented Jul 6, 2012

I've been working on implementing Singularity-style channel contracts. As of 7b03832, there is basic support for it in the compiler. I have a post describing it at http://theincredibleholk.wordpress.com/2012/07/06/rusty-pipes/. The proposal for channel contracts is also available at https://github.com/eholk/rust/wiki/Proposal-for-channel-contracts. So far the performance has been quite good. I'm going to be working on converting more code over to use them to get a feel for whether they are usable.

@eholk
Copy link
Contributor

eholk commented Jul 25, 2012

We have these now, so I'm going to close the bug. We could use more syntax extensions, and the pipe compiler needs to be more robust, but basic support is there.

I intend to try and replace all of the existing Rust communication code with things based on channel contracts, and then hopefully remove the comm module.

@eholk eholk closed this as completed Jul 25, 2012
@brson brson unassigned eholk Jun 16, 2014
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 22, 2022
tweak new test suite output

- Make the entire "## Running ui tests ..." green, including the target.
- Fix double-space in `testname.rs  .. ok`.
- Make the final summary a bit more like compiletest-rs, in particular the newlines around it
- Use the term "ignored" consistently, rather than "skipped"

r? `@oli-obk`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-concurrency Area: Concurrency A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows
Projects
None yet
Development

No branches or pull requests

4 participants