Skip to content
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

Speed up getting and setting funcref elements/fields in GC objects #9347

Open
Tracked by #9351
fitzgen opened this issue Oct 1, 2024 · 2 comments
Open
Tracked by #9351

Speed up getting and setting funcref elements/fields in GC objects #9347

fitzgen opened this issue Oct 1, 2024 · 2 comments
Labels
cranelift:goal:optimize-speed Focus area: the speed of the code produced by Cranelift. performance wasmtime:ref-types Issues related to reference types and GC in Wasmtime

Comments

@fitzgen
Copy link
Member

fitzgen commented Oct 1, 2024

We don't keep VMFuncRef pointers inside the GC heap, as the GC heap is untrusted, and instead have a side table, and store table IDs in GC objects. We currently use libcalls to do id-to-funcref conversion when reading a funcref out from a GC object and to intern a funcref and get its associated table ID when writing the funcref into a GC object. libcalls on field/element access are very much not ideal from a performance perspective.

I wrote up some thoughts on how we could improve the situation in the original PR:

My most-immediate thoughts are that we would do roughly the following to speed this up:

  • Expose the slab to Wasm, allowing id-to-funcref conversion to happen fully within wasm code
  • for funcref-to-id conversion, add an LRU/associative cache to the vmctx (or maybe runtime limits) to cache the results of the libcall and allow the happy path to stay within wasm code. the slow path would still fall back to a libcall however (I do not want to implement hashing in wasm code and try to keep it in sync with the Rust hashing)

My hope is that the above would result in good enough perf for us to not have to revisit this for quite a while.

Originally posted by @fitzgen in #9341 (comment)

@fitzgen fitzgen added cranelift:goal:optimize-speed Focus area: the speed of the code produced by Cranelift. performance wasmtime:ref-types Issues related to reference types and GC in Wasmtime labels Oct 1, 2024
Copy link

github-actions bot commented Oct 1, 2024

Subscribe to Label Action

cc @fitzgen

This issue or pull request has been labeled: "wasmtime:ref-types"

Thus the following users have been cc'd because of the following labels:

  • fitzgen: wasmtime:ref-types

To subscribe or unsubscribe from this label, edit the .github/subscribe-to-label.json configuration file.

Learn more.

@fitzgen
Copy link
Member Author

fitzgen commented Oct 9, 2024

@cfallin and I were just brainstorming on this problem and came up with a couple interesting ideas.

Idea 1

  • all VMFuncRefs inside a store are allocated within an arena in that store. all VMFuncRefs for the store, so instead of putting an module's funcrefs in the instance's vmctx, they would be allocated into this arena.
  • now we can use raw *mut VMFuncRefs inside the GC heap, without trusting the GC heap, by bounds checking that the pointer is within that arena and appropriately aligned on every field/element read from a GC object

The tricky part is that this arena can't be resized or else existing pointers are invalidated. So we would have to rely on pre-allocating (virtual) memory, and not allow passing new, dynamically-created wasmtime::Funcs to Wasm beyond that pre-allocated limit.

Idea 2

Expose the id-to-funcref slab to Wasm, as described above. (Potentially not useing wasmtime::Slab anymore, but instead some simpler type that is more easily exposed to Wasm code.)

But instead of worrying about interning and/or wasting space and/or doing GC to clean up unused entries, we do the following:

  • add an id: Option<FuncRefId> field to VMFuncRef
  • when doing funcref-to-id conversion:
    • if (*funcref).id is some, then we reuse the existing id
    • otherwise, when it is none, we do a libcall to push the funcref into the side table (or just push onto the slab directly in Wasm code) and set the id field to the new entry's index

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cranelift:goal:optimize-speed Focus area: the speed of the code produced by Cranelift. performance wasmtime:ref-types Issues related to reference types and GC in Wasmtime
Projects
None yet
Development

No branches or pull requests

1 participant