-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
make ResourceLimiter operate on Store data; add hooks for entering and exiting native code #2952
Conversation
Subscribe to Label Actioncc @peterhuene
This issue or pull request has been labeled: "cranelift", "wasmtime:c-api"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
In preparation of changing wasmtime::ResourceLimiter to be a re-export of this definition, because translating between two traits was causing problems elsewhere.
2ff37c3
to
f9e8c8e
Compare
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.
Ok reading again now that the diff is a bit smaller, this is still looking good. (modulo the Innermost
which I don't know how to make better and isn't really all that bad).
Can you add some tests thouggh for the enter/exit hooks? Ideally we'd have tests ensuring that they fire for all kinds of created host functions (e.g. Linker
-defined, Func
-defined, etc).
Finally, do you think it would make sense to run the hooks around the initial entry point into wasm as well? (e.g. the single entry point into wasm we have in func.rs
).
Subscribe to Label Actioncc @fitzgen, @peterhuene
This issue or pull request has been labeled: "fuzzing", "wasmtime:api"
Thus the following users have been cc'd because of the following labels:
To subscribe or unsubscribe from this label, edit the |
let mut store = Store::new(&engine, ()); | ||
store.limiter(StoreLimitsBuilder::new().memories(10).build()); | ||
let mut store = Store::new(&engine, StoreLimitsBuilder::new().memories(10).build()); | ||
store.limiter(|s| s as &mut dyn ResourceLimiter); |
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.
Is the as &mut dyn ResourceLimiter
required here in that rustc can't infer it?
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.
|s| s
doesn't attempt to coerce s
AFAIK.
Locally I've got two benchmarks for changes like this: host -> wasm overheadfn host_to_wasm_overhead() -> anyhow::Result<()> {
use wasmtime::*;
let engine = Engine::default();
let module = Module::new(
&engine,
r#"
(module
(func (export "run") (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add
)
)
"#,
)?;
let mut store = Store::new(&engine, ());
let instance = Instance::new(&mut store, &module, &[])?;
let run = instance.get_typed_func::<(i32, i32), i32, _>(&mut store, "run")?;
let now = std::time::Instant::now();
let total = 100_000_000;
for _ in 0..total {
run.call(&mut store, (1, 1))?;
}
let time = now.elapsed();
println!(
"use Time: {:?}, each:{} ns/op",
time,
time.as_nanos() / (total as u128)
);
Ok(())
} wasm -> host overheadfn wasm_to_host() -> anyhow::Result<()> {
use wasmtime::*;
let engine = Engine::default();
let module = Module::new(
&engine,
r#"
(module
(import "" "add" (func $add (param i32 i32) (result i32)))
(func (export "run") (param i32)
loop
i32.const 1
i32.const 2
call 0
drop
local.get 0
i32.const -1
i32.add
local.tee 0
br_if 0
end
))
"#,
)?;
let mut store = Store::new(&engine, ());
let func = Func::wrap(&mut store, |a: u32, b: u32| a + b);
let instance = Instance::new(&mut store, &module, &[func.into()])?;
let run = instance.get_typed_func::<i32, (), _>(&mut store, "run")?;
let now = std::time::Instant::now();
let total = 1_000_000_000;
run.call(&mut store, total)?;
let time = now.elapsed();
println!(
"use Time: {:?}, each:{} ns/op",
time,
time.as_nanos() / (total as u128)
);
Ok(())
} The numbers I got for this PR on my local macOS machine are:
So it looks like adding these unconditional branches has pretty negligible overhead. If it really matters in some use case we could always add a compile-time option to disable them, but otherwise I don't think there's too much impact. One thing that's required, though, is to add
|
👍 |
Based on #2897 - draft until that PR lands.
This PR does two things:
ResourceLimiter
trait is now implemented on the data inside aStore
rather than as a standalone owned type. This change required changing the structure of the Store internals a bunch. Additionally, the trait is now defined inwasmtime_runtime
and re-exported bywasmtime
.entering_native_code_hook
andexiting_native_code_hook
, are added toStore
. These functions get to operate on the data inside aStore
much like resource limiter's mut methods. These functions give embedding the opportunity to measure time (or other resources) and trap before entering any native code (i.e. aFunc
) linked into theStore
, and again before returning from that native code.