Live data from Hacker News

Zero-cost futures in Rust

aturon.github.io

51–60 of 348 posts

Re: Zero-cost futures in Rust

#51

I dabbled with rust in the past and was really fascinated with it, but haven't played around lately. One thing caught my eye in the post: fn get_row(id: i32) -> impl Future ; That return type looks odd to me. What does it mean to return an "impl", and is that a new feature in rust, or just something advanced that I missed in my exploration before?

Rust couldn't return Traits since they vary in return Size.So using couple of chain and maps would result in following syntax.

    fn did_too_many_chains() -> Chain>>>, SkipWhile>>>
Now, you can write:

   fn did_too_many_chains() -> impl Iterator 
and be done with it.

Re: Zero-cost futures in Rust

#52
post #33

I dabbled with rust in the past and was really fascinated with it, but haven't played around lately. One thing caught my eye in the post: fn get_row(id: i32) -> impl Future ; That return type looks odd to me. What does it mean to return an "impl", and is that a new feature in rust, or just something advanced that I missed in my exploration before?

This is an exciting upcoming feature in Rust, which you can read more about in a couple places: - http://aturon.github.io/blog/2015/09/28/impl-trait/ - https://github.com/rust-lang/rfcs/pull/1522 This feature allows you to return any struct that implements the trait, without having to type the name of the struct (which can sometimes be quite big). It also means that clients only know what traits are implemented; the…

Sounds awesome. Love it :)

Re: Zero-cost futures in Rust

#53
post #43

Wohoo. I was waiting for this. I hope that at a later point this will also mean that we get some sort of syntax support for it once it's stable and entered std.

What sort of syntax support do you have in mind? (Personally I think any language-level support is unlikely, given that Rust doesn't make a point of privileging any particular approach to concurrency.)

> Personally I think any language-level support is unlikely

I don't. :)

Futures are a very generic abstraction that doesn't really favor any approach any more than, say, iterators do.

Re: Zero-cost futures in Rust

#54

I'm rather surprised by the benchmark; I would expect the Go benchmark to be faster than Java (and the fact that it isn't may indicate some improvements that can be done to fasthttp by learning from rapidoid or minihttp). Then again, the difference isn't that much, so it just could be implementation details that would require a total refactor to fix.

Why would you expect that? AFAIK the Go compiler has a worse optimizer, a worse GC (at least throughput-wise) and possibly also a worse threading runtime. Since the benchmark measures steady-state performance and not memory or latency, and with the best Java server (probably optimized to almost never allocate) then Java having better code generation and threading could give it that much of an edge.

Re: Zero-cost futures in Rust

#55
post #45

TLDR; I’ve claimed a few times that our futures library provides a zero-cost abstraction, in that it compiles to something very close to the state machine code you’d write by hand. To make that a bit more concrete: - None of the future combinators impose any allocation. When we do things like chain uses of and_then, not only are we not allocating, we are in fact building up a big enum that represents the state machin…

that sounds great but I guess that will make the compilation time bigger.

In Rust it's frequently the case that slow compilations are dominated by generating and optimizing LLVM IR. This codegen step (generating LLVM IR) often takes awhile just because we're generating so much IR.

Rust takes an approach with generic functions called monomorphization which means that we generate a new version of each function for each set of generics it's instantiated with. This means that a future of a String will generate entirely different code from a future of an integer. This allows generics to be a zero cost abstraction because code is optimized as if you had substituted all the generics by hand.

Putting all that together, highly generic programs will generally trend towards higher compile times. With all the generics in play, there tends to be a lot of monomorphization which causes quite a lot of LLVM IR to get generated.

As with many aspects of Rust, however, you have a choice! Rust supports what we call "trait objects" which is a way to take a future and put it behind an allocation with a vtable (virtual dispatch). This forces the compiler to generate code immediately when a trait object is created, rather than down the line when something is monomorphized.

Put another way, you've got control over compile times if you're using futures. If you're taking a future generically and that takes too long to compile, you can instead take a trait object (or quickly convert it to a trait object). This will help cut down on the amount of code getting monomorphized.

So in general futures shouldn't make compilation worse. You'll have a choice between performance (no boxes) and compile times (boxing) occasionally, but that's basically already the case of what happens in Rust today.

Re: Zero-cost futures in Rust

#56

I'm rather surprised by the benchmark; I would expect the Go benchmark to be faster than Java (and the fact that it isn't may indicate some improvements that can be done to fasthttp by learning from rapidoid or minihttp). Then again, the difference isn't that much, so it just could be implementation details that would require a total refactor to fix.

Yep, same here -- at least for fasthttp. This is pretty far into microbenchmarking territory, so the differences among the top libraries likely don't matter much in practice. But I think the main point is pretty clear -- even with an extreme microbenchmark, futures don't seem to be imposing notable cost.

Re: Zero-cost futures in Rust

#57

I dabbled with rust in the past and was really fascinated with it, but haven't played around lately. One thing caught my eye in the post: fn get_row(id: i32) -> impl Future ; That return type looks odd to me. What does it mean to return an "impl", and is that a new feature in rust, or just something advanced that I missed in my exploration before?

[deleted]

Re: Zero-cost futures in Rust

#58

I'm rather surprised by the benchmark; I would expect the Go benchmark to be faster than Java (and the fact that it isn't may indicate some improvements that can be done to fasthttp by learning from rapidoid or minihttp). Then again, the difference isn't that much, so it just could be implementation details that would require a total refactor to fix.

Well, Go has a 1.7 release coming up very soon which has a nice performance boost due to the new SSA backend, I assume this test was done using Go 1.6 .

Re: Zero-cost futures in Rust

#59
post #43

Wohoo. I was waiting for this. I hope that at a later point this will also mean that we get some sort of syntax support for it once it's stable and entered std.

What sort of syntax support do you have in mind? (Personally I think any language-level support is unlikely, given that Rust doesn't make a point of privileging any particular approach to concurrency.)

See Python 3.5, ES6 and C# and their await stuff. They generally use a form of future internally to abstract this.

Re: Zero-cost futures in Rust

#60
post #42

I dabbled with rust in the past and was really fascinated with it, but haven't played around lately. One thing caught my eye in the post: fn get_row(id: i32) -> impl Future ; That return type looks odd to me. What does it mean to return an "impl", and is that a new feature in rust, or just something advanced that I missed in my exploration before?

On a related note: why `Future ` instead of `Future `? I notice it's consistent with the standard `Iterator `, but why is Iterator like that?

Because it's an associated type (https://doc.rust-lang.org/book/associated-types.html), not a regular generic parameter.
Post reply on HN