Live data from Hacker News

Is Rust stack-efficient yet?

arewestackefficientyet.com

91–100 of 111 posts

Re: Is Rust stack-efficient yet?

#91

Earlier quoted context omitted.

The C++ committee recognized this problem. As of C++17, copy elision is mandatory. Several forms of it, at least.

Rust has also recognized the problem from a very early stage one. For example this is why there was a `box` operator in early rust. And e.g. placement-in like APIs had been in the works for years, it's just that no satisfying and sound solution has been found (but multiple solutions which initially seems sound). Which is why we currently are in a "hope the optimizer does the right thing" situations (through it is pre…

It’s just a bit of a surprise, and Rust hasn’t ironed out some of these surprises. I’m sure it will get fixed eventually.

Yes, you can give examples of cases where unusual code (like deep type nesting) can create these large data structures, and you can call it an anti-pattern. But Rust is also pitched as a C++ replacement for greenfield projects, so you have all of these C++ programmers who are used to being able to “new” something into existence of any size, and then initialize it. A series of design decisions in Rust has broken that for objects which don’t fit on the stack.

I’m satisfied with the explanation that “no satisfying and sound solution has been found” and I’m also satisfied with “Rust developers haven’t gotten around to addressing this issue”. I’m not really interested in hearing why some people who run into the same issue are making bad decisions.

Re: Is Rust stack-efficient yet?

#92
post #66

We need &out and &in, so we can safely write this stuff by hand. Then we can worry about the compiler automatically optimizing to use &out behind the scenes (using ABI flexibility). Trying to skip that first step, so the compiler just does unverified shit behind the scenes, I think will just end up with inflexibility and disappointment. Be the tortoise not the hare.

Easier said than done. You can already have: unsafe fn new_in_place(out: &mut MaybeUninit ) But you require unsafe code both to implement it (to project MaybeUninit) and to call it. For it to be safe to call the type system would have to encode the invariant that &out is initialised after the call. It becomes even more complicated if the operation can fail.

As a stepping stone. we could worry just about the panic=abort case, where this is all easier.

For panicking, I think we would want to switch to a model where borrower not borowee runs destructor for &mut; that way we can support "moving out of &mut temporarily" too.

Re: Is Rust stack-efficient yet?

#93

I would love to see this for C#. Avoiding heap allocations was something I had to tackle as part of a simulation software. C# has a handful of GC generations, and GC gen1 is very fast, but it's still faster to pool things ahead of time.

This isn't related to heap allocations. It's about removing the cost of a stack variable being moved into another stack variable.

I became interested in stack performance specifically because I had to avoid heap allocations.

Re: Is Rust stack-efficient yet?

#94
post #43

Earlier quoted context omitted.

Box::new allocating on the stack and moving is only true in debug builds, in release builds it directly allocates on the heap. Not apologizing, just explaining. It is being fixed, the interim solution is to use a Vec.

There’s a broader problem here, which also applies to the C++ ecosystem, which is that debug builds are far less usable than they should be. C++ compilers in common debug configurations will emit a function call for std::move(), which is not in any way useful for typical debugging tasks and can make the program significantly slower. I don’t want to rely on compiler optimizations to make my code work. Or alternatively…

> common debug configurations will emit a function call for std::move()

This is bbeing fixed in clang I think at least. It will be treated as an intrinsic not as a function and I recall for forward something similar.

Re: Is Rust stack-efficient yet?

#95
post #90

I would love to see this for C#. Avoiding heap allocations was something I had to tackle as part of a simulation software. C# has a handful of GC generations, and GC gen1 is very fast, but it's still faster to pool things ahead of time.

Using structs, stack allocations (safe since C# 7.x) and native heap go a long way. Many of the post C# 7 features have been used to improve .NET performance in techpower benchmarks, and rewrite runtime code from C++ into C#.

You can also use generic functions that take struct arguments instead of delegates to get something like STL. I wish there was some syntactic sugar in the language for that, too - basically, struct lambdas.

Re: Is Rust stack-efficient yet?

#96

Earlier quoted context omitted.

As pointed out elsewhere in this comment tree, things living on the stack when they needn't can mean they don't fit and thus the program doesn't work, so the optimisation can matter for that reason, and this is a particular reason to worry about it for larger objects where the optimiser is more likely not to see what's going on.

And yet, real world production rust programs exist and measured performance is generally excellent. People are acting like this graph they saw for the first time today means that Rust is running at sub-Ruby speeds, when even with these excess copies we already know, and have known for years how rust programs have been performing in real life. That there is room for improvement here does not mean that the status quo w…

> People are acting like this graph they saw for the first time today means that Rust is running at sub-Ruby speeds

Well, this is no different of how Rust people talk about C++ as if it was as unsafe as if you were writing inline assembly :)

Re: Is Rust stack-efficient yet?

#97
post #43

This affects the way you write code, too. I was writing something in Rust and I wanted to create a new boxed object. Box::new(...) Boom! Program crashes. The object I’m putting in the heap is too large for the stack. Rustc does this by instantiating the object on the stack, and then copying it to the box. I don’t really want to fuss with nightly or stuff like Box::new_uninit just to deal with this. C++ has both regul…

Box::new allocating on the stack and moving is only true in debug builds, in release builds it directly allocates on the heap. Not apologizing, just explaining. It is being fixed, the interim solution is to use a Vec.

This is not guaranteed behavior and should not be relied on!

Re: Is Rust stack-efficient yet?

#98
post #85

Earlier quoted context omitted.

Rust has also recognized the problem from a very early stage one. For example this is why there was a `box` operator in early rust. And e.g. placement-in like APIs had been in the works for years, it's just that no satisfying and sound solution has been found (but multiple solutions which initially seems sound). Which is why we currently are in a "hope the optimizer does the right thing" situations (through it is pre…

> But I have yet to see commercial projects with mixed skill level team members where using such libraries didn't lead to productivity reduction on the long run (independent of programming language). Mixed skill team or not, I really don’t see why Box should be something the language struggles with.

Agreed – but why would you want to box an array instead of simply using a Vec?

Re: Is Rust stack-efficient yet?

#99

Earlier quoted context omitted.

There’s a broader problem here, which also applies to the C++ ecosystem, which is that debug builds are far less usable than they should be. C++ compilers in common debug configurations will emit a function call for std::move(), which is not in any way useful for typical debugging tasks and can make the program significantly slower. I don’t want to rely on compiler optimizations to make my code work. Or alternatively…

fwiw, GCC now has -ffold-simple-inlines exactly for this issue.

There's also the `artificial` attribute which instructs the debugger to skip through marked functions.

Re: Is Rust stack-efficient yet?

#100
post #51
post #22

Earlier quoted context omitted.

Evaluation order is unspecified in C++, whereas it is well-specified in Rust. This makes things easier to reason about in Rust, but does give the optimizer less wiggle room. https://en.cppreference.com/w/cpp/language/eval_order

How is evaluation order even relevant for RVO?

In code like `a(b(d),c(e))`, I think it could be relevant. You would want different code based on the size of `b(d)`, `c(e)`, `d`, and `e`. If you must evaluate b before c, that would eliminate some possible arrangements.

Specifically, if `e` and `b(d)` are huge, you probably would want to evaluate `c(e)` first and then `b(d)`.

Post reply on HN