Live data from Hacker News

Is Rust stack-efficient yet?

arewestackefficientyet.com

21–30 of 111 posts

Re: Is Rust stack-efficient yet?

#21
post #14

I noticed in one of my crates that Rust often cannot optimize "moves" away. I was in the unusual situation where I had to move around a very large stack buffer(typically in Rust they live on the heap). Instead of passing it back and forth between moving functions as I originally designed, I had to redesign it to use macros which significantly improved my benchmarks. Further attention to optimizations here would be ve…

How did you implement those macros?

Re: Is Rust stack-efficient yet?

#22
post #12

Earlier quoted context omitted.

The main goal is removing replacing pointless stack-to-stack copies with simply mutating in-place on the stack correctly in the first place. Due to some mix of: * Rust code relying more on copies than C++ (for esample, harder to make something uninitialized and fill it in) * LLVM missing optimizations that rust relies on heavier than C++ * No real guarantees around RVO / NRVO Rust code often will put something on the…

> No real guarantees around RVO / NRVO Shouldn’t Rust in theory have a lot more freedom in defining its calling conventions than C++ has? I wonder if there’s anything that prevents doing RVO by default, or if just hadn’t been a priority yet.

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

Re: Is Rust stack-efficient yet?

#23
post #9

I've run into frustrating stack overflows in seemingly trivial non-recursive code, so I appreciate this effort! I wonder if it might be simpler to track stack sizes statically instead of using runtime instrumentation. What I mean is, for example on x86_64, the function prologue has a stack reservation in the form of `sub rbp, 0x168`. So we can easily tell that the function uses 0x168 bytes of stack space. Just add th…

This won't work since you also need to track the maximum number of stack frames (e.g recursive calls) which is undecidable.

Re: Is Rust stack-efficient yet?

#25
post #5

It would be more informative if the stack metrics were paired with heap metrics. You can trivially avoid stack to stack copies by allocating on the heap and passing pointers / references. But that is often actually slower, because heap allocation is more costly than copying data within the stack.

This is not about a heap-vs-stack tradeoff, this is about the compiler routinely generating very inefficient code that copies data around on stack for no good reason. For an example I've seen myself: using a custom GC pointer library, calling `Gc::allocate(SomeBigStruct{...})` constructed the SomeBigStruct on stack and copied it around using memcpy 4 times before it actually landed in the allocated heap memory. The e…

If you don't mind me asking - how do you witness these low level memory allocations? Specific program, plugin to vs code?

Re: Is Rust stack-efficient yet?

#26
post #12

Earlier quoted context omitted.

The main goal is removing replacing pointless stack-to-stack copies with simply mutating in-place on the stack correctly in the first place. Due to some mix of: * Rust code relying more on copies than C++ (for esample, harder to make something uninitialized and fill it in) * LLVM missing optimizations that rust relies on heavier than C++ * No real guarantees around RVO / NRVO Rust code often will put something on the…

> No real guarantees around RVO / NRVO Shouldn’t Rust in theory have a lot more freedom in defining its calling conventions than C++ has? I wonder if there’s anything that prevents doing RVO by default, or if just hadn’t been a priority yet.

I think in theory it could, but something was definitely getting clogged in the optimizer. I'd see code like

" a = A::new(...);

return a; "

Create a on the stack, and immediately copy a into the stack region the caller was expecting it in. This seemed to get worse as struct size got larger, so I'm guessing there was so much IL the optimizer had to churn through it just gave up at some point.

Re: Is Rust stack-efficient yet?

#27
post #5

It would be more informative if the stack metrics were paired with heap metrics. You can trivially avoid stack to stack copies by allocating on the heap and passing pointers / references. But that is often actually slower, because heap allocation is more costly than copying data within the stack.

This is not about a heap-vs-stack tradeoff, this is about the compiler routinely generating very inefficient code that copies data around on stack for no good reason. For an example I've seen myself: using a custom GC pointer library, calling `Gc::allocate(SomeBigStruct{...})` constructed the SomeBigStruct on stack and copied it around using memcpy 4 times before it actually landed in the allocated heap memory. The e…

The optimizing backend for Rust and C++ is common. So if it didn't get optimized in Rust, it is very likely it wouldn't be in C++ as well. However, the code style of those two codebases might be different. IMHO C++ code is traditionally a lot more pointer and heap allocation heavy than Rust code. Rust makes moving stuff very convenient and using pointers/references quite inconvenient. Therefore showing heap allocation profiles would help us understand if those differences are due to actual compiler inefficiencies or different memory management patterns used in the source code.

Also rustc code has been written in different times than the majority of clang code. That might as well affect the copying patterns. Move semantics is actually a quite modern thing in C++ (and not default like in Rust).

Re: Is Rust stack-efficient yet?

#29

Earlier quoted context omitted.

This is not about a heap-vs-stack tradeoff, this is about the compiler routinely generating very inefficient code that copies data around on stack for no good reason. For an example I've seen myself: using a custom GC pointer library, calling `Gc::allocate(SomeBigStruct{...})` constructed the SomeBigStruct on stack and copied it around using memcpy 4 times before it actually landed in the allocated heap memory. The e…

If you don't mind me asking - how do you witness these low level memory allocations? Specific program, plugin to vs code?

You look at the generated assembly.

Re: Is Rust stack-efficient yet?

#30

Earlier quoted context omitted.

This is not about a heap-vs-stack tradeoff, this is about the compiler routinely generating very inefficient code that copies data around on stack for no good reason. For an example I've seen myself: using a custom GC pointer library, calling `Gc::allocate(SomeBigStruct{...})` constructed the SomeBigStruct on stack and copied it around using memcpy 4 times before it actually landed in the allocated heap memory. The e…

The optimizing backend for Rust and C++ is common. So if it didn't get optimized in Rust, it is very likely it wouldn't be in C++ as well. However, the code style of those two codebases might be different. IMHO C++ code is traditionally a lot more pointer and heap allocation heavy than Rust code. Rust makes moving stuff very convenient and using pointers/references quite inconvenient. Therefore showing heap allocatio…

C++'s constructors are basically custom built for this situation. It's really the only thing they're good for.
Post reply on HN