News for hackers. Stuff that matters.
Re:Zero-cost futures in Rust by soulbadguy on Thursday August 11, 2016 @12:11PM (#12269417)
Yes , i only have a simple understanding of rust memory model . So what happened when/if the future escapes/outlives the current stack/context ?
Re:Zero-cost futures in Rust by aturon on Thursday August 11, 2016 @12:19PM (#12269492)
To be clear, the issue here isn't so much stack vs heap, as much as how many heap allocations are happening.

In practice, you build up a really big combined future on the stack, which has all of the space needed for any state in its state machine, and then when the future is fired off (in a task -- one per connection), that entire thing is moved into the heap in one shot. Thus, generally, you do one big allocation up front per connection -- exactly the same as you'd do when writing state machines by hand.

The follow up posts will go into much more detail on this point :)

Re:Zero-cost futures in Rust by soulbadguy on Thursday August 11, 2016 @03:20PM (#12270916)
Fair enough, but op was quite misleading by saying that in rust closure don't need allocation.

So back to future vs coroutine , it seems that they the advantage in term of allocation simply because the context is not distroid when suspending/resuming coroutines

Re:Zero-cost futures in Rust by steveklabnik on Thursday August 11, 2016 @03:27PM (#12270967)

  let mut counter = 0;
  let mut increment = || { counter += 1; counter };

  increment();
  increment();
There is no heap allocation there.
Re:Zero-cost futures in Rust by saynsedit on Thursday August 11, 2016 @03:50PM (#12271110)
This is missing his point. "Increment" is called outside of its scope when the epoll triggers. If "counter" is stack allocated that would cause a segfault, so it must be heap allocated which is his point.
Re:Zero-cost futures in Rust by steveklabnik on Thursday August 11, 2016 @04:03PM (#12271205)
Well, they're two different points: closures in rust do not inherently have to heap allocate. But that also doesn't mean that they can _not_ be heap allocated either.

And in this example, it's not even really the closures that allocate: it's still one allocation, regardless of the number of closures.

Re:Zero-cost futures in Rust by soulbadguy on Thursday August 11, 2016 @05:56PM (#12271883)
No. they are not two different points. You are artificially restricting the argument, and saying that some parts are a different question by introducing this new idea of "inherent nature" of a closure in rust : Some humans have legs, some do not. Does it mean that having legs is not an "inherent" part of the human experience?

So to go back to the argument, we are trying to compare using a coroutine base approach vs using a future/state machine + closure approach. My point was that because a coroutine allows one to enter and leave a stack frame without destroying it, it can lead to less allocation and therefore be more efficient in those cases (and let's not even talk about the cost of the activation/deactivation of the stack frame)

Re:Zero-cost futures in Rust by steveklabnik on Thursday August 11, 2016 @06:23PM (#12272070)
To use your analogy, I feel like you're saying that only humans that have legs are human. I'm saying that they're all human.

This analogy is weird.

Furthermore, because closures aren't inherently boxed, there might not even be a stack frame to begin with. Closures are syntax sugar for a struct + a trait implementation on that struct, and said call is then very inline-able.

This is also where I'm getting at with the single invocation thing: with these futures, all of these closures are going to be inlined into one big state machine, which is then itself eventually put on the heap. But that heap allocation has nothing to do with the closure, and more to do with the future wanting to not tie its data down to a specific stack frame.

Re:Zero-cost futures in Rust by saynsedit on Thursday August 11, 2016 @07:44PM (#12272529)
I think this is becoming a semantic argument.

I think we all understand that Rust/C++ closures don't necessarily allocate memory. His point is simply that by using a rust closure to asynchronously handle an event a heap allocation must be done. Compare to the stack swapping method of classical coroutines, which wouldn't require a heap allocation.

I recognize that with Rust zero-cost futures, one big heap allocation is done for the entire futures combination and is roughly analogous to one big eager stack allocation for a coroutine.

Re:Zero-cost futures in Rust by steveklabnik on Thursday August 11, 2016 @07:53PM (#12272579)
Yes, I think so too. I just want to make sure the semantics are clear. I think your summary here is excellent.
Re:Zero-cost futures in Rust by tatterdemalion on Thursday August 11, 2016 @07:39PM (#12272498)
> Some humans have legs, some do not. Does it mean that having legs is not an "inherent" part of the human experience?

I mean - yes, that is what it means.

Re:Zero-cost futures in Rust by pcwalton on Thursday August 11, 2016 @06:01PM (#12271918)
You don't have to destroy the "stack frame" (by which I assume you mean the state retained between blocking operations) every time you enter and leave. Why do you think you need to?
Re:Zero-cost futures in Rust by saynsedit on Thursday August 11, 2016 @07:34PM (#12272469)
He's talking about the difference between swapping the stack pointer and executing a single "jump" instruction vs initiating a full function call (pushing argument(s), function prologue/epilogue)
Re:Zero-cost futures in Rust by pcwalton on Thursday August 11, 2016 @08:22PM (#12272711)
Calling a function isn't "allocation". And you don't just swap the stack pointer: you have to reload the register state. It's the same cost as a function call.
Re:Zero-cost futures in Rust by yazaddaruvala on Friday August 12, 2016 @05:49AM (#12274337)
May I ask, where do you assume a coroutine's stack lives?

i.e. In relation to program memory

Re:Zero-cost futures in Rust by soulbadguy on Friday August 12, 2016 @07:44AM (#12274779)
Not sure what you mean, but from my understating the coroutine e stacks are just allocated pieces of memory in the current address space ( might be stack allocated or heap allocated depending the the situation)
Re:Zero-cost futures in Rust by eddyb on Thursday August 11, 2016 @12:20PM (#12269501)
Compile error if it's holding on to any borrowed data on the stack - however, borrowing is only the default, if you move from a capture your closure will contain that value instead of reference to the value, and if you have "move" in front of your closure, all the captures are contained in the closure, so by boxing or by using -> impl Fn(...) you can safely return it.

If you need to hold onto data accessed from multiple locations, you'd need to use Rc<T> instead of keeping that data on the stack, which is closer to GC'd languages (and pretty similar to Swift, IIUC, except Rust is more explicit).

Re:Zero-cost futures in Rust by Rusky on Thursday August 11, 2016 @12:15PM (#12269454)
This is handled by the borrow checker, the same as anything else that might hold references to stack data - you get a compiler error and then can decide how to resolve the conflict, either by extending the lifetime of the referent (perhaps by boxing, or creating it earlier in the call stack), or by shrinking the lifetime of the future.
Re:Zero-cost futures in Rust by dbaupp on Thursday August 11, 2016 @12:16PM (#12269466)
It's an error if that would be unsafe, or else it compiles fine: the future compiles down to an enum/struct that stores everything inline and it can be returned/move up the stack/stored in global memory the same way that aggregate values returned without allocation (etc.) in C or C++.
Re:Zero-cost futures in Rust by steveklabnik on Thursday August 11, 2016 @12:16PM (#12269458)
From the post

  > There are essentially no imposed synchronization costs; if you want
  > to associate data that lives on your event loop and access it in a
  > single-threaded way from futures, we give you the tools to do so.