Repository navigation
feat(cli): add walltime unwinding mode and stack sample size options - #586
not-matthias wants to merge 2 commits into
Conversation
Add --walltime-unwinding-mode (CODSPEED_WALLTIME_UNWINDING_MODE) and --walltime-stack-sample-size (CODSPEED_WALLTIME_STACK_SAMPLE_SIZE) so the call-stack collection can be tuned for both walltime profilers, perf and samply. --perf-unwinding-mode / CODSPEED_PERF_UNWINDING_MODE stays as a hidden, deprecated alias so existing setups keep working; the new option wins when both are set. perf: the explicit stack size overrides the size inferred from the command (default 8192 bytes). samply: on Linux, forward the options as --unwinding-mode and --stack-size.
Match the option name added to samply-codspeed.
Merging this PR will not alter performance
|
|
| log::warn!( | ||
| "CODSPEED_PERF_UNWINDING_MODE / --perf-unwinding-mode is deprecated; use CODSPEED_WALLTIME_UNWINDING_MODE / --walltime-unwinding-mode instead." | ||
| ); |
There was a problem hiding this comment.
Deprecation warning never appears
Both codspeed run and codspeed exec call resolve_unwinding_mode() while building the config, before Orchestrator::new() installs the logger. This drops the warning, so users of --perf-unwinding-mode or CODSPEED_PERF_UNWINDING_MODE never learn about the replacement. Emit it after logger setup or use the existing startup-warning approach.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cli/shared.rs
Line: 258-260
Comment:
**Deprecation warning never appears**
Both `codspeed run` and `codspeed exec` call `resolve_unwinding_mode()` while building the config, before `Orchestrator::new()` installs the logger. This drops the warning, so users of `--perf-unwinding-mode` or `CODSPEED_PERF_UNWINDING_MODE` never learn about the replacement. Emit it after logger setup or use the existing startup-warning approach.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
@not-matthias, this is a legit thing, and it's extremely annoying.
We may want to have a first logger before the full environment parsing at some point, or queue the logs until we've initialized the logger.
We could create a dedicated issue and just eprintln!() here
| pub fn resolve_unwinding_mode(&self) -> Option<UnwindingMode> { | ||
| let Some(legacy) = self.perf_unwinding_mode else { | ||
| return self.walltime_unwinding_mode; | ||
| }; | ||
| log::warn!( | ||
| "CODSPEED_PERF_UNWINDING_MODE / --perf-unwinding-mode is deprecated; use CODSPEED_WALLTIME_UNWINDING_MODE / --walltime-unwinding-mode instead." | ||
| ); | ||
| Some(self.walltime_unwinding_mode.unwrap_or(legacy)) |
There was a problem hiding this comment.
The new precedence and stack-size overrides have no tests. Add focused cases for the old option alone, both options together, flag/environment combinations, and an explicit size overriding both the default and Python's inferred size. These are the main promises of this change; tests would catch later edits that silently send the wrong value to the profiler.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cli/shared.rs
Line: 254-261
Comment:
**Option rules lack tests**
The new precedence and stack-size overrides have no tests. Add focused cases for the old option alone, both options together, flag/environment combinations, and an explicit size overriding both the default and Python's inferred size. These are the main promises of this change; tests would catch later edits that silently send the wrong value to the profiler.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
I don't think we really care for this one
There was a problem hiding this comment.
Fair point — these tests are useful for regression protection but not essential to this change, so I’m withdrawing the suggestion. No action needed.
GuillaumeLagrange
left a comment
There was a problem hiding this comment.
some few quirks to make sure we handle properly
| /// Size in bytes of the user stack copied with each sample for DWARF unwinding. | ||
| /// Larger values produce deeper call stacks but bigger profiles. |
There was a problem hiding this comment.
we could provide the default value per language here if we expect users/agents to use this now
| log::warn!( | ||
| "CODSPEED_PERF_UNWINDING_MODE / --perf-unwinding-mode is deprecated; use CODSPEED_WALLTIME_UNWINDING_MODE / --walltime-unwinding-mode instead." | ||
| ); |
There was a problem hiding this comment.
@not-matthias, this is a legit thing, and it's extremely annoying.
We may want to have a first logger before the full environment parsing at some point, or queue the logs until we've initialized the logger.
We could create a dedicated issue and just eprintln!() here
| pub fn resolve_unwinding_mode(&self) -> Option<UnwindingMode> { | ||
| let Some(legacy) = self.perf_unwinding_mode else { | ||
| return self.walltime_unwinding_mode; | ||
| }; | ||
| log::warn!( | ||
| "CODSPEED_PERF_UNWINDING_MODE / --perf-unwinding-mode is deprecated; use CODSPEED_WALLTIME_UNWINDING_MODE / --walltime-unwinding-mode instead." | ||
| ); | ||
| Some(self.walltime_unwinding_mode.unwrap_or(legacy)) |
There was a problem hiding this comment.
I don't think we really care for this one
| /// Stack unwinding mode for the walltime profiler (if None, inferred from the command) | ||
| pub walltime_unwinding_mode: Option<UnwindingMode>, | ||
| /// User stack size in bytes copied per sample for DWARF unwinding (if None, profiler default) | ||
| pub walltime_stack_sample_size: Option<u32>, |
There was a problem hiding this comment.
I understand the separate flags for the cli, but here we could have them grouped? Cause technically the sample size makes no sense for fp etc, so even for clap it could make sense to parse it as an enum with two variants
FramePointer
and
Dwarf(Option<u32>) with the Option being here to see if we have an explicit setting or if we should default
| if let Some(mode) = config.walltime_unwinding_mode { | ||
| let mode = match mode { | ||
| UnwindingMode::FramePointer => "fp", | ||
| UnwindingMode::Dwarf => "dwarf", | ||
| }; | ||
| args.extend(["--unwinding-mode".into(), mode.into()]); | ||
| } | ||
| if let Some(size) = config.walltime_stack_sample_size { | ||
| args.extend(["--unwinding-stack-size".into(), size.to_string().into()]); | ||
| } |
There was a problem hiding this comment.
You may want to check the implementation, but I'm 95% sure that in our samply fork we do both, so we should make sure we're not introducing unexpected behavior here
|
|
||
| // Infer the unwinding mode from the benchmark cmd | ||
| let (cg_mode, stack_size) = if let Some(mode) = config.perf_unwinding_mode { | ||
| let (cg_mode, stack_size) = if let Some(mode) = config.walltime_unwinding_mode { |
There was a problem hiding this comment.
For the python/cargo/go tests:
We should not override specific stack size from cli IMO.
AND if we override it, we should DEFINITELY print a warning, but I think we should just outright take explicit cli over anything else
Summary
--walltime-unwinding-mode/CODSPEED_WALLTIME_UNWINDING_MODEand--walltime-stack-sample-size/CODSPEED_WALLTIME_STACK_SAMPLE_SIZE.--perf-unwinding-mode/CODSPEED_PERF_UNWINDING_MODEas a hidden, deprecated alias. The new option wins when both are set.--unwinding-modeand--unwinding-stack-size.Notes