Stebalien opened issue #4100:
Feature
Pass a
StoreContext
(of some form) to theStore::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 theCallHook
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).
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.
alexcrichton labeled issue #4100:
Feature
Pass a
StoreContext
(of some form) to theStore::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 theCallHook
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).
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.
- We need to charge significantly more for memory access instructions than other instructions (worst-case random memory access is slow).
- 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.
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.
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.
Stebalien closed issue #4100:
Feature
Pass a
StoreContext
(of some form) to theStore::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 theCallHook
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).
Stebalien commented on issue #4100:
And thanks for your time and feedback!
Last updated: Nov 22 2024 at 16:03 UTC