Implement x perf as a separate tool
This commit is contained in:
parent
d7c59370ce
commit
151986f493
12 changed files with 211 additions and 25 deletions
7
src/tools/rustc-perf-wrapper/Cargo.toml
Normal file
7
src/tools/rustc-perf-wrapper/Cargo.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "rustc-perf-wrapper"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.7", features = ["derive", "env"] }
|
||||
3
src/tools/rustc-perf-wrapper/README.md
Normal file
3
src/tools/rustc-perf-wrapper/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# rustc-perf wrapper
|
||||
Utility tool for invoking [`rustc-perf`](https://github.com/rust-lang/rustc-perf) for benchmarking/profiling
|
||||
a stage1/2 compiler built by bootstrap using `x run perf`.
|
||||
45
src/tools/rustc-perf-wrapper/src/config.rs
Normal file
45
src/tools/rustc-perf-wrapper/src/config.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Clone, Copy, Debug, clap::ValueEnum)]
|
||||
#[value(rename_all = "PascalCase")]
|
||||
pub enum Profile {
|
||||
Check,
|
||||
Debug,
|
||||
Doc,
|
||||
Opt,
|
||||
Clippy,
|
||||
}
|
||||
|
||||
impl Display for Profile {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let name = match self {
|
||||
Profile::Check => "Check",
|
||||
Profile::Debug => "Debug",
|
||||
Profile::Doc => "Doc",
|
||||
Profile::Opt => "Opt",
|
||||
Profile::Clippy => "Clippy",
|
||||
};
|
||||
f.write_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, clap::ValueEnum)]
|
||||
#[value(rename_all = "PascalCase")]
|
||||
pub enum Scenario {
|
||||
Full,
|
||||
IncrFull,
|
||||
IncrUnchanged,
|
||||
IncrPatched,
|
||||
}
|
||||
|
||||
impl Display for Scenario {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let name = match self {
|
||||
Scenario::Full => "Full",
|
||||
Scenario::IncrFull => "IncrFull",
|
||||
Scenario::IncrUnchanged => "IncrUnchanged",
|
||||
Scenario::IncrPatched => "IncrPatched",
|
||||
};
|
||||
f.write_str(name)
|
||||
}
|
||||
}
|
||||
130
src/tools/rustc-perf-wrapper/src/main.rs
Normal file
130
src/tools/rustc-perf-wrapper/src/main.rs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
use crate::config::{Profile, Scenario};
|
||||
use clap::Parser;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
mod config;
|
||||
|
||||
/// Performs profiling or benchmarking with [`rustc-perf`](https://github.com/rust-lang/rustc-perf)
|
||||
/// using a locally built compiler.
|
||||
#[derive(Debug, clap::Parser)]
|
||||
// Hide arguments from BuildContext in the default usage string.
|
||||
// Clap does not seem to have a way of disabling the usage of these arguments.
|
||||
#[clap(override_usage = "rustc-perf-wrapper [OPTIONS] <COMMAND>")]
|
||||
pub struct Args {
|
||||
#[clap(subcommand)]
|
||||
cmd: PerfCommand,
|
||||
|
||||
#[clap(flatten)]
|
||||
opts: SharedOpts,
|
||||
|
||||
#[clap(flatten)]
|
||||
ctx: BuildContext,
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
enum PerfCommand {
|
||||
/// Run `profile_local eprintln`.
|
||||
/// This executes the compiler on the given benchmarks and stores its stderr output.
|
||||
Eprintln,
|
||||
/// Run `profile_local samply`
|
||||
/// This executes the compiler on the given benchmarks and profiles it with `samply`.
|
||||
/// You need to install `samply`, e.g. using `cargo install samply`.
|
||||
Samply,
|
||||
/// Run `profile_local cachegrind`.
|
||||
/// This executes the compiler on the given benchmarks under `Cachegrind`.
|
||||
Cachegrind,
|
||||
}
|
||||
|
||||
impl PerfCommand {
|
||||
fn is_profiling(&self) -> bool {
|
||||
match self {
|
||||
PerfCommand::Eprintln | PerfCommand::Samply | PerfCommand::Cachegrind => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
struct SharedOpts {
|
||||
/// Select the benchmarks that you want to run (separated by commas).
|
||||
/// If unspecified, all benchmarks will be executed.
|
||||
#[clap(long, global = true, value_delimiter = ',')]
|
||||
include: Vec<String>,
|
||||
/// Select the scenarios that should be benchmarked.
|
||||
#[clap(
|
||||
long,
|
||||
global = true,
|
||||
value_delimiter = ',',
|
||||
default_value = "Full,IncrFull,IncrUnchanged,IncrPatched"
|
||||
)]
|
||||
scenarios: Vec<Scenario>,
|
||||
/// Select the profiles that should be benchmarked.
|
||||
#[clap(long, global = true, value_delimiter = ',', default_value = "Check,Debug,Opt")]
|
||||
profiles: Vec<Profile>,
|
||||
}
|
||||
|
||||
/// These arguments are mostly designed to be passed from bootstrap, not by users
|
||||
/// directly.
|
||||
#[derive(Debug, clap::Parser)]
|
||||
struct BuildContext {
|
||||
/// Compiler binary that will be benchmarked/profiled.
|
||||
#[clap(long, hide = true, env = "PERF_RUSTC")]
|
||||
compiler: PathBuf,
|
||||
/// rustc-perf collector binary that will be used for running benchmarks/profilers.
|
||||
#[clap(long, hide = true, env = "PERF_COLLECTOR")]
|
||||
collector: PathBuf,
|
||||
/// Directory where to store results.
|
||||
#[clap(long, hide = true, env = "PERF_RESULT_DIR")]
|
||||
results_dir: PathBuf,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
run(args);
|
||||
}
|
||||
|
||||
fn run(args: Args) {
|
||||
let mut cmd = Command::new(args.ctx.collector);
|
||||
match &args.cmd {
|
||||
PerfCommand::Eprintln => {
|
||||
cmd.arg("profile_local").arg("eprintln");
|
||||
}
|
||||
PerfCommand::Samply => {
|
||||
cmd.arg("profile_local").arg("samply");
|
||||
}
|
||||
PerfCommand::Cachegrind => {
|
||||
cmd.arg("profile_local").arg("cachegrind");
|
||||
}
|
||||
}
|
||||
if args.cmd.is_profiling() {
|
||||
cmd.arg("--out-dir").arg(&args.ctx.results_dir);
|
||||
}
|
||||
|
||||
if !args.opts.include.is_empty() {
|
||||
cmd.arg("--include").arg(args.opts.include.join(","));
|
||||
}
|
||||
if !args.opts.profiles.is_empty() {
|
||||
cmd.arg("--profiles")
|
||||
.arg(args.opts.profiles.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
|
||||
}
|
||||
if !args.opts.scenarios.is_empty() {
|
||||
cmd.arg("--scenarios")
|
||||
.arg(args.opts.scenarios.iter().map(|p| p.to_string()).collect::<Vec<_>>().join(","));
|
||||
}
|
||||
cmd.arg(&args.ctx.compiler);
|
||||
|
||||
println!("Running `rustc-perf` using `{}`", args.ctx.compiler.display());
|
||||
|
||||
const MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR");
|
||||
|
||||
let rustc_perf_dir = PathBuf::from(MANIFEST_DIR).join("../rustc-perf");
|
||||
|
||||
// We need to set the working directory to `src/tools/perf`, so that it can find the directory
|
||||
// with compile-time benchmarks.
|
||||
let cmd = cmd.current_dir(rustc_perf_dir);
|
||||
cmd.status().expect("error while running rustc-perf collector");
|
||||
|
||||
if args.cmd.is_profiling() {
|
||||
println!("You can find the results at `{}`", args.ctx.results_dir.display());
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue