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

New Fuel APIs for Store #7298

Merged
merged 1 commit into from
Oct 23, 2023
Merged

New Fuel APIs for Store #7298

merged 1 commit into from
Oct 23, 2023

Conversation

rockwotj
Copy link
Contributor

@rockwotj rockwotj commented Oct 19, 2023

In an effort to simplify the many fuel related APIs, simplify the
interface here to a single counter with get and set methods.
Additionally the async yield is reduced to an interval of the total fuel
instead of injecting fuel, so it's easy to still reason about how much
fuel is left even with yielding turned on.

Internally this works by keeping two counters - one the VM uses to
increment towards 0 for fuel, the other to track how much is in
"reserve". Then when we're out of gas, we pull from the reserve to
refuel and continue. We use the reserve in two cases: one for overflow
of the fuel (which is an i64 and the API expresses fuel as u64) and the
other for async yieling, which then the yield interval acts as a cap to
how much we can refuel with.

This also means that get_fuel can return the full range of u64
before this change it could only return up to i64::MAX. This is
important because this PR is removing the functionality to track fuel
consumption, and this makes the API less error prone for embedders to
track consumption themselves.

Careful to note that the VM counter that is stored as i64 can be
positive if an instruction "costs" multiple units of fuel when the fuel
ran out.

Fixes: #7255

I've implemented the APIs as documented in the strawman from the issue,
but I used Option<NonZeroU64> for the yield interval instead of trying
to figure out what to do if the yield interval is 0.

@rockwotj rockwotj requested a review from a team as a code owner October 19, 2023 21:23
@rockwotj rockwotj requested review from pchickey and removed request for a team October 19, 2023 21:23
@github-actions github-actions bot added fuzzing Issues related to our fuzzing infrastructure wasmtime:api Related to the API of the `wasmtime` crate itself wasmtime:c-api Issues pertaining to the C API. labels Oct 19, 2023
@github-actions
Copy link

Subscribe to Label Action

cc @fitzgen, @peterhuene

This issue or pull request has been labeled: "fuzzing", "wasmtime:api", "wasmtime:c-api"

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

  • fitzgen: fuzzing
  • peterhuene: wasmtime:api, wasmtime:c-api

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

Learn more.

@github-actions github-actions bot added the wasmtime:config Issues related to the configuration of Wasmtime label Oct 20, 2023
@github-actions
Copy link

Label Messager: wasmtime:config

It looks like you are changing Wasmtime's configuration options. Make sure to
complete this check list:

  • If you added a new Config method, you wrote extensive documentation for
    it.

    Our documentation should be of the following form:

    Short, simple summary sentence.
    
    More details. These details can be multiple paragraphs. There should be
    information about not just the method, but its parameters and results as
    well.
    
    Is this method fallible? If so, when can it return an error?
    
    Can this method panic? If so, when does it panic?
    
    # Example
    
    Optional example here.
    
  • If you added a new Config method, or modified an existing one, you
    ensured that this configuration is exercised by the fuzz targets.

    For example, if you expose a new strategy for allocating the next instance
    slot inside the pooling allocator, you should ensure that at least one of our
    fuzz targets exercises that new strategy.

    Often, all that is required of you is to ensure that there is a knob for this
    configuration option in wasmtime_fuzzing::Config (or one
    of its nested structs).

    Rarely, this may require authoring a new fuzz target to specifically test this
    configuration. See our docs on fuzzing for more details.

  • If you are enabling a configuration option by default, make sure that it
    has been fuzzed for at least two weeks before turning it on by default.


To modify this label's message, edit the .github/label-messager/wasmtime-config.md file.

To add new label messages or remove existing label messages, edit the
.github/label-messager.json configuration file.

Learn more.

@alexcrichton
Copy link
Member

I'll take a look once CI is green, so feel free to ping me when that comes up. I'll check in every now and then as well.

@rockwotj
Copy link
Contributor Author

@alexcrichton test are passing (no rush on a review, I wont be able to make updates until Monday anyways)

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow I really like how this all turned out, thank you for pushing on this!

I've got a few cosmetic-related concerns but otherwise I think this is good to go. If you're up for it as well it might be good to do a once-over of fuel-related documentation not only on Store but also Config and perhaps other locations since this is a somewhat significant departure from the prior model (but well worth it). For example running out of fuel now unconditionally panics and that cannot be configured, which may be lingering in a few locations (and if not then nothing to do yay!)

crates/wasmtime/src/store.rs Show resolved Hide resolved
crates/wasmtime/src/store.rs Outdated Show resolved Hide resolved
pub fn out_of_fuel_async_yield(&mut self, injection_count: u64, fuel_to_inject: u64) {
self.inner
.out_of_fuel_async_yield(injection_count, fuel_to_inject)
pub fn fuel_async_yield_interval(&mut self, interval: Option<NonZeroU64>) -> Result<()> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I think it definitely makes sense to store this as Option<NonZeroU64> taking that as a function parameter here may be a bit overkill in the sense that it's somewhat unergonomic to call. Could this instead take Option<u64> and return an error for Some(0)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on what to do for the C API in that case? Do we just translate the 0 there into None?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think that's reasonable to do for the C API as magical numbers like that are relatively common in C

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I've made this change then.

Copy link
Contributor Author

@rockwotj rockwotj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're up for it as well it might be good to do a once-over of fuel-related documentation not only on Store but also Config and perhaps other locations since this is a somewhat significant departure from the prior model (but well worth it). For example running out of fuel now unconditionally panics and that cannot be configured, which may be lingering in a few locations (and if not then nothing to do yay!)

I found one place in Config::consume_fuel so nice suggestion! A quick glance over the project via git grep fuel did not show any other usages.

crates/wasmtime/src/store.rs Outdated Show resolved Hide resolved
pub fn out_of_fuel_async_yield(&mut self, injection_count: u64, fuel_to_inject: u64) {
self.inner
.out_of_fuel_async_yield(injection_count, fuel_to_inject)
pub fn fuel_async_yield_interval(&mut self, interval: Option<NonZeroU64>) -> Result<()> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on what to do for the C API in that case? Do we just translate the 0 there into None?

@alexcrichton alexcrichton added this pull request to the merge queue Oct 23, 2023
@alexcrichton alexcrichton removed this pull request from the merge queue due to a manual request Oct 23, 2023
@alexcrichton
Copy link
Member

oops sorry queued up for merge a bit too soon there

In an effort to simplify the many fuel related APIs, simplify the
interface here to a single counter with get and set methods.
Additionally the async yield is reduced to an interval of the total fuel
instead of injecting fuel, so it's easy to still reason about how much
fuel is left even with yielding turned on.

Internally this works by keeping two counters - one the VM uses to
increment towards 0 for fuel, the other to track how much is in
"reserve". Then when we're out of gas, we pull from the reserve to
refuel and continue. We use the reserve in two cases: one for overflow
of the fuel (which is an i64 and the API expresses fuel as u64) and the
other for async yieling, which then the yield interval acts as a cap to
how much we can refuel with.

This also means that `get_fuel` can return the full range of `u64`
before this change it could only return up to `i64::MAX`. This is
important because this PR is removing the functionality to track fuel
consumption, and this makes the API less error prone for embedders to
track consumption themselves.

Careful to note that the VM counter that is stored as `i64` can be
positive if an instruction "costs" multiple units of fuel when the fuel
ran out.

prtest:full

Signed-off-by: Tyler Rockwood <rockwood@redpanda.com>
@alexcrichton alexcrichton added this pull request to the merge queue Oct 23, 2023
Merged via the queue into bytecodealliance:main with commit 85c0a2d Oct 23, 2023
40 checks passed
@rockwotj rockwotj deleted the fuel2 branch October 24, 2023 00:10
kpreisser added a commit to kpreisser/wasmtime-dotnet that referenced this pull request Oct 24, 2023
peterhuene pushed a commit to bytecodealliance/wasmtime-dotnet that referenced this pull request Oct 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fuzzing Issues related to our fuzzing infrastructure wasmtime:api Related to the API of the `wasmtime` crate itself wasmtime:c-api Issues pertaining to the C API. wasmtime:config Issues related to the configuration of Wasmtime
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Simplifying fuel APIs
2 participants