Cap function's stack usage

Hello, in embedded programming it might be useful to statically cap function's stack, because what I'm doing now is trying give function a stack size and try, would it play out or not. What do you think about that feature? Maybe some attribute would work? Of course it probably would limit things like recursion, and I'm not sure about FFI

4 Likes

Seems potentially reasonable. GCC and clang both have options to check or report stack usage: -fstack-usage, -mmax-stack-frame=, and -Wstack-usage=.

4 Likes

Have you seen the large_stack_frames clippy lint? It's imperfect, because it runs based on the unoptimized code (so it's looking at an upper bound on stack size), but it might reduce the number of experiments you need to run.

The presence of this lint is further evidence that a "maximum stack size" warning or error would be useful.

6 Likes

async fn has a side effect of moving (some of) its stack into the Future type, which is going to have a size known at compile time. There's going to be run-time stack in Future::poll, but likely a much smaller one. There's pollster crate that can drive Futures without a fully-featured async runtime.

1 Like

And if your async fn truly never .awaits, now_or_never is the maximally trivial executor, essentially just pin!(fut).poll(/*ignored*/), avoiding the need for any reactor at all.

1 Like

Futures only store variables that are held across .await points, not the whole stack frame

2 Likes

Are there any optimizations that can increase stack usage (e.g., perhaps alignment for vectorization?).

From what I can see there are not so many objections against it, so I will open an issue in rust-lang/rust. Or maybe there's a better route to proceed?

1 Like

Inlining. If you call two functions in series, max stack is max(A, B). If one call is inlined but the other remains outlined, stack usage is now A + B barring mid-function stack resizing. (LLVM only allows increases mid-function via C alloca and never decreases, AIUI.)

Also, just the process of compilation may require more stack usage than is evident by source stack usage (temporaries and locals) in order to save register state, although I doubt anyone asking this question would consider anything done during -O0 which can't be turned off as in scope.

In practice truely-zero-optimization stack usage is sloppy enough that if you're doing simple DCE, mem2reg, and overlapping liveness-exclusive stack allocation, you'd be hard pressed to ever end up with more stack usage than baseline.

1 Like

Unfortunately, yes: Unnecessary stack usage · Issue #88930 · rust-lang/rust · GitHub

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.