-
Notifications
You must be signed in to change notification settings - Fork 798
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
feat(c-api) Introduce the middleware (specifically metering) C API #2103
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the wasmer_metering_points_value
, wasmer_metering_points_is_exhausted
and wasmer_metering_get_remaining_points
can be simplified.
Right know, to get the points you have to do: wasmer_metering_get_remaining_points
, ask if wasmer_metering_points_is_exhausted
and then wasmer_metering_get_remaining_points
.
This ties very close to the inner Rust structures but made the usage harder.
I think one simpler thing that we can do is to have wasmer_metering_get_remaining_points
return the remaining points integer directly if it's not exhausted and -1
in case is exhausted.
Tests
Apart from that, we will need to test the metering API. Probably you can use the inline-c
crate macros for testing as we do it with other C-APi tests.
Yep, that's a good change! The only adjustment to that is that instead of returning |
I think that still makes the API a bit more complicated, and I'm failing to see the use case for a custom number that is not the "special case". What is the use case that you think we will cover with having the user to provide the exhausted value? |
…_t`. Also, move it into the `unstable::middleware` module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems great! 👍
Last comment I would add is it would be awesome to have a cost function example.
User-defined cost function isn't working yet :-). Working on it! |
…Copy`. The `F` parameter for `Metering`, and therefore for `FunctionMetering`, no longer requires to implement the `Clone` and `Copy` traits.
bors try |
tryBuild failed: |
bors try |
tryBuild failed: |
bors try |
…_points_are_exhausted`.
//! // Define our “cost function”. | ||
//! uint64_t cost_function(wasmer_parser_operator_t operator) { | ||
//! switch(operator) { | ||
//! // `local.get` and `i32.const` cost 1 unit. | ||
//! case LocalGet: | ||
//! case I32Const: | ||
//! return 1; | ||
//! | ||
//! // `i32.add` costs 2 units. | ||
//! case I32Add: | ||
//! return 2; | ||
//! | ||
//! // The other operations are free. | ||
//! default: | ||
//! return 0; | ||
//! } | ||
//! } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional: It might be worth using a more realistic cost function for the example?
a) the four Const operations are 0
b) F32Div and F64Div are cost 2
c) everything else is cost 1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've taken the example from examples/metering.rs
. It fits well with the simple WAT module. Thoughts?
@@ -0,0 +1,1017 @@ | |||
use wasmer::wasmparser::Operator; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clearly this file should be produced by a proc-macro that runs over wasmparser.
No action required. Please.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤣
@@ -317,7 +317,7 @@ impl NativeArtifact { | |||
if is_cross_compiling { | |||
Self::from_parts_crosscompiled(metadata, shared_filepath) | |||
} else { | |||
let lib = Library::new(&shared_filepath).map_err(to_compile_error)?; | |||
let lib = unsafe { Library::new(&shared_filepath).map_err(to_compile_error)? }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically this is part of a different PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah but I want to see green tests in this PR for the moment.
tryBuild failed: |
bors try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bors r+
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good!
/// See module's documentation. | ||
#[allow(non_camel_case_types)] | ||
pub type wasmer_metering_cost_function_t = | ||
extern "C" fn(wasm_operator: wasmer_parser_operator_t) -> u64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically should probably be an unsafe
function, but it's a minor point here because we immediately wrap it anyways. Only really matters if it has greater contact with Rust code.
/// | ||
/// See the documentation of the [`metering`] module. | ||
#[no_mangle] | ||
pub extern "C" fn wasm_config_push_middleware( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd assume middleware happens at a higher level than wasm_config
, as wasm_config
is used for setting up the initial engine / store. Not a huge deal, but it means that it's harder to share a store with modules using different middlewares. (I'm just assuming we allow a more flexible usage in the Rust API)
Edit by @Hywan: Fixes #2025.