Add epoch-based interruption for cooperative async timeslicing.
This PR introduces a new way of performing cooperative timeslicing that is intended to replace the "fuel" mechanism. The tradeoff is that this mechanism interrupts with less precision: not at deterministic points where fuel runs out, but rather when the Engine enters a new epoch. The generated code instrumentation is substantially faster, however, because it does not need to do as much work as when tracking fuel; it only loads the global "epoch counter" and does a compare-and-branch at backedges and function prologues. This change has been measured as ~twice as fast as fuel-based timeslicing for some workloads, especially control-flow-intensive workloads such as the SpiderMonkey JS interpreter on Wasm/WASI. The intended interface is that the embedder of the `Engine` performs an `engine.increment_epoch()` call periodically, e.g. once per millisecond. An async invocation of a Wasm guest on a `Store` can specify a number of epoch-ticks that are allowed before an async yield back to the executor's event loop. (The initial amount and automatic "refills" are configured on the `Store`, just as for fuel.) This call does only signal-safe work (it increments an `AtomicU64`) so could be invoked from a periodic signal, or from a thread that wakes up once per period.
This commit is contained in:
@@ -20,6 +20,8 @@
|
||||
)
|
||||
)]
|
||||
|
||||
use std::sync::atomic::AtomicU64;
|
||||
|
||||
use anyhow::Error;
|
||||
|
||||
mod export;
|
||||
@@ -84,6 +86,11 @@ pub unsafe trait Store {
|
||||
/// in the `VMContext`.
|
||||
fn vminterrupts(&self) -> *mut VMInterrupts;
|
||||
|
||||
/// Returns a pointer to the global epoch counter.
|
||||
///
|
||||
/// Used to configure the `VMContext` on initialization.
|
||||
fn epoch_ptr(&self) -> *const AtomicU64;
|
||||
|
||||
/// Returns the externref management structures necessary for this store.
|
||||
///
|
||||
/// The first element returned is the table in which externrefs are stored
|
||||
@@ -119,4 +126,8 @@ pub unsafe trait Store {
|
||||
/// is returned that's raised as a trap. Otherwise wasm execution will
|
||||
/// continue as normal.
|
||||
fn out_of_gas(&mut self) -> Result<(), Error>;
|
||||
/// Callback invoked whenever an instance observes a new epoch
|
||||
/// number. Cannot fail; cooperative epoch-based yielding is
|
||||
/// completely semantically transparent. Returns the new deadline.
|
||||
fn new_epoch(&mut self) -> Result<u64, Error>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user