From 8ee44e11dd6b53ccc9b33a7df84a424ab38d14e5 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 25 Nov 2018 16:01:23 -0700 Subject: [PATCH] Collect self profile results --- .../src/bin/rustc-perf-collector/execute.rs | 41 ++++++++++++------- collector/src/lib.rs | 2 + collector/src/self_profile.rs | 25 +++++++++++ 3 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 collector/src/self_profile.rs diff --git a/collector/src/bin/rustc-perf-collector/execute.rs b/collector/src/bin/rustc-perf-collector/execute.rs index a1167be63..fcb3fdd05 100644 --- a/collector/src/bin/rustc-perf-collector/execute.rs +++ b/collector/src/bin/rustc-perf-collector/execute.rs @@ -13,6 +13,7 @@ use std::cmp; use tempfile::TempDir; use collector::{Benchmark as CollectedBenchmark, BenchmarkState, Patch, Run, Stat}; +use collector::self_profile::SelfProfile; use failure::{err_msg, Error, ResultExt}; use serde_json; @@ -211,6 +212,8 @@ impl<'a> CargoProcess<'a> { cmd.arg("-Zborrowck=mir"); cmd.arg("-Ztwo-phase-borrows"); } + cmd.arg("-Zself-profile"); + cmd.arg("-Zprofile-json"); // --wrap-rustc-with is not a valid rustc flag. But rustc-fake // recognizes it, strips it (and its argument) out, and uses it as an // indicator that the rustc invocation should be profiled. This works @@ -228,6 +231,7 @@ impl<'a> CargoProcess<'a> { touch_all(&self.cwd)?; let output = command_output(&mut cmd)?; + let self_profile_json = fs::read_to_string(self.cwd.join("self_profile_results.json"))?; if let Some((ref mut processor, name, run_kind, run_kind_str, patch)) = self.processor_etc { let data = ProcessOutputData { @@ -237,6 +241,7 @@ impl<'a> CargoProcess<'a> { run_kind, run_kind_str, patch, + self_profile: serde_json::from_str(&self_profile_json).unwrap(), }; match processor.process_output(&data, output) { Ok(Retry::No) => return Ok(()), @@ -271,6 +276,7 @@ pub struct ProcessOutputData<'a> { build_kind: BuildKind, run_kind: RunKind, run_kind_str: &'a str, + self_profile: SelfProfile, patch: Option<&'a Patch>, } @@ -290,11 +296,11 @@ pub trait Processor { } pub struct MeasureProcessor { - clean_stats: Vec>, - nll_stats: Vec>, - base_incr_stats: Vec>, - clean_incr_stats: Vec>, - patched_incr_stats: Vec<(Patch, Vec>)>, + clean_stats: Vec<(Vec, SelfProfile)>, + nll_stats: Vec<(Vec, SelfProfile)>, + base_incr_stats: Vec<(Vec, SelfProfile)>, + clean_incr_stats: Vec<(Vec, SelfProfile)>, + patched_incr_stats: Vec<(Patch, Vec<(Vec, SelfProfile)>)>, pub collected: CollectedBenchmark, } @@ -329,20 +335,21 @@ impl Processor for MeasureProcessor { -> Result { match process_perf_stat_output(output) { Ok(stats) => { + let self_profile = data.self_profile.clone(); match data.run_kind { - RunKind::Clean => { self.clean_stats.push(stats); } - RunKind::Nll => { self.nll_stats.push(stats); } - RunKind::BaseIncr => { self.base_incr_stats.push(stats); } - RunKind::CleanIncr => { self.clean_incr_stats.push(stats); } + RunKind::Clean => { self.clean_stats.push((stats, self_profile)); } + RunKind::Nll => { self.nll_stats.push((stats, self_profile)); } + RunKind::BaseIncr => { self.base_incr_stats.push((stats, self_profile)); } + RunKind::CleanIncr => { self.clean_incr_stats.push((stats, self_profile)); } RunKind::PatchedIncrs => { let patch = data.patch.unwrap(); if let Some(mut entry) = self.patched_incr_stats.iter_mut().find(|s| &s.0 == patch) { - entry.1.push(stats); + entry.1.push((stats, self_profile)); return Ok(Retry::No); } - self.patched_incr_stats.push((patch.clone(), vec![stats])); + self.patched_incr_stats.push((patch.clone(), vec![(stats, self_profile)])); } } Ok(Retry::No) @@ -776,10 +783,14 @@ fn process_perf_stat_output(output: process::Output) -> Result, Deseri Ok(stats) } -fn process_stats(build_kind: BuildKind, state: BenchmarkState, runs: &[Vec]) -> Run { +fn process_stats( + build_kind: BuildKind, + state: BenchmarkState, + runs: &[(Vec, SelfProfile)], +) -> Run { let mut stats: HashMap> = HashMap::new(); - for run in runs.clone() { - for stat in run { + for (run_stats, _) in runs.clone() { + for stat in run_stats { stats .entry(stat.name.clone()) .or_insert_with(|| Vec::new()) @@ -811,5 +822,7 @@ fn process_stats(build_kind: BuildKind, state: BenchmarkState, runs: &[Vec check: build_kind == BuildKind::Check, release: build_kind == BuildKind::Opt, state: state, + // TODO: Aggregate self profiles. + self_profile: runs[0].1.clone(), } } diff --git a/collector/src/lib.rs b/collector/src/lib.rs index 2e14d98d5..da4363eb9 100644 --- a/collector/src/lib.rs +++ b/collector/src/lib.rs @@ -21,6 +21,7 @@ use chrono::naive::NaiveDate; use serde::{Deserialize, Serialize}; pub mod api; +pub mod self_profile; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Commit { @@ -194,6 +195,7 @@ pub struct Stat { #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Run { pub stats: Vec, + pub self_profile: self_profile::SelfProfile, #[serde(default)] pub check: bool, pub release: bool, diff --git a/collector/src/self_profile.rs b/collector/src/self_profile.rs new file mode 100644 index 000000000..e49a56f03 --- /dev/null +++ b/collector/src/self_profile.rs @@ -0,0 +1,25 @@ +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct SelfProfile { + pub category_data: Vec, + // This field is intentionally private as for perf it should not be read. + compilation_options: Options, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Category { + /// Category name, e.g. Parsing + #[serde(rename = "category")] + pub name: String, + /// Duration of all queries executed, combined, in milliseconds + pub time_ms: u64, + /// Number of queries executed + pub query_count: u64, + /// Percentage of query hits that were cached + pub query_hits: f32, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +struct Options { + optimization_level: String, + incremental: bool, +}