-
Notifications
You must be signed in to change notification settings - Fork 592
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wasm: introduce custom stack allocator for wasmtime #14161
Conversation
Signed-off-by: Tyler Rockwood <rockwood@redpanda.com>
Now that we've activated wasmtime's async functionality, a couple of crates have changed. Signed-off-by: Tyler Rockwood <rockwood@redpanda.com>
16941cd
to
c027feb
Compare
@travisdowns commit eae2763 has the implementation of what we talked about in slack if you're interested in taking a peek (no worries if not) |
144d63b
to
6e10e25
Compare
ducktape was retried in job https://buildkite.com/redpanda/redpanda/builds/38963#018b2c89-7442-4b9b-af40-0649d207c732 |
// stack space left. | ||
std::ptrdiff_t stack_left = (&dummy_stack_var) - bounds->bottom; | ||
void* stack_ptr = ::alloca(stack_left - max_host_function_stack_usage); | ||
// Prevent the alloca from being optimized away by logging the result. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this a concern? is there some sort of data dependency analysis that the compiler can't see?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure? At first I was just calling ::alloca(...)
and discarding the result and the stack wasn't overflowing, so I guess clang was optimizing that away or something? Ooh I should also probably make sure there is no tail call optimization or anything too.
By default wasmtime allocates stacks using `mmap`, but there is now an API to override the stack allocator. This is the custom allocator that we will plug into wasmtime. We allocate stacks on demand since they will fit within our 128KB allocation limit that we recommend. These stacks will also have a guard page at the bottom of the stack to protect against stack overflow. We cache stacks (indefinitely) because the call to `mprotect` will break up any transparent huge pages (THP) that have been allocated by the seastar allocator, in an effort to not breakup all these pages all over memory we reuse them aggressively. Another option is to preallocate a 2MB THP on startup and chunk that up for wasmtime stacks, but then that imposes a limit on the number of VMs we can run on a single core, to attempt to prevent that limitation we will allocate them dynamically, as the performance impact should be small anyways for breaking up those pages. There is more as comments in the allocator header as well. Signed-off-by: Tyler Rockwood <rockwood@redpanda.com>
This plugins a sharded stack allocator into a custom wasmtime stack allocator. The setup and API here is very similar to how the custom wasmtime (linear) data memory is plugged in. Signed-off-by: Tyler Rockwood <rockwood@redpanda.com>
We want to ensure that our host functions don't blow the stack when executing if a guest uses up a bunch of stack space within the Wasm VM. We do this in our tests by allocating a variable amount on the stack so that it looks to every host function that the guest has used the maximum amount of the stack. Additionally, we only run in this "strict stack mode" in release tests. We don't want to do this in production builds, and in debug builds ASAN throws a fit when doing this. Presumably ASAN complains because it doesn't know we've switched the stack as that happens in Rust land which isn't instrumented with ASAN checks. Honestly this is fine as stack usage in debug mode is wildly different than release mode and we're realistically only using debug mode internally in non production usage. Signed-off-by: Tyler Rockwood <rockwood@redpanda.com>
Force push: Address #14161 (comment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm.
i think it is worth understanding the bit about alloca being optimized away, but other than that ship it.
Looks like clang "optimizes" it away: https://godbolt.org/z/eEexvrj4b Which may or may not be compiler bug... happy to take suggestions on better ways to prevent it from being optimized away (we do want this to work in release mode). |
Oh i see on closer inspection you want the extra stack space but you have no use for the returned I do wonder though if it being optimized away is a mirage? For example. If I write |
I'm not sure I follow - it's probably fine to ignore the alloca if we ignore the return result, but it does change the semantics of the resulting code.
huh these seem at odds? |
@rockwotj - it's a bit hard to be precise because However, it is not surprising to me that the The usual way to work around this stuff is to "escape" the relative value. E.g., escape the alloca pointer, so the compiler no longer knows what went on it with and has to assume it gets used in all the supported ways. We have |
Introduce a custom stack allocator that we plugin to wasmtime using the APIs added in bytecodealliance/wasmtime#7209.
See the individual commits on the overall design and implementation details, as well as the tradeoffs of other options.
Backports Required
Release Notes