@@ -76,14 +76,56 @@ impl Instance {
7676 }
7777}
7878
79+ /// Configuration for profiling Wasm execution.
80+ ///
81+ /// Viceroy supports two types of profiling:
82+ /// - **Guest profiling**: Profiles the WebAssembly guest code itself, producing Firefox profiler compatible JSON.
83+ /// - **Native profiling**: Profiles wasmtime's JIT compiler for debugging across guest, viceroy and wasmtime.
7984#[ derive( Clone ) ]
80- pub struct GuestProfileConfig {
81- /// Path to write profiling results from the guest. In serve mode,
82- /// this must refer to a directory, while in run mode it names
83- /// a file.
84- pub path : PathBuf ,
85- /// Period at which the guest should be profiled.
86- pub sample_period : Duration ,
85+ pub enum ProfilingConfig {
86+ /// No profiling enabled
87+ None ,
88+ /// Profile the WebAssembly guest code
89+ Guest {
90+ /// Path to write profiling results. In serve mode, this should be a directory
91+ /// where per-request profiles are written. In run mode, this is a single file.
92+ path : PathBuf ,
93+ /// Period at which the guest should be sampled (default: 50μs)
94+ sample_period : Duration ,
95+ } ,
96+ /// Profile wasmtime's JIT compiler using native profiling tools
97+ Native ( wasmtime:: ProfilingStrategy ) ,
98+ }
99+
100+ impl ProfilingConfig {
101+ /// Get the native profiling strategy for wasmtime
102+ pub fn native_strategy ( & self ) -> wasmtime:: ProfilingStrategy {
103+ match self {
104+ ProfilingConfig :: Native ( strategy) => * strategy,
105+ _ => wasmtime:: ProfilingStrategy :: None ,
106+ }
107+ }
108+
109+ /// Get the guest profile configuration if guest profiling is enabled
110+ fn guest_config ( & self ) -> Option < GuestProfileConfig > {
111+ match self {
112+ ProfilingConfig :: Guest {
113+ path,
114+ sample_period,
115+ } => Some ( GuestProfileConfig {
116+ path : path. clone ( ) ,
117+ sample_period : * sample_period,
118+ } ) ,
119+ _ => None ,
120+ }
121+ }
122+ }
123+
124+ // Keep GuestProfileConfig internal for now to maintain backwards compatibility
125+ #[ derive( Clone ) ]
126+ struct GuestProfileConfig {
127+ path : PathBuf ,
128+ sample_period : Duration ,
87129}
88130
89131pub struct NextRequest ( Option < ( DownstreamRequest , Arc < ExecuteCtx > ) > ) ;
@@ -165,12 +207,11 @@ pub struct ExecuteCtx {
165207}
166208
167209impl ExecuteCtx {
168- /// Build a new execution context, given the path to a module and a set of experimental wasi modules .
210+ /// Build a new execution context with unified profiling configuration .
169211 pub fn build (
170212 module_path : impl AsRef < Path > ,
171- profiling_strategy : ProfilingStrategy ,
213+ profiling : ProfilingConfig ,
172214 wasi_modules : HashSet < ExperimentalModule > ,
173- guest_profile_config : Option < GuestProfileConfig > ,
174215 unknown_import_behavior : UnknownImportBehavior ,
175216 adapt_components : bool ,
176217 ) -> Result < ExecuteCtxBuilder , Error > {
@@ -200,7 +241,7 @@ impl ExecuteCtx {
200241 ( is_wat, is_component, input)
201242 } ;
202243
203- let config = & configure_wasmtime ( is_component, profiling_strategy ) ;
244+ let config = & configure_wasmtime ( is_component, profiling . native_strategy ( ) ) ;
204245 let engine = Engine :: new ( config) ?;
205246 let instance_pre = if is_component {
206247 warn ! (
@@ -278,7 +319,8 @@ impl ExecuteCtx {
278319 let epoch_increment_stop = Arc :: new ( AtomicBool :: new ( false ) ) ;
279320 let engine_clone = engine. clone ( ) ;
280321 let epoch_increment_stop_clone = epoch_increment_stop. clone ( ) ;
281- let sample_period = guest_profile_config
322+ let sample_period = profiling
323+ . guest_config ( )
282324 . as_ref ( )
283325 . map ( |c| c. sample_period )
284326 . unwrap_or ( DEFAULT_EPOCH_INTERRUPTION_PERIOD ) ;
@@ -309,28 +351,28 @@ impl ExecuteCtx {
309351 shielding_sites : ShieldingSites :: new ( ) ,
310352 epoch_increment_thread,
311353 epoch_increment_stop,
312- guest_profile_config : guest_profile_config . map ( |c| Arc :: new ( c ) ) ,
354+ guest_profile_config : profiling . guest_config ( ) . map ( Arc :: new) ,
313355 cache : Arc :: new ( Cache :: default ( ) ) ,
314356 pending_reuse : Arc :: new ( AsyncMutex :: new ( vec ! [ ] ) ) ,
315357 } ;
316358
317359 Ok ( ExecuteCtxBuilder { inner } )
318360 }
319361
320- /// Create a new execution context, given the path to a module and a set of experimental wasi modules.
362+ /// Create a new execution context with unified profiling configuration.
363+ ///
364+ /// This is a convenience wrapper around `build().finish()`.
321365 pub fn new (
322366 module_path : impl AsRef < Path > ,
323- profiling_strategy : ProfilingStrategy ,
367+ profiling : ProfilingConfig ,
324368 wasi_modules : HashSet < ExperimentalModule > ,
325- guest_profile_config : Option < GuestProfileConfig > ,
326369 unknown_import_behavior : UnknownImportBehavior ,
327370 adapt_components : bool ,
328371 ) -> Result < Arc < Self > , Error > {
329372 ExecuteCtx :: build (
330373 module_path,
331- profiling_strategy ,
374+ profiling ,
332375 wasi_modules,
333- guest_profile_config,
334376 unknown_import_behavior,
335377 adapt_components,
336378 ) ?
@@ -415,11 +457,12 @@ impl ExecuteCtx {
415457 /// ```no_run
416458 /// # use std::collections::HashSet;
417459 /// use hyper::{Body, http::Request};
418- /// # use viceroy_lib::{Error, ExecuteCtx, ProfilingStrategy, ViceroyService};
460+ /// # use viceroy_lib::{Error, ExecuteCtx, ProfilingConfig, ViceroyService};
461+ /// # use viceroy_lib::config::UnknownImportBehavior;
419462 /// # async fn f() -> Result<(), Error> {
420463 /// # let req = Request::new(Body::from(""));
421464 /// let adapt_core_wasm = false;
422- /// let ctx = ExecuteCtx::new("path/to/a/file.wasm", ProfilingStrategy ::None, HashSet::new(), None, Default::default() , adapt_core_wasm)?;
465+ /// let ctx = ExecuteCtx::new("path/to/a/file.wasm", ProfilingConfig ::None, HashSet::new(), UnknownImportBehavior::LinkError , adapt_core_wasm)?;
423466 /// let local = "127.0.0.1:80".parse().unwrap();
424467 /// let remote = "127.0.0.1:0".parse().unwrap();
425468 /// let resp = ctx.handle_request(req, local, remote).await?;
0 commit comments