Stream: git-wasmtime

Topic: wasmtime / issue #5109 More control over fuel consumption


view this post on Zulip Wasmtime GitHub notifications bot (Oct 24 2022 at 20:03):

coolreader18 opened issue #5109:

Feature

A set of new APIs that provide more control over fuel consumption:

impl Config {
    #[cfg(feature = "custom-fuel-cost")]
    fn fuel_cost(&mut self, f: impl Fn(&wasmparser::Operator<'_>) -> u64 + Send + Sync + 'static) -> &mut Self;
}
impl Store {
    fn fuel_remaining(&self) -> Option<u64>;
    /// Returns an error if the store is not configured for fuel consumption
    fn set_fuel(&mut self, value: u64) -> Result<()>;
}

Benefit

Allows more direct control over fuel consumption and filling, letting users set custom fuel costs for each operand if they deem some to be more costly/intensive in their environment, as well letting them set precisely how much fuel they might allow a single function call or set of function calls.

Implementation

I have an implementation for the custom fuel cost configuration, and the methods on Store should be fairly trivial.

Alternatives

fuel_remaining and set_fuel can be approximated by consume_fuel(0) and if new_fuel > fuel_remaining() { add_fuel(delta) } else { consume_fuel(delta) } respectively. fuel_cost cannot be emulated, so the alternative is to just accept wasmtime's default cost function. As an alternative in designing the API, the fuel_cost closure could perhaps take a wasmtime::Operator or wasmtime::OperatorCategory enum, so as to avoid exposing wasmparser in the public API. However, both of those approaches have issues (a duplicate Operator is.. okay actually thinking about it, if it were to just define another enum Operator using wasmparser::for_each_operator! that might not be too bad. That's a valid second option, if wasmparser in public API (behind a feature flag) isn't something that's desirable.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 24 2022 at 20:08):

coolreader18 edited issue #5109:

Feature

A set of new APIs that provide more control over fuel consumption:

impl Config {
    #[cfg(feature = "custom-fuel-cost")]
    fn fuel_cost(&mut self, f: impl Fn(&wasmparser::Operator<'_>) -> u64 + Send + Sync + 'static) -> &mut Self;
}
impl Store {
    fn fuel_remaining(&self) -> Option<u64>;
    /// Returns an error if the store is not configured for fuel consumption
    fn set_fuel(&mut self, value: u64) -> Result<()>;
}

Benefit

Allows more direct control over fuel consumption and filling, letting users set custom fuel costs for each operand if they deem some to be more costly/intensive in their environment, as well letting them set precisely how much fuel they might allow a single function call or set of function calls.

Implementation

I have an implementation for the custom fuel cost configuration, and the methods on Store should be fairly trivial.

Alternatives

fuel_remaining and set_fuel can be approximated by consume_fuel(0) and if new_fuel > fuel_remaining() { add_fuel(delta) } else { consume_fuel(delta) } respectively. fuel_cost cannot be emulated, so the alternative is to just accept wasmtime's default cost function. As an alternative in designing the API, the fuel_cost closure could perhaps take a wasmtime::Operator or wasmtime::OperatorCategory enum, so as to avoid exposing wasmparser in the public API. However, both of those approaches have issues (a duplicate Operator is.. okay actually thinking about it, if it were to just define another enum Operator using wasmparser::for_each_operator! (maybe without the parameters at all, just the opcodes themselves?) that might not be too bad. That's a valid second option, if wasmparser in public API (behind a feature flag) isn't something that's desirable.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 24 2022 at 20:09):

coolreader18 edited issue #5109:

Feature

A set of new APIs that provide more control over fuel consumption:

impl Config {
    #[cfg(feature = "custom-fuel-cost")]
    fn fuel_cost(&mut self, f: impl Fn(&wasmparser::Operator<'_>) -> u64 + Send + Sync + 'static) -> &mut Self;
}
impl Store {
    fn fuel_remaining(&self) -> Option<u64>;
    /// Returns an error if the store is not configured for fuel consumption
    fn set_fuel(&mut self, value: u64) -> Result<()>;
}

Benefit

Allows more direct control over fuel consumption and filling, letting users set custom fuel costs for each operand if they deem some to be more costly/intensive in their environment, as well letting them set precisely how much fuel they might allow a single function call or set of function calls.

Implementation

I have an implementation for the custom fuel cost configuration, and the methods on Store should be fairly trivial.

Alternatives

fuel_remaining and set_fuel can be approximated by consume_fuel(0) and if new_fuel > fuel_remaining() { add_fuel(delta) } else { consume_fuel(delta) } respectively. fuel_cost cannot be emulated, so the alternative is to just accept wasmtime's default cost function. As an alternative in designing the API, the fuel_cost closure could perhaps take a wasmtime::Operator or wasmtime::OperatorCategory enum, so as to avoid exposing wasmparser in the public API. However, both of those approaches have issues (a duplicate Operator is.. okay actually thinking about it, if it were to just define another enum Operator using wasmparser::for_each_operator! (maybe without the parameters at all, just the opcodes themselves?) that might not be too bad. That's a valid second option, if wasmparser in public API (behind a feature flag) isn't something that's desirable.
Edit: actually yeah that sounds like a really good idea I'm gonna change my impl to do that.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 24 2022 at 21:13):

coolreader18 edited issue #5109:

Feature

A set of new APIs that provide more control over fuel consumption:

impl Config {
    #[cfg(feature = "custom-fuel-cost")]
    fn fuel_cost(&mut self, f: impl Fn(&wasmparser::Operator<'_>) -> u64 + Send + Sync + 'static) -> &mut Self;
}
impl Store {
    fn fuel_remaining(&self) -> Option<u64>;
    /// Returns an error if the store is not configured for fuel consumption
    fn set_fuel(&mut self, value: u64) -> Result<()>;
}
#[non_exhaustive]
struct OutOfFuelError;

Benefit

Allows more direct control over fuel consumption and filling, letting users set custom fuel costs for each operand if they deem some to be more costly/intensive in their environment, as well letting them set precisely how much fuel they might allow a single function call or set of function calls. OutOfFuelError being made public allows users to check when a Trap was caused by fuel running out.

Implementation

I have an implementation for the custom fuel cost configuration, and the methods on Store should be fairly trivial.

Alternatives

fuel_remaining and set_fuel can be approximated by consume_fuel(0) and if new_fuel > fuel_remaining() { add_fuel(delta) } else { consume_fuel(delta) } respectively. fuel_cost cannot be emulated, so the alternative is to just accept wasmtime's default cost function. As an alternative in designing the API, the fuel_cost closure could perhaps take a wasmtime::Operator or wasmtime::OperatorCategory enum, so as to avoid exposing wasmparser in the public API. However, both of those approaches have issues (a duplicate Operator is.. okay actually thinking about it, if it were to just define another enum Operator using wasmparser::for_each_operator! (maybe without the parameters at all, just the opcodes themselves?) that might not be too bad. That's a valid second option, if wasmparser in public API (behind a feature flag) isn't something that's desirable.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 24 2022 at 21:18):

coolreader18 edited issue #5109:

Feature

A set of new APIs that provide more control over fuel consumption:

impl Config {
    #[cfg(feature = "custom-fuel-cost")]
    fn fuel_cost(&mut self, f: impl Fn(&wasmparser::Operator<'_>) -> u64 + Send + Sync + 'static) -> &mut Self;
}
impl Store {
    fn fuel_remaining(&self) -> Option<u64>;
    /// Returns an error if the store is not configured for fuel consumption
    fn set_fuel(&mut self, value: u64) -> Result<()>;
}
#[non_exhaustive]
struct OutOfFuelError;

Benefit

Allows more direct control over fuel consumption and filling, letting users set custom fuel costs for each operand if they deem some to be more costly/intensive in their environment, as well letting them set precisely how much fuel they might allow a single function call or set of function calls. OutOfFuelError being made public allows users to check when a Trap was caused by fuel running out.

Implementation

I have an implementation for the custom fuel cost configuration, and the methods on Store should be fairly trivial.

Alternatives

fuel_remaining and set_fuel can be approximated by consume_fuel(0) and if new_fuel > fuel_remaining() { add_fuel(delta) } else { consume_fuel(delta) } respectively. fuel_cost cannot be emulated, so the alternative is to just accept wasmtime's default cost function. As an alternative in designing the API, the fuel_cost closure could perhaps take a wasmtime::Operator or wasmtime::OperatorCategory enum, so as to avoid exposing wasmparser in the public API. However, both of those approaches have issues (a duplicate Operator is.. okay actually thinking about it, if it were to just define another enum Operator using wasmparser::for_each_operator! (maybe without the parameters at all, just the opcodes themselves?) that might not be too bad. That's a valid second option, if wasmparser in public API (behind a feature flag) isn't something that's desirable.
Edit: actually yeah that sounds like a really good idea I'm gonna change my impl to do that.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 24 2022 at 21:20):

coolreader18 commented on issue #5109:

Oh, looks like wasmtime-fuzzing has a shim for set_fuel the same as I described:

https://github.com/bytecodealliance/wasmtime/blob/main/crates/fuzzing/src/oracles.rs#L790-L802

view this post on Zulip Wasmtime GitHub notifications bot (Oct 24 2022 at 21:23):

coolreader18 edited issue #5109:

Feature

A set of new APIs that provide more control over fuel consumption:

impl Config {
    fn fuel_cost(&mut self, f: impl Fn(WasmOpcode) -> u64 + Send + Sync + 'static) -> &mut Self;
}
enum WasmOpcode {
    Unreachable,
    Nop,
    Block,
    Loop,
    // ...
}
impl Store {
    fn fuel_remaining(&self) -> Option<u64>;
    /// Returns an error if the store is not configured for fuel consumption
    fn set_fuel(&mut self, value: u64) -> Result<()>;
}
#[non_exhaustive]
struct OutOfFuelError;

Benefit

Allows more direct control over fuel consumption and filling, letting users set custom fuel costs for each operand if they deem some to be more costly/intensive in their environment, as well letting them set precisely how much fuel they might allow a single function call or set of function calls. OutOfFuelError being made public allows users to check when a Trap was caused by fuel running out.

Implementation

I have an implementation for the custom fuel cost configuration, and the methods on Store should be fairly trivial.

Alternatives

fuel_remaining and set_fuel can be approximated by consume_fuel(0) and if new_fuel > fuel_remaining() { add_fuel(delta) } else { consume_fuel(delta) } respectively. fuel_cost cannot be emulated, so the alternative is to just accept wasmtime's default cost function. As an alternative in designing the API, the fuel_cost closure could take a &wasmparser::Operator<'_> as it did in the original version of this issue. However, that would require exposing wasmparser in wasmtime's public api, which is undesirable.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 08 2023 at 03:40):

howjmay commented on issue #5109:

Hi I am curious why #5220 can help us set customized fuel for each opcode?

view this post on Zulip Wasmtime GitHub notifications bot (Oct 16 2023 at 18:24):

fitzgen closed issue #5109:

Feature

A set of new APIs that provide more control over fuel consumption:

impl Config {
    fn fuel_cost(&mut self, f: impl Fn(WasmOpcode) -> u64 + Send + Sync + 'static) -> &mut Self;
}
enum WasmOpcode {
    Unreachable,
    Nop,
    Block,
    Loop,
    // ...
}
impl Store {
    fn fuel_remaining(&self) -> Option<u64>;
    /// Returns an error if the store is not configured for fuel consumption
    fn set_fuel(&mut self, value: u64) -> Result<()>;
}
#[non_exhaustive]
struct OutOfFuelError;

Benefit

Allows more direct control over fuel consumption and filling, letting users set custom fuel costs for each operand if they deem some to be more costly/intensive in their environment, as well letting them set precisely how much fuel they might allow a single function call or set of function calls. OutOfFuelError being made public allows users to check when a Trap was caused by fuel running out.

Implementation

I have an implementation for the custom fuel cost configuration, and the methods on Store should be fairly trivial.

Alternatives

fuel_remaining and set_fuel can be approximated by consume_fuel(0) and if new_fuel > fuel_remaining() { add_fuel(delta) } else { consume_fuel(delta) } respectively. fuel_cost cannot be emulated, so the alternative is to just accept wasmtime's default cost function. As an alternative in designing the API, the fuel_cost closure could take a &wasmparser::Operator<'_> as it did in the original version of this issue. However, that would require exposing wasmparser in wasmtime's public api, which is undesirable.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 16 2023 at 20:38):

RReverser commented on issue #5109:

Looks like #7240 only adds reset_fuel, I don't think it should've auto-closed this issue?

In particular,

fn fuel_cost(&mut self, f: impl Fn(WasmOpcode) -> u64 + Send + Sync + 'static) -> &mut Self;

this would be still desirable.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 16 2023 at 22:45):

alexcrichton reopened issue #5109:

Feature

A set of new APIs that provide more control over fuel consumption:

impl Config {
    fn fuel_cost(&mut self, f: impl Fn(WasmOpcode) -> u64 + Send + Sync + 'static) -> &mut Self;
}
enum WasmOpcode {
    Unreachable,
    Nop,
    Block,
    Loop,
    // ...
}
impl Store {
    fn fuel_remaining(&self) -> Option<u64>;
    /// Returns an error if the store is not configured for fuel consumption
    fn set_fuel(&mut self, value: u64) -> Result<()>;
}
#[non_exhaustive]
struct OutOfFuelError;

Benefit

Allows more direct control over fuel consumption and filling, letting users set custom fuel costs for each operand if they deem some to be more costly/intensive in their environment, as well letting them set precisely how much fuel they might allow a single function call or set of function calls. OutOfFuelError being made public allows users to check when a Trap was caused by fuel running out.

Implementation

I have an implementation for the custom fuel cost configuration, and the methods on Store should be fairly trivial.

Alternatives

fuel_remaining and set_fuel can be approximated by consume_fuel(0) and if new_fuel > fuel_remaining() { add_fuel(delta) } else { consume_fuel(delta) } respectively. fuel_cost cannot be emulated, so the alternative is to just accept wasmtime's default cost function. As an alternative in designing the API, the fuel_cost closure could take a &wasmparser::Operator<'_> as it did in the original version of this issue. However, that would require exposing wasmparser in wasmtime's public api, which is undesirable.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 17 2023 at 12:02):

rockwotj commented on issue #5109:

Apologies for this getting closed. I was picking up #5220 which also would have closed this issue. Maybe @coolreader18 could update this issue to have it be more about a custom cost function for fuel APIs?

Also if you have opinions on store fuel related APIs would love to hear there here https://github.com/bytecodealliance/wasmtime/issues/7255


Last updated: Dec 23 2024 at 13:07 UTC