Stream: git-wasmtime

Topic: wasmtime / issue #4100 Pass a store to the call_hook


view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 14:59):

Stebalien opened issue #4100:

Feature

Pass a StoreContext (of some form) to the Store::call_hook.

Benefit

I'm currently wrapping every host function with some custom fuel accounting logic. Being able to move this logic into the Store::call_hook would make significantly harder to "mess up" and forget to wrap a wasm entry/exit point.

Implementation

To avoid breaking changes, I assume we'd need a new call_hook_with_store method that takes a callback that accepts a store along with the CallHook itself.

Alternatives

Our current alternative of wrapping host and exported functions "works". But it would be really nice to not have to do that (at least in this case).

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 15:16):

alexcrichton commented on issue #4100:

This is actually intentionally left out for now since the call-hooks are intended to be pretty low-level hooks and getting access to the entire store allows embedders to do things like recursively call wasm which I suspect wouldn't be safe to actually allow given the current implementation.

Could you describe your fuel accounting case a bit more though? This could perhaps be something we add natively to Wasmtime as well.

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 15:16):

alexcrichton labeled issue #4100:

Feature

Pass a StoreContext (of some form) to the Store::call_hook.

Benefit

I'm currently wrapping every host function with some custom fuel accounting logic. Being able to move this logic into the Store::call_hook would make significantly harder to "mess up" and forget to wrap a wasm entry/exit point.

Implementation

To avoid breaking changes, I assume we'd need a new call_hook_with_store method that takes a callback that accepts a store along with the CallHook itself.

Alternatives

Our current alternative of wrapping host and exported functions "works". But it would be really nice to not have to do that (at least in this case).

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 16:25):

Stebalien commented on issue #4100:

Could you describe your fuel accounting case a bit more though? This could perhaps be something we add natively to Wasmtime as well.

We're doing fuel accounting in a blockchain context, so deterministic and pessimistic fuel accounting is our priority. The TL;DR is: we want quite a bit of control.

  1. We need to charge significantly more for memory access instructions than other instructions (worst-case random memory access is slow).
  2. We need to charge for bulk memory instructions (random access charge + a per-byte cost).

Furthermore, we want to account for fuel accounting overhead itself. For example, we're planning on charging _less_ for bulk memory instructions that take a constant parameter, because the fuel accounting overhead is lower.

Finally, we're planning on performing fuel instrumentation from within a wasm module to make it easier to ensure that fuel is always accounted for in the exact same way.


But to be clear, simply wrapping all of our calls in and out of wasm "works". It would just be _better_ if we had a way to read/write globals without having to wrap host calls.

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 18:09):

alexcrichton commented on issue #4100:

Ah ok, thanks for the explanation. It's theoretically possible that we could provide a custom fuel-counting API or something like that, but if your use case needs such precise control over fuel then it might be best for you to instrument the wasm ahead of time. The fuel accounting done in Wasmtime wasn't every really intended to be super precise and/or fit a particular spec, rather it was instead originally for "it reasonable gets async things to yield". While an API for embedding modules with fuel accounting like you've mentioned I suspect long-term it might make more sense for you to instrument the module itself. For example the module could have its own global for fuel which is checked periodically and otherwise incremented/decremented from in the same manner as fuel in Wasmtime. I think that the generate code should be pretty similar in theory.

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 19:06):

Stebalien commented on issue #4100:

It's theoretically possible that we could provide a custom fuel-counting API or something like that, but if your use case needs such precise control over fuel then it might be best for you to instrument the wasm ahead of time. The fuel accounting done in Wasmtime wasn't every really intended to be super precise and/or fit a particular spec, rather it was instead originally for "it reasonable gets async things to yield".

Yeah, that's what I figured. We _also_ need to accurately account for things like stack depth, so I don't think we're going to be able to get away from instrumentation.

For example the module could have its own global for fuel which is checked periodically and otherwise incremented/decremented from in the same manner as fuel in Wasmtime.

Yep, that's what we're doing. We have a global for both stack depth and fuel usage, and update it at the beginning of every continuous "block".


Given this, I'm going to close this issue as it sounds like manual wrapping is the best solution for now.

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 19:06):

Stebalien closed issue #4100:

Feature

Pass a StoreContext (of some form) to the Store::call_hook.

Benefit

I'm currently wrapping every host function with some custom fuel accounting logic. Being able to move this logic into the Store::call_hook would make significantly harder to "mess up" and forget to wrap a wasm entry/exit point.

Implementation

To avoid breaking changes, I assume we'd need a new call_hook_with_store method that takes a callback that accepts a store along with the CallHook itself.

Alternatives

Our current alternative of wrapping host and exported functions "works". But it would be really nice to not have to do that (at least in this case).

view this post on Zulip Wasmtime GitHub notifications bot (May 05 2022 at 19:06):

Stebalien commented on issue #4100:

And thanks for your time and feedback!


Last updated: Dec 23 2024 at 12:05 UTC