diff --git a/collector/src/bin/collector.rs b/collector/src/bin/collector.rs index e9aae52c2..c82929267 100644 --- a/collector/src/bin/collector.rs +++ b/collector/src/bin/collector.rs @@ -37,6 +37,7 @@ use collector::compile::benchmark::category::Category; use collector::compile::benchmark::codegen_backend::CodegenBackend; use collector::compile::benchmark::profile::Profile; use collector::compile::benchmark::scenario::Scenario; +use collector::compile::benchmark::target::Target; use collector::compile::benchmark::{ compile_benchmark_dir, get_compile_benchmarks, ArtifactType, Benchmark, BenchmarkName, }; @@ -99,6 +100,7 @@ struct CompileBenchmarkConfig { iterations: Option, is_self_profile: bool, bench_rustc: bool, + targets: Vec, } struct RuntimeBenchmarkConfig { @@ -200,6 +202,7 @@ fn profile_compile( scenarios: &[Scenario], backends: &[CodegenBackend], errors: &mut BenchmarkErrors, + targets: &[Target], ) { eprintln!("Profiling {} with {:?}", toolchain.id, profiler); if let Profiler::SelfProfile = profiler { @@ -220,6 +223,7 @@ fn profile_compile( backends, toolchain, Some(1), + targets, )); eprintln!("Finished benchmark {benchmark_id}"); @@ -910,6 +914,7 @@ fn main_result() -> anyhow::Result { iterations: Some(iterations), is_self_profile: self_profile.self_profile, bench_rustc: bench_rustc.bench_rustc, + targets: vec![Target::default()], }; run_benchmarks(&mut rt, conn, shared, Some(config), None)?; @@ -1024,6 +1029,7 @@ fn main_result() -> anyhow::Result { iterations: runs.map(|v| v as usize), is_self_profile: self_profile.self_profile, bench_rustc: bench_rustc.bench_rustc, + targets: vec![Target::default()], }; let runtime_suite = rt.block_on(load_runtime_benchmarks( conn.as_mut(), @@ -1136,6 +1142,7 @@ fn main_result() -> anyhow::Result { scenarios, backends, &mut errors, + &[Target::default()], ); Ok(id) }; @@ -1734,6 +1741,7 @@ fn bench_published_artifact( iterations: Some(3), is_self_profile: false, bench_rustc: false, + targets: vec![Target::default()], }), Some(RuntimeBenchmarkConfig::new( runtime_suite, @@ -1834,6 +1842,7 @@ fn bench_compile( &config.backends, &shared.toolchain, config.iterations, + &config.targets, ))) .with_context(|| anyhow::anyhow!("Cannot compile {}", benchmark.name)) }, diff --git a/collector/src/compile/benchmark/mod.rs b/collector/src/compile/benchmark/mod.rs index 1f31ef70d..7fb671dc3 100644 --- a/collector/src/compile/benchmark/mod.rs +++ b/collector/src/compile/benchmark/mod.rs @@ -3,6 +3,7 @@ use crate::compile::benchmark::codegen_backend::CodegenBackend; use crate::compile::benchmark::patch::Patch; use crate::compile::benchmark::profile::Profile; use crate::compile::benchmark::scenario::Scenario; +use crate::compile::benchmark::target::Target; use crate::compile::execute::{CargoProcess, Processor}; use crate::toolchain::Toolchain; use crate::utils::wait_for_future; @@ -20,6 +21,7 @@ pub mod codegen_backend; pub(crate) mod patch; pub mod profile; pub mod scenario; +pub mod target; fn default_runs() -> usize { 3 @@ -180,6 +182,7 @@ impl Benchmark { cwd: &'a Path, profile: Profile, backend: CodegenBackend, + target: Target, ) -> CargoProcess<'a> { let mut cargo_args = self .config @@ -220,10 +223,12 @@ impl Benchmark { .collect(), touch_file: self.config.touch_file.clone(), jobserver: None, + target, } } /// Run a specific benchmark under a processor + profiler combination. + #[allow(clippy::too_many_arguments)] pub async fn measure( &self, processor: &mut dyn Processor, @@ -232,6 +237,7 @@ impl Benchmark { backends: &[CodegenBackend], toolchain: &Toolchain, iterations: Option, + targets: &[Target], ) -> anyhow::Result<()> { if self.config.disabled { eprintln!("Skipping {}: disabled", self.name); @@ -263,10 +269,15 @@ impl Benchmark { } eprintln!("Preparing {}", self.name); - let mut target_dirs: Vec<((CodegenBackend, Profile), TempDir)> = vec![]; + let mut target_dirs: Vec<((CodegenBackend, Profile, Target), TempDir)> = vec![]; for backend in backends { for profile in &profiles { - target_dirs.push(((*backend, *profile), self.make_temp_dir(&self.path)?)); + for target in targets { + target_dirs.push(( + (*backend, *profile, *target), + self.make_temp_dir(&self.path)?, + )); + } } } @@ -304,15 +315,21 @@ impl Benchmark { ) .context("jobserver::new")?; let mut threads = Vec::with_capacity(target_dirs.len()); - for ((backend, profile), prep_dir) in &target_dirs { + for ((backend, profile, target), prep_dir) in &target_dirs { let server = server.clone(); let thread = s.spawn::<_, anyhow::Result<()>>(move || { wait_for_future(async move { let server = server.clone(); - self.mk_cargo_process(toolchain, prep_dir.path(), *profile, *backend) - .jobserver(server) - .run_rustc(false) - .await?; + self.mk_cargo_process( + toolchain, + prep_dir.path(), + *profile, + *backend, + *target, + ) + .jobserver(server) + .run_rustc(false) + .await?; Ok::<(), anyhow::Error>(()) })?; Ok(()) @@ -343,12 +360,13 @@ impl Benchmark { let mut timing_dirs: Vec> = vec![]; let benchmark_start = std::time::Instant::now(); - for ((backend, profile), prep_dir) in &target_dirs { + for ((backend, profile, target), prep_dir) in &target_dirs { let backend = *backend; let profile = *profile; + let target = *target; eprintln!( - "Running {}: {:?} + {:?} + {:?}", - self.name, profile, scenarios, backend + "Running {}: {:?} + {:?} + {:?} + {:?}", + self.name, profile, scenarios, backend, target, ); // We want at least two runs for all benchmarks (since we run @@ -370,7 +388,7 @@ impl Benchmark { // A full non-incremental build. if scenarios.contains(&Scenario::Full) { - self.mk_cargo_process(toolchain, cwd, profile, backend) + self.mk_cargo_process(toolchain, cwd, profile, backend, target) .processor(processor, Scenario::Full, "Full", None) .run_rustc(true) .await?; @@ -381,7 +399,7 @@ impl Benchmark { // An incremental from scratch (slowest incremental case). // This is required for any subsequent incremental builds. if scenarios.iter().any(|s| s.is_incr()) { - self.mk_cargo_process(toolchain, cwd, profile, backend) + self.mk_cargo_process(toolchain, cwd, profile, backend, target) .incremental(true) .processor(processor, Scenario::IncrFull, "IncrFull", None) .run_rustc(true) @@ -390,7 +408,7 @@ impl Benchmark { // An incremental build with no changes (fastest incremental case). if scenarios.contains(&Scenario::IncrUnchanged) { - self.mk_cargo_process(toolchain, cwd, profile, backend) + self.mk_cargo_process(toolchain, cwd, profile, backend, target) .incremental(true) .processor(processor, Scenario::IncrUnchanged, "IncrUnchanged", None) .run_rustc(true) @@ -405,7 +423,7 @@ impl Benchmark { // An incremental build with some changes (realistic // incremental case). let scenario_str = format!("IncrPatched{}", i); - self.mk_cargo_process(toolchain, cwd, profile, backend) + self.mk_cargo_process(toolchain, cwd, profile, backend, target) .incremental(true) .processor( processor, diff --git a/collector/src/compile/benchmark/target.rs b/collector/src/compile/benchmark/target.rs new file mode 100644 index 000000000..7af2213b6 --- /dev/null +++ b/collector/src/compile/benchmark/target.rs @@ -0,0 +1,16 @@ +/// Target representing an Rust target triple, for a full list of targets and +/// their support see; +/// https://doc.rust-lang.org/nightly/rustc/platform-support.html +/// +/// Presently we only support x86_64 +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Deserialize)] +pub enum Target { + /// `x86_64-unknown-linux-gnu` + X86_64UnknownLinuxGnu, +} + +impl Default for Target { + fn default() -> Self { + Self::X86_64UnknownLinuxGnu + } +} diff --git a/collector/src/compile/execute/bencher.rs b/collector/src/compile/execute/bencher.rs index d76759846..d113b9025 100644 --- a/collector/src/compile/execute/bencher.rs +++ b/collector/src/compile/execute/bencher.rs @@ -1,6 +1,7 @@ use crate::compile::benchmark::codegen_backend::CodegenBackend; use crate::compile::benchmark::profile::Profile; use crate::compile::benchmark::scenario::Scenario; +use crate::compile::benchmark::target::Target; use crate::compile::benchmark::BenchmarkName; use crate::compile::execute; use crate::compile::execute::{ @@ -91,6 +92,7 @@ impl<'a> BenchProcessor<'a> { scenario: database::Scenario, profile: database::Profile, backend: CodegenBackend, + target: Target, stats: Stats, ) { let backend = match backend { @@ -98,6 +100,10 @@ impl<'a> BenchProcessor<'a> { CodegenBackend::Cranelift => database::CodegenBackend::Cranelift, }; + let target = match target { + Target::X86_64UnknownLinuxGnu => database::Target::X86_64UnknownLinuxGnu, + }; + let mut buf = FuturesUnordered::new(); for (stat, value) in stats.iter() { buf.push(self.conn.record_statistic( @@ -107,6 +113,7 @@ impl<'a> BenchProcessor<'a> { profile, scenario, backend, + target, stat, value, )); @@ -199,8 +206,15 @@ impl Processor for BenchProcessor<'_> { res.0.stats.retain(|key, _| key.starts_with("size:")); } - self.insert_stats(collection, scenario, profile, data.backend, res.0) - .await; + self.insert_stats( + collection, + scenario, + profile, + data.backend, + data.target, + res.0, + ) + .await; Ok(Retry::No) } diff --git a/collector/src/compile/execute/mod.rs b/collector/src/compile/execute/mod.rs index c43fb02d6..004a05c49 100644 --- a/collector/src/compile/execute/mod.rs +++ b/collector/src/compile/execute/mod.rs @@ -4,6 +4,7 @@ use crate::compile::benchmark::codegen_backend::CodegenBackend; use crate::compile::benchmark::patch::Patch; use crate::compile::benchmark::profile::Profile; use crate::compile::benchmark::scenario::Scenario; +use crate::compile::benchmark::target::Target; use crate::compile::benchmark::BenchmarkName; use crate::toolchain::Toolchain; use crate::utils::fs::EnsureImmutableFile; @@ -129,6 +130,7 @@ pub struct CargoProcess<'a> { pub rustc_args: Vec, pub touch_file: Option, pub jobserver: Option, + pub target: Target, } /// Returns an optional list of Performance CPU cores, if the system has P and E cores. /// This list *should* be in a format suitable for the `taskset` command. @@ -273,12 +275,13 @@ impl<'a> CargoProcess<'a> { // really. pub async fn run_rustc(&mut self, needs_final: bool) -> anyhow::Result<()> { log::info!( - "run_rustc with incremental={}, profile={:?}, scenario={:?}, patch={:?}, backend={:?}, phase={}", + "run_rustc with incremental={}, profile={:?}, scenario={:?}, patch={:?}, backend={:?}, target={:?}, phase={}", self.incremental, self.profile, self.processor_etc.as_ref().map(|v| v.1), self.processor_etc.as_ref().and_then(|v| v.3), self.backend, + self.target, if needs_final { "benchmark" } else { "dependencies" } ); @@ -420,6 +423,7 @@ impl<'a> CargoProcess<'a> { scenario_str, patch, backend: self.backend, + target: self.target, }; match processor.process_output(&data, output).await { Ok(Retry::No) => return Ok(()), @@ -484,6 +488,7 @@ pub struct ProcessOutputData<'a> { scenario_str: &'a str, patch: Option<&'a Patch>, backend: CodegenBackend, + target: Target, } /// Trait used by `Benchmark::measure()` to provide different kinds of diff --git a/database/schema.md b/database/schema.md index a51df4b60..8fb9d8657 100644 --- a/database/schema.md +++ b/database/schema.md @@ -35,6 +35,7 @@ Here is the diagram for compile-time benchmarks: │ scenario │ │ cid │ │ │ backend │ │ value ├───┘ │ metric │ └──────────┘ + │ target │ └───────────────┘ ``` @@ -151,9 +152,9 @@ many times in the `pstat` table. ``` sqlite> select * from pstat_series limit 1; -id crate profile scenario backend metric ----------- ---------- ---------- ---------- ------- ------------ -1 helloworld check full llvm task-clock:u +id crate profile scenario backend target metric +---------- ---------- ---------- ---------- ------- ------------ ------------ +1 helloworld check full llvm x86_64-linux-unknown-gnu task-clock:u ``` ### pstat diff --git a/database/src/bin/import-sqlite.rs b/database/src/bin/import-sqlite.rs index cc060ab8d..5159d4dae 100644 --- a/database/src/bin/import-sqlite.rs +++ b/database/src/bin/import-sqlite.rs @@ -45,7 +45,7 @@ async fn main() { let sqlite_aid = sqlite_conn.artifact_id(&aid).await; let postgres_aid = postgres_conn.artifact_id(&aid).await; - for (&(benchmark, profile, scenario, backend, metric), id) in + for (&(benchmark, profile, scenario, backend, target, metric), id) in sqlite_idx.compile_statistic_descriptions() { if benchmarks.insert(benchmark) { @@ -74,6 +74,7 @@ async fn main() { profile, scenario, backend, + target, metric.as_str(), stat, ) diff --git a/database/src/bin/postgres-to-sqlite.rs b/database/src/bin/postgres-to-sqlite.rs index b45095fc8..c6299544e 100644 --- a/database/src/bin/postgres-to-sqlite.rs +++ b/database/src/bin/postgres-to-sqlite.rs @@ -246,11 +246,12 @@ impl Table for PstatSeries { } fn postgres_select_statement(&self, _since_weeks_ago: Option) -> String { - "select id, crate, profile, scenario, backend, metric from ".to_string() + self.name() + "select id, crate, profile, scenario, backend, target, metric from ".to_string() + + self.name() } fn sqlite_insert_statement(&self) -> &'static str { - "insert into pstat_series (id, crate, profile, scenario, backend, metric) VALUES (?, ?, ?, ?, ?, ?)" + "insert into pstat_series (id, crate, profile, scenario, backend, target, metric) VALUES (?, ?, ?, ?, ?, ?, ?)" } fn sqlite_execute_insert(&self, statement: &mut rusqlite::Statement, row: tokio_postgres::Row) { @@ -262,6 +263,7 @@ impl Table for PstatSeries { row.get::<_, &str>(3), row.get::<_, &str>(4), row.get::<_, &str>(5), + row.get::<_, &str>(6), ]) .unwrap(); } diff --git a/database/src/bin/sqlite-to-postgres.rs b/database/src/bin/sqlite-to-postgres.rs index e2f01ac37..9ac7fb974 100644 --- a/database/src/bin/sqlite-to-postgres.rs +++ b/database/src/bin/sqlite-to-postgres.rs @@ -322,6 +322,7 @@ struct PstatSeriesRow<'a> { profile: &'a str, scenario: &'a str, backend: &'a str, + target: &'a str, metric: &'a str, } @@ -331,11 +332,11 @@ impl Table for PstatSeries { } fn sqlite_attributes() -> &'static str { - "id, crate, profile, scenario, backend, metric" + "id, crate, profile, scenario, backend, target, metric" } fn postgres_attributes() -> &'static str { - "id, crate, profile, scenario, backend, metric" + "id, crate, profile, scenario, backend, target, metric" } fn postgres_generated_id_attribute() -> Option<&'static str> { @@ -350,7 +351,8 @@ impl Table for PstatSeries { profile: row.get_ref(2).unwrap().as_str().unwrap(), scenario: row.get_ref(3).unwrap().as_str().unwrap(), backend: row.get_ref(4).unwrap().as_str().unwrap(), - metric: row.get_ref(5).unwrap().as_str().unwrap(), + target: row.get_ref(5).unwrap().as_str().unwrap(), + metric: row.get_ref(6).unwrap().as_str().unwrap(), }) .unwrap(); } diff --git a/database/src/lib.rs b/database/src/lib.rs index 21e3c2fbe..618f0178f 100644 --- a/database/src/lib.rs +++ b/database/src/lib.rs @@ -340,6 +340,43 @@ impl PartialOrd for Scenario { } } +/// Target representing an Rust target triple, for a full list of targets and +/// their support see; +/// https://doc.rust-lang.org/nightly/rustc/platform-support.html +/// +/// Presently we only support x86_64 +#[derive( + Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, +)] +pub enum Target { + /// `x86_64-unknown-linux-gnu` + X86_64UnknownLinuxGnu, +} + +impl Target { + pub fn as_str(self) -> &'static str { + match self { + Target::X86_64UnknownLinuxGnu => "x86_64-unknown-linux-gnu", + } + } +} + +impl FromStr for Target { + type Err = String; + fn from_str(s: &str) -> Result { + Ok(match s.to_ascii_lowercase().as_str() { + "x86_64-unknown-linux-gnu" => Target::X86_64UnknownLinuxGnu, + _ => return Err(format!("{} is not a valid target", s)), + }) + } +} + +impl fmt::Display for Target { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.as_str()) + } +} + /// The codegen backend used for compilation. #[derive( Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, @@ -472,7 +509,7 @@ pub struct Index { artifacts: Indexed>, /// Id lookup of compile stat description ids /// For legacy reasons called `pstat_series` in the database, and so the name is kept here. - pstat_series: Indexed<(Benchmark, Profile, Scenario, CodegenBackend, Metric)>, + pstat_series: Indexed<(Benchmark, Profile, Scenario, CodegenBackend, Target, Metric)>, /// Id lookup of runtime stat description ids runtime_pstat_series: Indexed<(Benchmark, Metric)>, } @@ -593,6 +630,7 @@ pub enum DbLabel { profile: Profile, scenario: Scenario, backend: CodegenBackend, + target: Target, metric: Metric, }, } @@ -612,9 +650,10 @@ impl Lookup for DbLabel { scenario, backend, metric, + target, } => index .pstat_series - .get(&(*benchmark, *profile, *scenario, *backend, *metric)), + .get(&(*benchmark, *profile, *scenario, *backend, *target, *metric)), } } } @@ -664,7 +703,7 @@ impl Index { self.pstat_series .map .keys() - .map(|(_, _, _, _, metric)| metric) + .map(|(_, _, _, _, _, metric)| metric) .collect::>() .into_iter() .map(|s| s.to_string()) @@ -690,7 +729,7 @@ impl Index { &self, ) -> impl Iterator< Item = ( - &(Benchmark, Profile, Scenario, CodegenBackend, Metric), + &(Benchmark, Profile, Scenario, CodegenBackend, Target, Metric), StatisticalDescriptionId, ), > + '_ { diff --git a/database/src/pool.rs b/database/src/pool.rs index 61439c927..d33f5b432 100644 --- a/database/src/pool.rs +++ b/database/src/pool.rs @@ -1,4 +1,6 @@ -use crate::{ArtifactCollection, ArtifactId, ArtifactIdNumber, CodegenBackend, CompileBenchmark}; +use crate::{ + ArtifactCollection, ArtifactId, ArtifactIdNumber, CodegenBackend, CompileBenchmark, Target, +}; use crate::{CollectionId, Index, Profile, QueuedCommit, Scenario, Step}; use chrono::{DateTime, Utc}; use hashbrown::HashMap; @@ -45,6 +47,7 @@ pub trait Connection: Send + Sync { profile: Profile, scenario: Scenario, backend: CodegenBackend, + target: Target, metric: &str, value: f64, ); diff --git a/database/src/pool/postgres.rs b/database/src/pool/postgres.rs index 29355eb82..f3501e716 100644 --- a/database/src/pool/postgres.rs +++ b/database/src/pool/postgres.rs @@ -1,7 +1,7 @@ use crate::pool::{Connection, ConnectionManager, ManagedConnection, Transaction}; use crate::{ ArtifactCollection, ArtifactId, ArtifactIdNumber, Benchmark, CodegenBackend, CollectionId, - Commit, CommitType, CompileBenchmark, Date, Index, Profile, QueuedCommit, Scenario, + Commit, CommitType, CompileBenchmark, Date, Index, Profile, QueuedCommit, Scenario, Target, }; use anyhow::Context as _; use chrono::{DateTime, TimeZone, Utc}; @@ -279,6 +279,12 @@ static MIGRATIONS: &[&str] = &[ alter table pstat_series add constraint test_case UNIQUE(crate, profile, scenario, backend, metric); "#, r#"alter table pull_request_build add column backends text;"#, + // A pstat series shows 1 target + r#" + alter table pstat_series add target text not null default 'x86_64-unknown-linux-gnu'; + alter table pstat_series drop constraint test_case; + alter table pstat_series add constraint test_case UNIQUE(crate, profile, scenario, backend, target, metric); + "#, ]; #[async_trait::async_trait] @@ -466,8 +472,8 @@ impl PostgresConnection { .await .unwrap(), get_error: conn.prepare("select benchmark, error from error where aid = $1").await.unwrap(), - insert_pstat_series: conn.prepare("insert into pstat_series (crate, profile, scenario, backend, metric) VALUES ($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING RETURNING id").await.unwrap(), - select_pstat_series: conn.prepare("select id from pstat_series where crate = $1 and profile = $2 and scenario = $3 and backend = $4 and metric = $5").await.unwrap(), + insert_pstat_series: conn.prepare("insert into pstat_series (crate, profile, scenario, backend, target, metric) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT DO NOTHING RETURNING id").await.unwrap(), + select_pstat_series: conn.prepare("select id from pstat_series where crate = $1 and profile = $2 and scenario = $3 and backend = $4 and target = $5 and metric = $6").await.unwrap(), collection_id: conn.prepare("insert into collection (perf_commit) VALUES ($1) returning id").await.unwrap(), record_duration: conn.prepare(" insert into artifact_collection_duration ( @@ -617,7 +623,7 @@ where pstat_series: self .conn() .query( - "select id, crate, profile, scenario, backend, metric from pstat_series;", + "select id, crate, profile, scenario, backend, target, metric from pstat_series;", &[], ) .await @@ -631,7 +637,8 @@ where Profile::from_str(row.get::<_, String>(2).as_str()).unwrap(), row.get::<_, String>(3).as_str().parse().unwrap(), CodegenBackend::from_str(row.get::<_, String>(4).as_str()).unwrap(), - row.get::<_, String>(5).as_str().into(), + Target::from_str(row.get::<_, String>(5).as_str()).unwrap(), + row.get::<_, String>(6).as_str().into(), ), ) }) @@ -829,17 +836,19 @@ where profile: Profile, scenario: Scenario, backend: CodegenBackend, + target: Target, metric: &str, stat: f64, ) { let profile = profile.to_string(); let scenario = scenario.to_string(); let backend = backend.to_string(); + let target = target.to_string(); let sid = self .conn() .query_opt( &self.statements().select_pstat_series, - &[&benchmark, &profile, &scenario, &backend, &metric], + &[&benchmark, &profile, &scenario, &backend, &target, &metric], ) .await .unwrap(); @@ -849,14 +858,14 @@ where self.conn() .query_opt( &self.statements().insert_pstat_series, - &[&benchmark, &profile, &scenario, &backend, &metric], + &[&benchmark, &profile, &scenario, &backend, &target, &metric], ) .await .unwrap(); self.conn() .query_one( &self.statements().select_pstat_series, - &[&benchmark, &profile, &scenario, &backend, &metric], + &[&benchmark, &profile, &scenario, &backend, &target, &metric], ) .await .unwrap() diff --git a/database/src/pool/sqlite.rs b/database/src/pool/sqlite.rs index 9ed540020..27d6b46de 100644 --- a/database/src/pool/sqlite.rs +++ b/database/src/pool/sqlite.rs @@ -1,7 +1,7 @@ use crate::pool::{Connection, ConnectionManager, ManagedConnection, Transaction}; use crate::{ ArtifactCollection, ArtifactId, Benchmark, CodegenBackend, CollectionId, Commit, CommitType, - CompileBenchmark, Date, Profile, + CompileBenchmark, Date, Profile, Target, }; use crate::{ArtifactIdNumber, Index, QueuedCommit}; use chrono::{DateTime, TimeZone, Utc}; @@ -386,6 +386,24 @@ static MIGRATIONS: &[Migration] = &[ "#, ), Migration::new("alter table pull_request_build add column backends text"), + // Add target as a unique constraint, defaulting to 'x86_64-unknown-linux-gnu' + Migration::without_foreign_key_constraints( + r#" + create table pstat_series_with_target( + id integer primary key not null, + crate text not null references benchmark(name) on delete cascade on update cascade, + profile text not null, + scenario text not null, + backend text not null, + target text not null default 'x86_64-unknown-linux-gnu', + metric text not null, + UNIQUE(crate, profile, scenario, backend, target, metric) + ); + insert into pstat_series_with_target select id, crate, profile, scenario, backend, 'x86_64-unknown-linux-gnu', metric from pstat_series; + drop table pstat_series; + alter table pstat_series_with_target rename to pstat_series; + "#, + ), ]; #[async_trait::async_trait] @@ -501,7 +519,9 @@ impl Connection for SqliteConnection { .collect(); let pstat_series = self .raw() - .prepare("select id, crate, profile, scenario, backend, metric from pstat_series;") + .prepare( + "select id, crate, profile, scenario, backend, target, metric from pstat_series;", + ) .unwrap() .query_map(params![], |row| { Ok(( @@ -511,7 +531,8 @@ impl Connection for SqliteConnection { Profile::from_str(row.get::<_, String>(2)?.as_str()).unwrap(), row.get::<_, String>(3)?.as_str().parse().unwrap(), CodegenBackend::from_str(row.get::<_, String>(4)?.as_str()).unwrap(), - row.get::<_, String>(5)?.as_str().into(), + Target::from_str(row.get::<_, String>(5)?.as_str()).unwrap(), + row.get::<_, String>(6)?.as_str().into(), ), )) }) @@ -654,24 +675,28 @@ impl Connection for SqliteConnection { profile: Profile, scenario: crate::Scenario, backend: CodegenBackend, + target: Target, metric: &str, value: f64, ) { let profile = profile.to_string(); let scenario = scenario.to_string(); let backend = backend.to_string(); - self.raw_ref().execute("insert or ignore into pstat_series (crate, profile, scenario, backend, metric) VALUES (?, ?, ?, ?, ?)", params![ + let target = target.to_string(); + self.raw_ref().execute("insert or ignore into pstat_series (crate, profile, scenario, backend, target, metric) VALUES (?, ?, ?, ?, ?, ?)", params![ &benchmark, &profile, &scenario, &backend, + &target, &metric, ]).unwrap(); - let sid: i32 = self.raw_ref().query_row("select id from pstat_series where crate = ? and profile = ? and scenario = ? and backend = ? and metric = ?", params![ + let sid: i32 = self.raw_ref().query_row("select id from pstat_series where crate = ? and profile = ? and scenario = ? and backend = ? and target = ? and metric = ?", params![ &benchmark, &profile, &scenario, &backend, + &target, &metric, ], |r| r.get(0)).unwrap(); self.raw_ref() diff --git a/database/src/selector.rs b/database/src/selector.rs index 6069989ef..d4479b95c 100644 --- a/database/src/selector.rs +++ b/database/src/selector.rs @@ -29,7 +29,7 @@ use std::{ use crate::{ interpolate::Interpolate, metric::Metric, ArtifactId, ArtifactIdIter, Benchmark, - CodegenBackend, Connection, Index, Lookup, Profile, Scenario, + CodegenBackend, Connection, Index, Lookup, Profile, Scenario, Target, }; #[derive(Debug)] @@ -193,6 +193,7 @@ pub struct CompileBenchmarkQuery { profile: Selector, backend: Selector, metric: Selector, + target: Selector, } impl CompileBenchmarkQuery { @@ -223,6 +224,7 @@ impl CompileBenchmarkQuery { scenario: Selector::All, backend: Selector::All, metric: Selector::One(metric.as_str().into()), + target: Selector::All, } } } @@ -235,6 +237,7 @@ impl Default for CompileBenchmarkQuery { profile: Selector::All, backend: Selector::All, metric: Selector::All, + target: Selector::All, } } } @@ -250,25 +253,29 @@ impl BenchmarkQuery for CompileBenchmarkQuery { ) -> Result>, String> { let mut statistic_descriptions: Vec<_> = index .compile_statistic_descriptions() - .filter(|(&(b, p, s, backend, m), _)| { + .filter(|(&(b, p, s, backend, target, metric), _)| { self.benchmark.matches(b) && self.profile.matches(p) && self.scenario.matches(s) && self.backend.matches(backend) - && self.metric.matches(m) - }) - .map(|(&(benchmark, profile, scenario, backend, metric), sid)| { - ( - CompileTestCase { - benchmark, - profile, - scenario, - backend, - }, - metric, - sid, - ) + && self.target.matches(target) + && self.metric.matches(metric) }) + .map( + |(&(benchmark, profile, scenario, backend, target, metric), sid)| { + ( + CompileTestCase { + benchmark, + profile, + scenario, + backend, + target, + }, + metric, + sid, + ) + }, + ) .collect(); statistic_descriptions.sort_unstable(); @@ -318,6 +325,7 @@ pub struct CompileTestCase { pub profile: Profile, pub scenario: Scenario, pub backend: CodegenBackend, + pub target: Target, } impl TestCase for CompileTestCase {}