pub struct GuestProfiler { /* private fields */ }Expand description
Collects basic profiling data for a single WebAssembly guest.
This profiler can’t provide measurements that are as accurate or detailed
as a platform-specific profiler, such as perf on Linux. On the other
hand, this profiler works on every platform that Wasmtime supports. Also,
as an embedder you can use this profiler selectively on individual guest
instances rather than profiling the entire process.
To use this, you’ll need to arrange to call GuestProfiler::sample at
regular intervals while the guest is on the stack. The most straightforward
way to do that is to call it from a callback registered with
Store::epoch_deadline_callback().
Starting a profile with GuestProfiler::new prepares the profiled
modules each time, which for modules with many functions can take
milliseconds. To profile the same modules many times, for example once per
instance, prepare them once with GuestProfilerModules and start each
profile with GuestProfiler::new_with_modules.
§Accuracy
The data collection granularity is limited by the mechanism you use to interrupt guest execution and collect a profiling sample.
If you use epoch interruption, then samples will only be collected at function entry points and loop headers. This introduces some bias to the results. In addition, samples will only be taken at times when WebAssembly functions are running, not during host-calls.
It is technically possible to use fuel interruption instead. That introduces worse bias since samples occur after a certain number of WebAssembly instructions, which can take different amounts of time.
You may instead be able to use platform-specific methods, such as
setitimer(ITIMER_VIRTUAL, ...) on POSIX-compliant systems, to sample on
a more accurate interval. The only current requirement is that the guest
you wish to profile must be on the same stack where you call sample,
and executing within the same thread. However, the GuestProfiler::sample
method is not currently async-signal-safe, so doing this correctly is not
easy.
§Security
Profiles produced using this profiler do not include any configuration details from the host, such as virtual memory addresses, or from any WebAssembly modules that you haven’t specifically allowed. So for example, these profiles should be safe to share with untrusted users who have provided untrusted code that you are running in a multi-tenancy environment.
However, the profile does include byte offsets into the text section of the compiled module, revealing some information about the size of the code generated for each module. For user-provided modules, the user could get the same information by compiling the module for themself using a similar version of Wasmtime on the same target architecture, but for any module where they don’t already have the WebAssembly module binary available this could theoretically lead to an undesirable information disclosure. So you should only include user-provided modules in profiles.
Implementations§
Source§impl GuestProfiler
impl GuestProfiler
Sourcepub fn new(
engine: &Engine,
module_name: &str,
interval: Duration,
modules: impl IntoIterator<Item = (String, Module)>,
) -> Result<GuestProfiler, Error>
pub fn new( engine: &Engine, module_name: &str, interval: Duration, modules: impl IntoIterator<Item = (String, Module)>, ) -> Result<GuestProfiler, Error>
Begin profiling a new guest. When this function is called, the current wall-clock time is recorded as the start time for the guest.
The module_name parameter is recorded in the profile to help identify
where the profile came from.
The interval parameter should match the rate at which you intend
to call sample. However, this is used as a hint and not required to
exactly match the real sample rate.
Only modules which are present in the modules vector will appear in
stack traces in this profile. Any stack frames which were executing
host code or functions from other modules will be omitted. See the
“Security” section of the GuestProfiler documentation for guidance
on what modules should not be included in this list.
This prepares modules afresh for every profile, which for modules
with many functions is most of this function’s cost. To profile the
same modules repeatedly, prepare them once with
GuestProfilerModules::new and use
GuestProfiler::new_with_modules instead.
§Errors
Returns an error if engine has guest debugging enabled, which
profiling does not support.
§Panics
Panics if any module in modules was not created with engine.
Sourcepub fn new_with_modules(
module_name: &str,
interval: Duration,
modules: &GuestProfilerModules,
) -> GuestProfiler
pub fn new_with_modules( module_name: &str, interval: Duration, modules: &GuestProfilerModules, ) -> GuestProfiler
Begin profiling a new guest using a set of modules prepared with
GuestProfilerModules. When this function is called, the current
wall-clock time is recorded as the start time for the guest.
This behaves like GuestProfiler::new, except that the per-module
preparation has already been done, so starting a profile costs the
same however many functions the modules define. Only modules in
modules will appear in stack traces in this profile.
See GuestProfiler::new for the meaning of module_name and
interval.
Sourcepub fn new_component(
engine: &Engine,
component_name: &str,
interval: Duration,
component: Component,
extra_modules: impl IntoIterator<Item = (String, Module)>,
) -> Result<GuestProfiler, Error>
pub fn new_component( engine: &Engine, component_name: &str, interval: Duration, component: Component, extra_modules: impl IntoIterator<Item = (String, Module)>, ) -> Result<GuestProfiler, Error>
Create a new profiler for the provided component
See GuestProfiler::new for additional information; this function
works identically except that it takes a component and sets up
instrumentation to track calls in each of its constituent modules.
Sourcepub fn sample(&mut self, store: impl AsContext, delta: Duration)
pub fn sample(&mut self, store: impl AsContext, delta: Duration)
Add a sample to the profile. This function collects a backtrace from
any stack frames for allowed modules on the current stack. It should
typically be called from a callback registered using
Store::epoch_deadline_callback().
The delta parameter is the amount of CPU time that was used by this
guest since the previous sample. It is allowed to pass Duration::ZERO
here if recording CPU usage information is not needed.
Sourcepub fn call_hook(&mut self, store: impl AsContext, kind: CallHook)
pub fn call_hook(&mut self, store: impl AsContext, kind: CallHook)
Add a marker for transitions between guest and host to the profile.
This function should typically be called from a callback registered
using Store::call_hook(), and the kind
parameter should be the value of the same type passed into that hook.
Sourcepub fn finish(self, output: impl Write) -> Result<(), Error>
pub fn finish(self, output: impl Write) -> Result<(), Error>
When the guest finishes running, call this function to write the
profile to the given output. The output is a JSON-formatted object in
the Firefox “processed profile format”. Files in this format may
be visualized at https://profiler.firefox.com/.
Trait Implementations§
Auto Trait Implementations§
impl !RefUnwindSafe for GuestProfiler
impl !UnwindSafe for GuestProfiler
impl Freeze for GuestProfiler
impl Send for GuestProfiler
impl Sync for GuestProfiler
impl Unpin for GuestProfiler
impl UnsafeUnpin for GuestProfiler
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more