Skip to content

Commit 42410f7

Browse files
committed
Add runtime benchmark profiling command
1 parent 78e8d81 commit 42410f7

File tree

3 files changed

+78
-25
lines changed

3 files changed

+78
-25
lines changed

collector/src/bin/collector.rs

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ use tokio::runtime::Runtime;
3131
use collector::compile::execute::bencher::BenchProcessor;
3232
use collector::compile::execute::profiler::{ProfileProcessor, Profiler};
3333
use collector::runtime::{
34-
bench_runtime, runtime_benchmark_dir, BenchmarkFilter, BenchmarkSuite,
35-
BenchmarkSuiteCompilation, CargoIsolationMode, DEFAULT_RUNTIME_ITERATIONS,
34+
bench_runtime, prepare_runtime_benchmark_suite, profile_runtime, runtime_benchmark_dir,
35+
BenchmarkFilter, BenchmarkSuite, BenchmarkSuiteCompilation, CargoIsolationMode,
36+
DEFAULT_RUNTIME_ITERATIONS,
3637
};
3738
use collector::toolchain::{
3839
create_toolchain_from_published_version, get_local_toolchain, Sysroot, Toolchain,
@@ -245,7 +246,7 @@ fn cg_annotate(cgout: &Path, path: &Path) -> anyhow::Result<()> {
245246
}
246247

247248
#[allow(clippy::too_many_arguments)]
248-
fn profile(
249+
fn profile_compile(
249250
toolchain: &Toolchain,
250251
profiler: Profiler,
251252
out_dir: &Path,
@@ -492,6 +493,16 @@ enum Commands {
492493
#[arg(long = "no-isolate")]
493494
no_isolate: bool,
494495
},
496+
497+
/// Profiles a runtime benchmark.
498+
ProfileRuntime {
499+
#[command(flatten)]
500+
local: LocalOptions,
501+
502+
/// Name of the benchmark that should be profiled
503+
benchmark: String,
504+
},
505+
495506
/// Benchmarks a local rustc
496507
BenchLocal {
497508
#[command(flatten)]
@@ -640,15 +651,7 @@ fn main_result() -> anyhow::Result<i32> {
640651
no_isolate,
641652
} => {
642653
log_db(&db);
643-
let toolchain = get_local_toolchain(
644-
&[Profile::Opt],
645-
&local.rustc,
646-
None,
647-
local.cargo.as_deref(),
648-
local.id.as_deref(),
649-
"",
650-
target_triple,
651-
)?;
654+
let toolchain = get_local_toolchain_for_runtime_benchmarks(&local, &target_triple)?;
652655
let pool = Pool::open(&db.db);
653656

654657
let isolation_mode = if no_isolate {
@@ -679,6 +682,17 @@ fn main_result() -> anyhow::Result<i32> {
679682
run_benchmarks(&mut rt, conn, shared, None, Some(config))?;
680683
Ok(0)
681684
}
685+
Commands::ProfileRuntime { local, benchmark } => {
686+
let toolchain = get_local_toolchain_for_runtime_benchmarks(&local, &target_triple)?;
687+
let suite = prepare_runtime_benchmark_suite(
688+
&toolchain,
689+
&runtime_benchmark_dir,
690+
CargoIsolationMode::Cached,
691+
)?
692+
.suite;
693+
profile_runtime(suite, &benchmark)?;
694+
Ok(0)
695+
}
682696
Commands::BenchLocal {
683697
local,
684698
opts,
@@ -894,7 +908,7 @@ fn main_result() -> anyhow::Result<i32> {
894908
target_triple.clone(),
895909
)?;
896910
let id = toolchain.id.clone();
897-
profile(
911+
profile_compile(
898912
&toolchain,
899913
profiler,
900914
&out_dir,
@@ -995,6 +1009,21 @@ Make sure to modify `{dir}/perf-config.json` if the category/artifact don't matc
9951009
}
9961010
}
9971011

1012+
fn get_local_toolchain_for_runtime_benchmarks(
1013+
local: &LocalOptions,
1014+
target_triple: &str,
1015+
) -> anyhow::Result<Toolchain> {
1016+
get_local_toolchain(
1017+
&[Profile::Opt],
1018+
&local.rustc,
1019+
None,
1020+
local.cargo.as_deref(),
1021+
local.id.as_deref(),
1022+
"",
1023+
target_triple.to_string(),
1024+
)
1025+
}
1026+
9981027
async fn load_runtime_benchmarks(
9991028
conn: &mut dyn Connection,
10001029
benchmark_dir: &Path,

collector/src/runtime/benchmark.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ impl BenchmarkSuite {
5959
.iter()
6060
.flat_map(|suite| suite.benchmark_names.iter().map(|n| n.as_ref()))
6161
}
62+
63+
pub fn get_group_by_benchmark(&self, benchmark: &str) -> Option<&BenchmarkGroup> {
64+
self.groups.iter().find(|group| {
65+
group
66+
.benchmark_names
67+
.iter()
68+
.any(|b| b.as_str() == benchmark)
69+
})
70+
}
6271
}
6372

6473
pub struct BenchmarkFilter {

collector/src/runtime/mod.rs

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::ffi::OsStr;
12
use std::io::{BufRead, BufReader, Cursor};
23
use std::path::Path;
34
use std::process::{Command, Stdio};
@@ -13,7 +14,7 @@ pub use benchmark::{
1314
use database::{ArtifactIdNumber, CollectionId, Connection};
1415

1516
use crate::utils::git::get_rustc_perf_commit;
16-
use crate::{run_command_with_output, CollectorCtx};
17+
use crate::{run_command, run_command_with_output, CollectorCtx};
1718

1819
mod benchmark;
1920

@@ -105,6 +106,30 @@ pub async fn bench_runtime(
105106
Ok(())
106107
}
107108

109+
pub fn profile_runtime(suite: BenchmarkSuite, benchmark: &str) -> anyhow::Result<()> {
110+
let Some(group) = suite.get_group_by_benchmark(benchmark) else {
111+
return Err(anyhow::anyhow!("Benchmark `{benchmark}` not found"));
112+
};
113+
let mut cmd = prepare_command(&group.binary);
114+
cmd.arg("profile").arg(benchmark);
115+
run_command(&mut cmd)?;
116+
Ok(())
117+
}
118+
119+
/// Prepares a command for execution, adding some shared flags.
120+
fn prepare_command<S: AsRef<OsStr>>(binary: S) -> Command {
121+
// Turn off ASLR
122+
let mut command = Command::new("setarch");
123+
command.arg(std::env::consts::ARCH).arg("-R").arg(binary);
124+
125+
// We want to see a backtrace if the program panics
126+
command.env("RUST_BACKTRACE", "1");
127+
128+
command.stdout(Stdio::piped());
129+
command.stderr(Stdio::piped());
130+
command
131+
}
132+
108133
/// Records the results (stats) of a benchmark into the database.
109134
async fn record_stats(
110135
conn: &dyn Connection,
@@ -191,28 +216,18 @@ fn execute_runtime_benchmark_binary(
191216
filter: &BenchmarkFilter,
192217
iterations: u32,
193218
) -> anyhow::Result<impl Iterator<Item = anyhow::Result<BenchmarkMessage>>> {
194-
// Turn off ASLR
195-
let mut command = Command::new("setarch");
196-
command.arg(std::env::consts::ARCH);
197-
command.arg("-R");
198-
command.arg(binary);
219+
let mut command = prepare_command(binary);
199220
command.arg("run");
200221
command.arg("--iterations");
201222
command.arg(&iterations.to_string());
202223

203-
// We want to see a backtrace if the benchmark panics
204-
command.env("RUST_BACKTRACE", "1");
205-
206224
if let Some(ref exclude) = filter.exclude {
207225
command.args(["--exclude", exclude]);
208226
}
209227
if let Some(ref include) = filter.include {
210228
command.args(["--include", include]);
211229
}
212230

213-
command.stdout(Stdio::piped());
214-
command.stderr(Stdio::piped());
215-
216231
let output = run_command_with_output(&mut command)?;
217232
if !output.status.success() {
218233
return Err(anyhow::anyhow!(

0 commit comments

Comments
 (0)