diff --git a/Cargo.lock b/Cargo.lock index 315d9a52..dee817ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1509,7 +1509,7 @@ dependencies = [ [[package]] name = "fxprof-processed-profile" version = "0.8.1" -source = "git+https://github.com/CodSpeedHQ/samply-codspeed?branch=codspeed#7fbe8e5e2412b0cbbab7668f4321d4fbac84529c" +source = "git+https://github.com/CodSpeedHQ/samply-codspeed?rev=72d93a3a#72d93a3a55e214a234d51484f701ab11e56919b0" dependencies = [ "bitflags 2.10.0", "debugid", @@ -4416,7 +4416,7 @@ dependencies = [ [[package]] name = "samply" version = "0.13.1" -source = "git+https://github.com/CodSpeedHQ/samply-codspeed?branch=codspeed#7fbe8e5e2412b0cbbab7668f4321d4fbac84529c" +source = "git+https://github.com/CodSpeedHQ/samply-codspeed?rev=72d93a3a#72d93a3a55e214a234d51484f701ab11e56919b0" dependencies = [ "bitflags 2.10.0", "byteorder", @@ -4485,7 +4485,7 @@ dependencies = [ [[package]] name = "samply-api" version = "0.24.0" -source = "git+https://github.com/CodSpeedHQ/samply-codspeed?branch=codspeed#7fbe8e5e2412b0cbbab7668f4321d4fbac84529c" +source = "git+https://github.com/CodSpeedHQ/samply-codspeed?rev=72d93a3a#72d93a3a55e214a234d51484f701ab11e56919b0" dependencies = [ "samply-debugid", "samply-symbols", @@ -4501,7 +4501,7 @@ dependencies = [ [[package]] name = "samply-debugid" version = "0.1.0" -source = "git+https://github.com/CodSpeedHQ/samply-codspeed?branch=codspeed#7fbe8e5e2412b0cbbab7668f4321d4fbac84529c" +source = "git+https://github.com/CodSpeedHQ/samply-codspeed?rev=72d93a3a#72d93a3a55e214a234d51484f701ab11e56919b0" dependencies = [ "debugid", "uuid", @@ -4510,7 +4510,7 @@ dependencies = [ [[package]] name = "samply-object" version = "0.1.0" -source = "git+https://github.com/CodSpeedHQ/samply-codspeed?branch=codspeed#7fbe8e5e2412b0cbbab7668f4321d4fbac84529c" +source = "git+https://github.com/CodSpeedHQ/samply-codspeed?rev=72d93a3a#72d93a3a55e214a234d51484f701ab11e56919b0" dependencies = [ "debugid", "object 0.39.0", @@ -4521,7 +4521,7 @@ dependencies = [ [[package]] name = "samply-quota-manager" version = "0.1.0" -source = "git+https://github.com/CodSpeedHQ/samply-codspeed?branch=codspeed#7fbe8e5e2412b0cbbab7668f4321d4fbac84529c" +source = "git+https://github.com/CodSpeedHQ/samply-codspeed?rev=72d93a3a#72d93a3a55e214a234d51484f701ab11e56919b0" dependencies = [ "bytesize", "futures", @@ -4535,7 +4535,7 @@ dependencies = [ [[package]] name = "samply-symbols" version = "0.24.1" -source = "git+https://github.com/CodSpeedHQ/samply-codspeed?branch=codspeed#7fbe8e5e2412b0cbbab7668f4321d4fbac84529c" +source = "git+https://github.com/CodSpeedHQ/samply-codspeed?rev=72d93a3a#72d93a3a55e214a234d51484f701ab11e56919b0" dependencies = [ "addr2line 0.26.1", "bitflags 2.10.0", @@ -6016,7 +6016,7 @@ dependencies = [ [[package]] name = "wholesym" version = "0.8.1" -source = "git+https://github.com/CodSpeedHQ/samply-codspeed?branch=codspeed#7fbe8e5e2412b0cbbab7668f4321d4fbac84529c" +source = "git+https://github.com/CodSpeedHQ/samply-codspeed?rev=72d93a3a#72d93a3a55e214a234d51484f701ab11e56919b0" dependencies = [ "bytes", "core-foundation 0.10.1", diff --git a/Cargo.toml b/Cargo.toml index 83dc8fbc..94937bfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,7 +75,7 @@ rmp-serde = "1.3.0" uuid = { version = "1.21.0", features = ["v4"] } which = "8.0.2" crc32fast = "1.5.0" -samply = { git = "https://github.com/CodSpeedHQ/samply-codspeed", branch = "codspeed" } +samply = { git = "https://github.com/CodSpeedHQ/samply-codspeed", rev = "72d93a3a" } # branch = "codspeed" [target.'cfg(target_os = "linux")'.dependencies] procfs = "0.17.0" diff --git a/src/executor/helpers/command.rs b/src/executor/helpers/command.rs index bdbc4e1c..31a678ee 100644 --- a/src/executor/helpers/command.rs +++ b/src/executor/helpers/command.rs @@ -48,7 +48,6 @@ impl CommandBuilder { self } - #[cfg(target_os = "macos")] pub fn env(&mut self, key: K, value: V) -> &mut Self where K: AsRef, @@ -59,6 +58,18 @@ impl CommandBuilder { self } + pub fn envs(&mut self, vars: I) -> &mut Self + where + I: IntoIterator, + K: AsRef, + V: AsRef, + { + for (k, v) in vars { + self.env(k, v); + } + self + } + pub fn current_dir(&mut self, dir: D) where D: AsRef, diff --git a/src/executor/wall_time/executor.rs b/src/executor/wall_time/executor.rs index 93f9b989..93946736 100644 --- a/src/executor/wall_time/executor.rs +++ b/src/executor/wall_time/executor.rs @@ -88,17 +88,33 @@ pub struct WallTimeExecutor { benchmark_state: OnceCell<(FifoBenchmarkData, ExecutionTimestamps)>, } +fn select_profiler() -> Option> { + const PROFILER_OVERRIDE_ENV: &str = "CODSPEED_WALLTIME_PROFILER"; + + match std::env::var(PROFILER_OVERRIDE_ENV).ok().as_deref() { + Some("perf") => return Some(Box::new(PerfProfiler::new())), + Some("samply") => return Some(Box::new(SamplyProfiler::new())), + Some(other) => { + warn!( + "Ignoring unknown {PROFILER_OVERRIDE_ENV}={other:?}; expected `perf` or `samply`." + ); + } + None => {} + } + + if cfg!(target_os = "linux") { + Some(Box::new(PerfProfiler::new())) + } else if cfg!(target_os = "macos") { + Some(Box::new(SamplyProfiler::new())) + } else { + None + } +} + impl WallTimeExecutor { pub fn new() -> Self { - let profiler: Option> = if cfg!(target_os = "linux") { - Some(Box::new(PerfProfiler::new())) - } else if cfg!(target_os = "macos") { - Some(Box::new(SamplyProfiler::new())) - } else { - None - }; Self { - profiler, + profiler: select_profiler(), benchmark_state: OnceCell::new(), } } @@ -106,6 +122,7 @@ impl WallTimeExecutor { fn walltime_bench_cmd( config: &ExecutorConfig, execution_context: &ExecutionContext, + isolate: bool, ) -> Result<(NamedTempFile, NamedTempFile, CommandBuilder)> { let path_value = build_path_env(config.enable_introspection)?; @@ -130,7 +147,11 @@ impl WallTimeExecutor { bench_cmd.current_dir(abs_cwd); } - let bench_cmd = wrap_with_isolation(bench_cmd)?; + let bench_cmd = if isolate { + wrap_with_isolation(bench_cmd)? + } else { + bench_cmd + }; Ok((env_file, script_file, bench_cmd)) } @@ -168,8 +189,15 @@ impl Executor for WallTimeExecutor { ) -> Result<()> { let _guard = HookScriptsGuard::setup(); - let (_env_file, _script_file, cmd_builder) = - WallTimeExecutor::walltime_bench_cmd(&execution_context.config, execution_context)?; + let isolate = self + .profiler + .as_ref() + .is_none_or(|p| p.requires_isolation()); + let (_env_file, _script_file, cmd_builder) = WallTimeExecutor::walltime_bench_cmd( + &execution_context.config, + execution_context, + isolate, + )?; // Split-borrow `self` so the closure inside `run_with_profiler` can // capture `benchmark_state` while we hold `&mut profiler`. diff --git a/src/executor/wall_time/profiler/mod.rs b/src/executor/wall_time/profiler/mod.rs index 524d59de..3874fc5f 100644 --- a/src/executor/wall_time/profiler/mod.rs +++ b/src/executor/wall_time/profiler/mod.rs @@ -33,6 +33,12 @@ pub trait Profiler { None } + /// Whether the benchmark command should be wrapped with the Linux + /// systemd-run isolation scope. + fn requires_isolation(&self) -> bool { + true + } + /// One-time system setup (install tool, tweak sysctls, ...). async fn setup( &self, diff --git a/src/executor/wall_time/profiler/samply/mod.rs b/src/executor/wall_time/profiler/samply/mod.rs index e56ee41b..35c2b34a 100644 --- a/src/executor/wall_time/profiler/samply/mod.rs +++ b/src/executor/wall_time/profiler/samply/mod.rs @@ -46,6 +46,10 @@ impl SamplyProfiler { #[async_trait(?Send)] impl Profiler for SamplyProfiler { + fn requires_isolation(&self) -> bool { + false + } + async fn setup( &self, _system_info: &SystemInfo, @@ -101,6 +105,17 @@ impl Profiler for SamplyProfiler { cmd_builder.wrap_with(samply_builder); + cmd_builder.envs([ + // Disable JIT classification as it produces duplicates symbols in + // Node.js for the Interpreter frames. + ("SAMPLY_DISABLE_JIT_CLASSIFICATION", "1"), + ("SAMPLY_USE_DEBUGINFOD", "1"), + ( + "SAMPLY_BREAKPAD_SYMBOL_SERVER", + "https://symbols.mozilla.org/,https://symbols.electronjs.org/", + ), + ]); + // If `setup` decided the bash on PATH is Apple-signed, prepend brew's // bin so samply's spawned shell resolves to the ad-hoc-signed brew bash // instead. Only the samply child's PATH is touched.