# Cap function's stack usage

**URL:** <https://internals.rust-lang.org/t/cap-functions-stack-usage/20340>\
**Category:** language design\
**Created:** [February 16, 2024, 6:55am UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340 "2024-02-16T06:55:41Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ddystopia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddystopia/32/10915_2.png) [@Ddystopia](https://internals.rust-lang.org/u/Ddystopia)\
**Post date:** [February 16, 2024, 6:55am UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/1 "2024-02-16T06:55:41Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 16, 2024, 11:28am UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/2 "2024-02-16T11:28:00Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![farnz](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/farnz/32/6587_2.png) [@farnz](https://internals.rust-lang.org/u/farnz)\
**Post date:** [February 16, 2024, 11:38am UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/3 "2024-02-16T11:38:21Z")

</div>

Have you seen the [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#/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.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [February 17, 2024, 12:06pm UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/4 "2024-02-17T12:06:16Z")

</div>

`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`](https://lib.rs/crates/pollster) crate that can drive `Future`s without a fully-featured async runtime.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 18, 2024, 3:33am UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/5 "2024-02-18T03:33:27Z")

</div>

> [@kornel](#):
>
> There's [`pollster`](https://lib.rs/crates/pollster) crate

And if your `async fn` truly never `.await`s, [`now_or_never`](https://docs.rs/futures/latest/futures/future/trait.FutureExt.html#method.now_or_never) is the maximally trivial executor, essentially just `pin!(fut).poll(/*ignored*/)`, avoiding the need for any reactor at all.

---

<div class="post-metadata">

**Author:** ![Ddystopia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddystopia/32/10915_2.png) [@Ddystopia](https://internals.rust-lang.org/u/Ddystopia)\
**Post date:** [February 18, 2024, 12:15pm UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/6 "2024-02-18T12:15:10Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [February 18, 2024, 9:38pm UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/7 "2024-02-18T21:38:42Z")

</div>

> [@farnz](#):
>
> 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.

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

---

<div class="post-metadata">

**Author:** ![Ddystopia](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddystopia/32/10915_2.png) [@Ddystopia](https://internals.rust-lang.org/u/Ddystopia)\
**Post date:** [February 18, 2024, 9:57pm UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/8 "2024-02-18T21:57:34Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 18, 2024, 11:00pm UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/9 "2024-02-18T23:00:27Z")

</div>

> [@mathstuf](#):
>
> Are there any optimizations that can _increase_ stack usage

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.

---

<div class="post-metadata">

**Author:** ![newpavlov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/newpavlov/32/3290_2.png) [@newpavlov](https://internals.rust-lang.org/u/newpavlov)\
**Post date:** [February 19, 2024, 11:38am UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/10 "2024-02-19T11:38:01Z")

</div>

> [@mathstuf](#):
>
> Are there any optimizations that can _increase_ stack usage (e.g., perhaps alignment for vectorization?).

Unfortunately, yes: [Unnecessary stack usage · Issue #88930 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/88930)

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [May 19, 2024, 11:38am UTC](https://internals.rust-lang.org/t/cap-functions-stack-usage/20340/11 "2024-05-19T11:38:20Z")

</div>

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