Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 102 additions & 86 deletions ci/check-profiling.sh

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions collector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ The following options alter the behaviour of the `bench_local` subcommand.
`IncrUnchanged`, `IncrPatched`, and `All`. The default is `All`. Note that
`IncrFull` is always run if either of `IncrUnchanged` or `IncrPatched` are
run (even if not requested).
- `--frontend-threads <FRONTEND_THREADS>`: comma-separated list of thread counts for
the parallel frontend. Maps directly to the `-Zthreads` rustc option.
The default is `1`.
- `--backends <BACKENDS>`: the codegen backends to be benchmarked. The possible
choices are one or more (comma-separated) of `Llvm`, `Cranelift`. The default
is `Llvm`.
Expand Down Expand Up @@ -204,7 +207,7 @@ and discover all benchmarks within them. If you only want to run benchmark(s) fr
you can use this to speed up the runtime benchmarking or profiling commands.

The `bench_runtime_local` command also shares some options with the `bench_local` command, notably
`--id`, `--db`, `--cargo`, `--cargo-config`, `--include`, `--exclude` and `--iterations`.
`--id`, `--db`, `--cargo`, `--cargo-config`, `--include`, `--exclude` and `--iterations`.

### How to view the measurements on your own machine

Expand Down Expand Up @@ -489,6 +492,7 @@ The following options alter the behaviour of the `profile_local` subcommand.
diff files will also be produced.
- `--rustdoc <RUSTDOC>` as for `bench_local`.
- `--scenarios <SCENARIOS>`: as for `bench_local`.
- `--frontend-threads <FRONTEND_THREADS>`: as for `bench_local`.
- `--backends <BACKENDS>`: as for `bench_local`.
- `--jobs <JOB-COUNT>`: execute `<JOB-COUNT>` benchmarks in parallel. This is only allowed for certain
profilers whose results are not affected by system noise (e.g. `callgrind` or `eprintln`).
Expand All @@ -511,7 +515,7 @@ build directory (at least Valgrind 3.22 is required), like this:

```
DEP_VALGRIND=<path-to-valgrind-install>/include cargo run --release --bin collector \
--features precise-cachegrind profile_runtime cachegrind <RUSTC> <BENCHMARK_NAME>
--features precise-cachegrind profile_runtime cachegrind <RUSTC> <BENCHMARK_NAME>
```

## Codegen diff
Expand All @@ -534,7 +538,7 @@ binary artifacts (executables, libraries). You can compare the binary statistics
[--profile <Debug|Opt>] \
[--backend <Llvm|Cranelift>]
```

You can also compare (diff) the size statistics between two compilers:
```bash
./target/release/collector binary_stats compile `<rustc>` --include <benchmark name> --rustc2 <rustc2>
Expand Down
114 changes: 78 additions & 36 deletions collector/src/bin/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use collector::benchmark_set::{get_benchmark_set, BenchmarkSetId, BenchmarkSetMe
use collector::codegen::{codegen_diff, CodegenType};
use collector::compile::benchmark::category::Category;
use collector::compile::benchmark::codegen_backend::CodegenBackend;
use collector::compile::benchmark::parallel_frontend::FrontendThreads;
use collector::compile::benchmark::profile::Profile;
use collector::compile::benchmark::scenario::Scenario;
use collector::compile::benchmark::target::Target;
Expand Down Expand Up @@ -116,6 +117,7 @@ struct CompileBenchmarkConfig {
self_profile_storage: Option<Box<dyn SelfProfileStorage>>,
bench_rustc: bool,
targets: Vec<Target>,
frontend_threads_counts: Vec<FrontendThreads>,
}

struct RuntimeBenchmarkConfig {
Expand Down Expand Up @@ -166,50 +168,54 @@ fn generate_diffs(
benchmarks: &[Benchmark],
profiles: &[Profile],
scenarios: &[Scenario],
frontend_threads_counts: &[FrontendThreads],
errors: &mut BenchmarkErrors,
profiler: &Profiler,
) -> Vec<PathBuf> {
let mut annotated_diffs = Vec::new();
for benchmark in benchmarks {
for &profile in profiles {
for scenario in scenarios.iter().flat_map(|scenario| {
if profile.is_doc() && scenario.is_incr() {
return vec![];
}
match scenario {
Scenario::Full | Scenario::IncrFull | Scenario::IncrUnchanged => {
vec![format!("{:?}", scenario)]
for &frontend_threads in frontend_threads_counts {
for scenario in scenarios.iter().flat_map(|scenario| {
if profile.is_doc() && scenario.is_incr() {
return vec![];
}
match scenario {
Scenario::Full | Scenario::IncrFull | Scenario::IncrUnchanged => {
vec![format!("{:?}", scenario)]
}
Scenario::IncrPatched => (0..benchmark.patches.len())
.map(|i| format!("{scenario:?}{i}"))
.collect::<Vec<_>>(),
}
}) {
let filename = |prefix, id| {
format!(
"{}-{}-{}-{:?}-{}-frontend_threads_{}{}",
prefix,
id,
benchmark.name,
profile,
scenario,
frontend_threads.get(),
profiler.postfix()
)
};
let id_diff = format!("{id1}-{id2}");
let prefix = profiler.prefix();
let prefix2 = profiler.prefix2();
let left = out_dir.join(filename(prefix, id1));
let right = out_dir.join(filename(prefix, id2));
let output = out_dir.join(filename(&format!("{prefix2}-diff"), &id_diff));

if let Err(e) = profiler.diff(&left, &right, &output) {
errors.incr();
eprintln!("collector error: {e:?}");
continue;
}
Scenario::IncrPatched => (0..benchmark.patches.len())
.map(|i| format!("{scenario:?}{i}"))
.collect::<Vec<_>>(),
}
}) {
let filename = |prefix, id| {
format!(
"{}-{}-{}-{:?}-{}{}",
prefix,
id,
benchmark.name,
profile,
scenario,
profiler.postfix()
)
};
let id_diff = format!("{id1}-{id2}");
let prefix = profiler.prefix();
let prefix2 = profiler.prefix2();
let left = out_dir.join(filename(prefix, id1));
let right = out_dir.join(filename(prefix, id2));
let output = out_dir.join(filename(&format!("{prefix2}-diff"), &id_diff));

if let Err(e) = profiler.diff(&left, &right, &output) {
errors.incr();
eprintln!("collector error: {e:?}");
continue;
}

annotated_diffs.push(output);
annotated_diffs.push(output);
}
}
}
}
Expand All @@ -227,6 +233,7 @@ fn profile_compile(
backends: &[CodegenBackend],
errors: &mut BenchmarkErrors,
targets: &[Target],
frontend_threads_counts: &[FrontendThreads],
) {
eprintln!("Profiling {} with {:?}", toolchain.id, profiler);
if let Profiler::SelfProfile = profiler {
Expand All @@ -248,6 +255,7 @@ fn profile_compile(
toolchain,
Some(1),
targets,
frontend_threads_counts,
// We always want to profile everything
&hashbrown::HashSet::new(),
));
Expand Down Expand Up @@ -411,6 +419,27 @@ struct CompileTimeOptions {
/// It should be a path to the `clippy-driver` binary.
#[arg(long)]
clippy: Option<PathBuf>,

/// Parallel frontend thread count in comma-separated list
#[arg(long = "frontend-threads", value_delimiter = ',')]
frontend_threads_counts: Vec<u32>,
}

impl CompileTimeOptions {
fn validate_and_normalize_frontend_threads(&self) -> Vec<FrontendThreads> {
if self.frontend_threads_counts.is_empty() {
return FrontendThreads::default_threads_counts();
}

let mut threads = self
.frontend_threads_counts
.iter()
.map(|&x| FrontendThreads::new(x))
.collect::<Vec<_>>();
threads.sort();
threads.dedup();
threads
}
}

#[derive(Debug, clap::Args)]
Expand Down Expand Up @@ -992,6 +1021,7 @@ fn main_result() -> anyhow::Result<i32> {
purge,
} => {
log_db(&db);
let frontend_threads_counts = opts.validate_and_normalize_frontend_threads();
let profiles = opts.profiles.0;
let scenarios = opts.scenarios.0;
let backends = opts.codegen_backends.0;
Expand Down Expand Up @@ -1044,6 +1074,7 @@ fn main_result() -> anyhow::Result<i32> {
},
bench_rustc: bench_rustc.bench_rustc,
targets: vec![Target::host()],
frontend_threads_counts,
};

rt.block_on(run_benchmarks(conn.as_mut(), shared, Some(config), None))?;
Expand Down Expand Up @@ -1084,6 +1115,7 @@ fn main_result() -> anyhow::Result<i32> {

let profiles = &opts.profiles.0;
let scenarios = &opts.scenarios.0;
let frontend_threads_counts = opts.validate_and_normalize_frontend_threads();
let backends = &opts.codegen_backends.0;

let mut benchmarks = get_compile_benchmarks(&compile_benchmark_dir, (&local).into())?;
Expand Down Expand Up @@ -1123,6 +1155,7 @@ fn main_result() -> anyhow::Result<i32> {
backends,
&mut errors,
&[Target::host()],
&frontend_threads_counts,
);
Ok(id)
};
Expand All @@ -1141,6 +1174,7 @@ fn main_result() -> anyhow::Result<i32> {
&benchmarks,
profiles,
scenarios,
&frontend_threads_counts,
&mut errors,
&profiler,
);
Expand Down Expand Up @@ -1680,6 +1714,7 @@ async fn create_benchmark_configs(
},
bench_rustc,
targets: vec![job.target().into()],
frontend_threads_counts: FrontendThreads::default_threads_counts(),
})
} else {
None
Expand Down Expand Up @@ -2135,6 +2170,11 @@ async fn bench_published_artifact(
} else {
Scenario::all_non_incr()
};
let frontend_threads_counts = if collector::version_supports_parallel_frontend(&toolchain.id) {
FrontendThreads::default_threads_counts()
} else {
vec![FrontendThreads::new(1)]
};

// Exclude benchmarks that don't work with a stable compiler.
let mut compile_benchmarks = get_compile_benchmarks(dirs.compile, CompileBenchmarkFilter::All)?;
Expand Down Expand Up @@ -2168,6 +2208,7 @@ async fn bench_published_artifact(
self_profile_storage: None,
bench_rustc: false,
targets: vec![Target::host()],
frontend_threads_counts,
}),
Some(RuntimeBenchmarkConfig::new(
runtime_suite,
Expand Down Expand Up @@ -2274,6 +2315,7 @@ async fn bench_compile(
&shared.toolchain,
config.iterations,
&config.targets,
&config.frontend_threads_counts,
&collector.measured_compile_test_cases,
))
.await
Expand Down
Loading
Loading