Skip to content

Commit 1339cb3

Browse files
feat: harvest CPU more performance rustc/cargo build options
1 parent dad7079 commit 1339cb3

2 files changed

Lines changed: 77 additions & 0 deletions

File tree

crates/codspeed/build.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ fn main() {
77

88
collect_rustc_info();
99
collect_cargo_info();
10+
collect_build_profile_info();
1011

1112
let mut build = cc::Build::new();
1213
build
@@ -48,6 +49,41 @@ fn main() {
4849
}
4950
}
5051

52+
/// Collect build profile and performance-relevant compiler options at build time.
53+
/// These env var names must be kept in sync with `src/instrument_hooks/mod.rs`.
54+
///
55+
/// Reference: <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts>
56+
fn collect_build_profile_info() {
57+
// PROFILE is set by Cargo to the name of the profile being built (e.g. "release", "bench", "debug").
58+
if let Ok(profile) = std::env::var("PROFILE") {
59+
println!("cargo:rustc-env=CODSPEED_BUILD_PROFILE={profile}");
60+
}
61+
62+
// OPT_LEVEL is set by Cargo to the optimization level (0, 1, 2, 3, s, z).
63+
if let Ok(opt_level) = std::env::var("OPT_LEVEL") {
64+
println!("cargo:rustc-env=CODSPEED_BUILD_OPT_LEVEL={opt_level}");
65+
}
66+
67+
// Extract performance-relevant codegen flags from rustflags.
68+
//
69+
// Cargo uses two mutually exclusive sources for rustflags (see
70+
// <https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads>):
71+
// - RUSTFLAGS env var (space-separated, takes priority)
72+
// - CARGO_ENCODED_RUSTFLAGS env var (0x1f-separated, used when RUSTFLAGS is not set)
73+
// We check both in priority order to accurately represent the flags used to build.
74+
let rustflags: Vec<String> = if let Ok(raw) = std::env::var("RUSTFLAGS") {
75+
raw.split_whitespace().map(String::from).collect()
76+
} else if let Ok(encoded) = std::env::var("CARGO_ENCODED_RUSTFLAGS") {
77+
encoded.split('\x1f').map(String::from).collect()
78+
} else {
79+
Vec::new()
80+
};
81+
82+
if let Some(target_cpu) = extract_codegen_flag(&rustflags, "target-cpu") {
83+
println!("cargo:rustc-env=CODSPEED_BUILD_TARGET_CPU={target_cpu}");
84+
}
85+
}
86+
5187
/// Collect rustc toolchain info at build time and expose as env vars.
5288
/// These env var names must be kept in sync with `src/instrument_hooks/mod.rs`.
5389
fn collect_rustc_info() {
@@ -98,3 +134,35 @@ fn collect_cargo_info() {
98134
println!("cargo:rustc-env=CODSPEED_CARGO_VERSION={rest}");
99135
}
100136
}
137+
138+
/// Extract a codegen option value from a list of rustc flags.
139+
///
140+
/// Handles all three forms that rustc accepts:
141+
/// - `-Ckey=value` (no space)
142+
/// - `-C` `key=value` (space between -C and the option, split into two entries)
143+
/// - `-C` `key` `value` (space between key and value, split into three entries) — only for flags that accept it
144+
///
145+
/// Returns the value for the first match of `key`.
146+
fn extract_codegen_flag(flags: &[String], key: &str) -> Option<String> {
147+
let mut iter = flags.iter();
148+
while let Some(flag) = iter.next() {
149+
// Form: -Ckey=value
150+
if let Some(rest) = flag.strip_prefix("-C") {
151+
if let Some(value) = rest.strip_prefix(key).and_then(|s| s.strip_prefix('=')) {
152+
return Some(value.to_string());
153+
}
154+
// rest is not our key, skip
155+
continue;
156+
}
157+
158+
// Form: -C key=value or -C key value
159+
if flag == "-C" {
160+
if let Some(next) = iter.next() {
161+
if let Some(value) = next.strip_prefix(key).and_then(|s| s.strip_prefix('=')) {
162+
return Some(value.to_string());
163+
}
164+
}
165+
}
166+
}
167+
None
168+
}

crates/codspeed/src/instrument_hooks/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ mod linux_impl {
5959
if let Some(v) = option_env!("CODSPEED_CARGO_VERSION") {
6060
let _ = self.set_environment(SECTION, "cargo", v);
6161
}
62+
if let Some(v) = option_env!("CODSPEED_BUILD_PROFILE") {
63+
let _ = self.set_environment(SECTION, "profile", v);
64+
}
65+
if let Some(v) = option_env!("CODSPEED_BUILD_OPT_LEVEL") {
66+
let _ = self.set_environment(SECTION, "opt-level", v);
67+
}
68+
if let Some(v) = option_env!("CODSPEED_BUILD_TARGET_CPU") {
69+
let _ = self.set_environment(SECTION, "target-cpu", v);
70+
}
6271

6372
if let Err(e) = self.write_environment() {
6473
eprintln!("Warning: failed to write environment info: {e}");

0 commit comments

Comments
 (0)