Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'xtask/src/metrics.rs')
-rw-r--r--xtask/src/metrics.rs111
1 files changed, 60 insertions, 51 deletions
diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs
index e4d3e981af..b683b32e6d 100644
--- a/xtask/src/metrics.rs
+++ b/xtask/src/metrics.rs
@@ -1,95 +1,103 @@
use std::{
collections::BTreeMap,
- env,
+ env, fs,
io::Write as _,
path::Path,
time::{Instant, SystemTime, UNIX_EPOCH},
};
-use anyhow::{bail, format_err, Result};
-use xshell::{cmd, mkdir_p, pushd, pushenv, read_file, rm_rf};
+use anyhow::{bail, format_err};
+use xshell::{cmd, Shell};
use crate::flags;
type Unit = String;
impl flags::Metrics {
- pub(crate) fn run(self) -> Result<()> {
- let mut metrics = Metrics::new()?;
+ pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
+ let mut metrics = Metrics::new(sh)?;
if !self.dry_run {
- rm_rf("./target/release")?;
+ sh.remove_path("./target/release")?;
}
if !Path::new("./target/rustc-perf").exists() {
- mkdir_p("./target/rustc-perf")?;
- cmd!("git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf")
+ sh.create_dir("./target/rustc-perf")?;
+ cmd!(sh, "git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf")
.run()?;
}
{
- let _d = pushd("./target/rustc-perf")?;
+ let _d = sh.push_dir("./target/rustc-perf");
let revision = &metrics.perf_revision;
- cmd!("git reset --hard {revision}").run()?;
+ cmd!(sh, "git reset --hard {revision}").run()?;
}
- let _env = pushenv("RA_METRICS", "1");
+ let _env = sh.push_env("RA_METRICS", "1");
{
// https://github.com/rust-analyzer/rust-analyzer/issues/9997
- let _d = pushd("target/rustc-perf/collector/benchmarks/webrender")?;
- cmd!("cargo update -p url --precise 1.6.1").run()?;
+ let _d = sh.push_dir("target/rustc-perf/collector/benchmarks/webrender");
+ cmd!(sh, "cargo update -p url --precise 1.6.1").run()?;
}
- metrics.measure_build()?;
- metrics.measure_analysis_stats_self()?;
- metrics.measure_analysis_stats("ripgrep")?;
- metrics.measure_analysis_stats("webrender")?;
- metrics.measure_analysis_stats("diesel/diesel")?;
+ metrics.measure_build(sh)?;
+ metrics.measure_analysis_stats_self(sh)?;
+ metrics.measure_analysis_stats(sh, "ripgrep")?;
+ metrics.measure_analysis_stats(sh, "webrender")?;
+ metrics.measure_analysis_stats(sh, "diesel/diesel")?;
if !self.dry_run {
- let _d = pushd("target")?;
+ let _d = sh.push_dir("target");
let metrics_token = env::var("METRICS_TOKEN").unwrap();
cmd!(
+ sh,
"git clone --depth 1 https://{metrics_token}@github.com/rust-analyzer/metrics.git"
)
.run()?;
- let _d = pushd("metrics")?;
+ let _d = sh.push_dir("metrics");
- let mut file = std::fs::OpenOptions::new().append(true).open("metrics.json")?;
+ let mut file = fs::File::options().append(true).open("metrics.json")?;
writeln!(file, "{}", metrics.json())?;
- cmd!("git add .").run()?;
- cmd!("git -c user.name=Bot -c [email protected] commit --message 📈")
+ cmd!(sh, "git add .").run()?;
+ cmd!(sh, "git -c user.name=Bot -c [email protected] commit --message 📈")
.run()?;
- cmd!("git push origin master").run()?;
+ cmd!(sh, "git push origin master").run()?;
}
- eprintln!("{:#?}", metrics);
+ eprintln!("{metrics:#?}");
Ok(())
}
}
impl Metrics {
- fn measure_build(&mut self) -> Result<()> {
+ fn measure_build(&mut self, sh: &Shell) -> anyhow::Result<()> {
eprintln!("\nMeasuring build");
- cmd!("cargo fetch").run()?;
+ cmd!(sh, "cargo fetch").run()?;
let time = Instant::now();
- cmd!("cargo build --release --package rust-analyzer --bin rust-analyzer").run()?;
+ cmd!(sh, "cargo build --release --package rust-analyzer --bin rust-analyzer").run()?;
let time = time.elapsed();
self.report("build", time.as_millis() as u64, "ms".into());
Ok(())
}
- fn measure_analysis_stats_self(&mut self) -> Result<()> {
- self.measure_analysis_stats_path("self", ".")
+ fn measure_analysis_stats_self(&mut self, sh: &Shell) -> anyhow::Result<()> {
+ self.measure_analysis_stats_path(sh, "self", ".")
}
- fn measure_analysis_stats(&mut self, bench: &str) -> Result<()> {
+ fn measure_analysis_stats(&mut self, sh: &Shell, bench: &str) -> anyhow::Result<()> {
self.measure_analysis_stats_path(
+ sh,
bench,
&format!("./target/rustc-perf/collector/benchmarks/{}", bench),
)
}
- fn measure_analysis_stats_path(&mut self, name: &str, path: &str) -> Result<()> {
- eprintln!("\nMeasuring analysis-stats/{}", name);
- let output = cmd!("./target/release/rust-analyzer -q analysis-stats --memory-usage {path}")
- .read()?;
+ fn measure_analysis_stats_path(
+ &mut self,
+ sh: &Shell,
+ name: &str,
+ path: &str,
+ ) -> anyhow::Result<()> {
+ eprintln!("\nMeasuring analysis-stats/{name}");
+ let output =
+ cmd!(sh, "./target/release/rust-analyzer -q analysis-stats --memory-usage {path}")
+ .read()?;
for (metric, value, unit) in parse_metrics(&output) {
- self.report(&format!("analysis-stats/{}/{}", name, metric), value, unit.into());
+ self.report(&format!("analysis-stats/{name}/{metric}"), value, unit.into());
}
Ok(())
}
@@ -125,10 +133,10 @@ struct Host {
}
impl Metrics {
- fn new() -> Result<Metrics> {
- let host = Host::new()?;
+ fn new(sh: &Shell) -> anyhow::Result<Metrics> {
+ let host = Host::new(sh)?;
let timestamp = SystemTime::now();
- let revision = cmd!("git rev-parse HEAD").read()?;
+ let revision = cmd!(sh, "git rev-parse HEAD").read()?;
let perf_revision = "c52ee623e231e7690a93be88d943016968c1036b".into();
Ok(Metrics { host, timestamp, revision, perf_revision, metrics: BTreeMap::new() })
}
@@ -157,28 +165,29 @@ impl Metrics {
}
impl Host {
- fn new() -> Result<Host> {
+ fn new(sh: &Shell) -> anyhow::Result<Host> {
if cfg!(not(target_os = "linux")) {
bail!("can only collect metrics on Linux ");
}
- let os = read_field("/etc/os-release", "PRETTY_NAME=")?.trim_matches('"').to_string();
+ let os = read_field(sh, "/etc/os-release", "PRETTY_NAME=")?.trim_matches('"').to_string();
- let cpu =
- read_field("/proc/cpuinfo", "model name")?.trim_start_matches(':').trim().to_string();
+ let cpu = read_field(sh, "/proc/cpuinfo", "model name")?
+ .trim_start_matches(':')
+ .trim()
+ .to_string();
- let mem = read_field("/proc/meminfo", "MemTotal:")?;
+ let mem = read_field(sh, "/proc/meminfo", "MemTotal:")?;
return Ok(Host { os, cpu, mem });
- fn read_field(path: &str, field: &str) -> Result<String> {
- let text = read_file(path)?;
+ fn read_field(sh: &Shell, path: &str, field: &str) -> anyhow::Result<String> {
+ let text = sh.read_file(path)?;
- let line = text
- .lines()
- .find(|it| it.starts_with(field))
- .ok_or_else(|| format_err!("can't parse {}", path))?;
- Ok(line[field.len()..].trim().to_string())
+ text.lines()
+ .find_map(|it| it.strip_prefix(field))
+ .map(|it| it.trim().to_string())
+ .ok_or_else(|| format_err!("can't parse {}", path))
}
}
fn to_json(&self, mut obj: write_json::Object<'_>) {