Skip to content

Commit a4d589f

Browse files
authored
Merge pull request #1643 from Kobzol/db-purge-artifact
Add a command and benchmark flags to remove artifact data
2 parents 2822e8a + e201ed7 commit a4d589f

File tree

6 files changed

+162
-33
lines changed

6 files changed

+162
-33
lines changed

collector/src/bin/collector.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,21 @@ struct BenchRustcOption {
413413
bench_rustc: bool,
414414
}
415415

416+
#[derive(Clone, Debug, clap::ValueEnum)]
417+
enum PurgeMode {
418+
/// Purge all old data associated with the artifact
419+
Old,
420+
/// Purge old data of failed benchmarks associated with the artifact
421+
Failed,
422+
}
423+
424+
#[derive(Debug, clap::Args)]
425+
struct PurgeOption {
426+
/// Removes old data for the specified artifact prior to running the benchmarks.
427+
#[arg(long = "purge")]
428+
purge: Option<PurgeMode>,
429+
}
430+
416431
// For each subcommand we list the mandatory arguments in the required
417432
// order, followed by the options in alphabetical order.
418433
#[derive(Debug, clap::Subcommand)]
@@ -437,6 +452,9 @@ enum Commands {
437452
/// faster.
438453
#[arg(long = "no-isolate")]
439454
no_isolate: bool,
455+
456+
#[command(flatten)]
457+
purge: PurgeOption,
440458
},
441459

442460
/// Profiles a runtime benchmark.
@@ -493,6 +511,9 @@ enum Commands {
493511

494512
#[command(flatten)]
495513
self_profile: SelfProfileOption,
514+
515+
#[command(flatten)]
516+
purge: PurgeOption,
496517
},
497518

498519
/// Benchmarks the next commit or release for perf.rust-lang.org
@@ -552,6 +573,15 @@ enum Commands {
552573

553574
/// Download a crate into collector/benchmarks.
554575
Download(DownloadCommand),
576+
577+
/// Removes all data associated with artifact(s) with the given name.
578+
PurgeArtifact {
579+
/// Name of the artifact.
580+
name: String,
581+
582+
#[command(flatten)]
583+
db: DbOption,
584+
},
555585
}
556586

557587
#[derive(Debug, clap::Parser)]
@@ -620,6 +650,7 @@ fn main_result() -> anyhow::Result<i32> {
620650
iterations,
621651
db,
622652
no_isolate,
653+
purge,
623654
} => {
624655
log_db(&db);
625656
let toolchain = get_local_toolchain_for_runtime_benchmarks(&local, &target_triple)?;
@@ -633,6 +664,8 @@ fn main_result() -> anyhow::Result<i32> {
633664

634665
let mut conn = rt.block_on(pool.connection());
635666
let artifact_id = ArtifactId::Tag(toolchain.id.clone());
667+
rt.block_on(purge_old_data(conn.as_mut(), &artifact_id, purge.purge));
668+
636669
let runtime_suite = rt.block_on(load_runtime_benchmarks(
637670
conn.as_mut(),
638671
&runtime_benchmark_dir,
@@ -747,6 +780,7 @@ fn main_result() -> anyhow::Result<i32> {
747780
bench_rustc,
748781
iterations,
749782
self_profile,
783+
purge,
750784
} => {
751785
log_db(&db);
752786
let profiles = opts.profiles.0;
@@ -775,7 +809,9 @@ fn main_result() -> anyhow::Result<i32> {
775809
benchmarks.retain(|b| b.category().is_primary_or_secondary());
776810

777811
let artifact_id = ArtifactId::Tag(toolchain.id.clone());
778-
let conn = rt.block_on(pool.connection());
812+
let mut conn = rt.block_on(pool.connection());
813+
rt.block_on(purge_old_data(conn.as_mut(), &artifact_id, purge.purge));
814+
779815
let shared = SharedBenchmarkConfig {
780816
toolchain,
781817
artifact_id,
@@ -1057,6 +1093,14 @@ Make sure to modify `{dir}/perf-config.json` if the category/artifact don't matc
10571093
);
10581094
Ok(0)
10591095
}
1096+
Commands::PurgeArtifact { name, db } => {
1097+
let pool = Pool::open(&db.db);
1098+
let conn = rt.block_on(pool.connection());
1099+
rt.block_on(conn.purge_artifact(&ArtifactId::Tag(name.clone())));
1100+
1101+
println!("Data of artifact {name} were removed");
1102+
Ok(0)
1103+
}
10601104
}
10611105
}
10621106

@@ -1115,6 +1159,28 @@ fn log_db(db_option: &DbOption) {
11151159
println!("Using database `{}`", db_option.db);
11161160
}
11171161

1162+
async fn purge_old_data(
1163+
conn: &mut dyn Connection,
1164+
artifact_id: &ArtifactId,
1165+
purge_mode: Option<PurgeMode>,
1166+
) {
1167+
match purge_mode {
1168+
Some(PurgeMode::Old) => {
1169+
// Delete everything associated with the artifact
1170+
conn.purge_artifact(artifact_id).await;
1171+
}
1172+
Some(PurgeMode::Failed) => {
1173+
// Delete all benchmarks that have an error for the given artifact
1174+
let artifact_row_id = conn.artifact_id(artifact_id).await;
1175+
let errors = conn.get_error(artifact_row_id).await;
1176+
for krate in errors.keys() {
1177+
conn.collector_remove_step(artifact_row_id, krate).await;
1178+
}
1179+
}
1180+
None => {}
1181+
}
1182+
}
1183+
11181184
/// Record a collection entry into the database, specifying which benchmark steps will be executed.
11191185
async fn init_collection(
11201186
connection: &mut dyn Connection,

database/queries.md renamed to database/manual-modifications.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# Useful queries
2-
This document contains useful queries that should be performed manually in exceptional situations.
1+
# Useful queries and commands
2+
This document contains useful queries and commands that should be performed manually in exceptional
3+
situations.
34

45
## Remove data for a stable artifact from the DB
56
This is important for situations where there is some compilation error for a stable benchmark,
@@ -8,9 +9,16 @@ of future incompatibility lints turning into errors.
89

910
The benchmark should be fixed first, and then the DB should be altered (see below).
1011

11-
The easiest solution is to simply completely remove the artifact from the DB. There are
12-
`ON DELETE CASCADE` clauses for `aid` (artifact ID) on tables that reference it, so it should be
13-
enough to just delete the artifact from the `artifact` table.
12+
The easiest solution is to simply completely remove the artifact from the DB.
13+
You can do that either using the following command:
14+
15+
```bash
16+
$ cargo run --bin collector purge_artifact <artifact-name>
17+
# $ cargo run --bin collector purge_artifact 1.70.0 # Remove stable artifact 1.70.0
18+
```
19+
20+
Or using SQL queries. There are `ON DELETE CASCADE` clauses for `aid` (artifact ID) on tables that
21+
reference it, so it should be enough to just delete the artifact from the `artifact` table.
1422
The set of queries below show an example of removing the measured data and errors for Rust `1.69`
1523
and `1.70`:
1624
```sql

database/src/lib.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,30 @@ impl From<Commit> for ArtifactId {
384384
}
385385
}
386386

387+
struct ArtifactInfo<'a> {
388+
name: &'a str,
389+
date: Option<DateTime<Utc>>,
390+
kind: &'static str,
391+
}
392+
393+
impl ArtifactId {
394+
fn info(&self) -> ArtifactInfo {
395+
let (name, date, ty) = match self {
396+
Self::Commit(commit) => (
397+
commit.sha.as_str(),
398+
Some(commit.date.0),
399+
if commit.is_try() { "try" } else { "master" },
400+
),
401+
Self::Tag(a) => (a.as_str(), None, "release"),
402+
};
403+
ArtifactInfo {
404+
name,
405+
date,
406+
kind: ty,
407+
}
408+
}
409+
}
410+
387411
intern!(pub struct QueryLabel);
388412

389413
#[derive(PartialEq, Eq, Clone, Debug)]

database/src/pool.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ pub trait Connection: Send + Sync {
152152
async fn collector_start_step(&self, aid: ArtifactIdNumber, step: &str) -> bool;
153153
async fn collector_end_step(&self, aid: ArtifactIdNumber, step: &str);
154154

155+
async fn collector_remove_step(&self, aid: ArtifactIdNumber, step: &str);
156+
155157
async fn in_progress_artifacts(&self) -> Vec<ArtifactId>;
156158

157159
async fn in_progress_steps(&self, aid: &ArtifactId) -> Vec<Step>;
@@ -179,6 +181,9 @@ pub trait Connection: Send + Sync {
179181
profile: &str,
180182
cache: &str,
181183
) -> Vec<(ArtifactIdNumber, i32)>;
184+
185+
/// Removes all data associated with the given artifact.
186+
async fn purge_artifact(&self, aid: &ArtifactId);
182187
}
183188

184189
#[async_trait::async_trait]

database/src/pool/postgres.rs

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -948,33 +948,26 @@ where
948948
}
949949

950950
async fn artifact_id(&self, artifact: &ArtifactId) -> ArtifactIdNumber {
951-
let (name, date, ty) = match artifact {
952-
ArtifactId::Commit(commit) => (
953-
commit.sha.to_string(),
954-
Some(commit.date.0),
955-
if commit.is_try() { "try" } else { "master" },
956-
),
957-
ArtifactId::Tag(a) => (a.clone(), None, "release"),
958-
};
951+
let info = artifact.info();
959952
let aid = self
960953
.conn()
961-
.query_opt("select id from artifact where name = $1", &[&name])
954+
.query_opt("select id from artifact where name = $1", &[&info.name])
962955
.await
963956
.unwrap();
964957

965958
let aid = match aid {
966959
Some(aid) => aid.get::<_, i32>(0) as u32,
967960
None => {
968961
self.conn()
969-
.query_opt("insert into artifact (name, date, type) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING RETURNING id", &[
970-
&name,
971-
&date,
972-
&ty,
973-
])
974-
.await
975-
.unwrap();
962+
.query_opt("insert into artifact (name, date, type) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING RETURNING id", &[
963+
&info.name,
964+
&info.date,
965+
&info.kind,
966+
])
967+
.await
968+
.unwrap();
976969
self.conn()
977-
.query_one("select id from artifact where name = $1", &[&name])
970+
.query_one("select id from artifact where name = $1", &[&info.name])
978971
.await
979972
.unwrap()
980973
.get::<_, i32>(0) as u32
@@ -1141,6 +1134,16 @@ where
11411134
log::error!("did not end {} for {:?}", step, aid);
11421135
}
11431136
}
1137+
async fn collector_remove_step(&self, aid: ArtifactIdNumber, step: &str) {
1138+
self.conn()
1139+
.execute(
1140+
"delete from collector_progress \
1141+
where aid = $1 and step = $2;",
1142+
&[&(aid.0 as i32), &step],
1143+
)
1144+
.await
1145+
.unwrap();
1146+
}
11441147
async fn in_progress_artifacts(&self) -> Vec<ArtifactId> {
11451148
let rows = self
11461149
.conn()
@@ -1387,4 +1390,14 @@ where
13871390
_ => panic!("unknown artifact type: {:?}", ty),
13881391
}
13891392
}
1393+
1394+
async fn purge_artifact(&self, aid: &ArtifactId) {
1395+
// Once we delete the artifact, all data associated with it should also be deleted
1396+
// thanks to ON DELETE CASCADE.
1397+
let info = aid.info();
1398+
self.conn()
1399+
.execute("delete from artifact where name = $1", &[&info.name])
1400+
.await
1401+
.unwrap();
1402+
}
13901403
}

database/src/pool/sqlite.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -624,26 +624,19 @@ impl Connection for SqliteConnection {
624624
)
625625
}
626626
async fn artifact_id(&self, artifact: &crate::ArtifactId) -> ArtifactIdNumber {
627-
let (name, date, ty) = match artifact {
628-
crate::ArtifactId::Commit(commit) => (
629-
commit.sha.to_string(),
630-
Some(commit.date.0),
631-
if commit.is_try() { "try" } else { "master" },
632-
),
633-
crate::ArtifactId::Tag(a) => (a.clone(), None, "release"),
634-
};
627+
let info = artifact.info();
635628

636629
self.raw_ref()
637630
.execute(
638631
"insert or ignore into artifact (name, date, type) VALUES (?, ?, ?)",
639-
params![&name, &date.map(|d| d.timestamp()), &ty,],
632+
params![&info.name, &info.date.map(|d| d.timestamp()), &info.kind,],
640633
)
641634
.unwrap();
642635
ArtifactIdNumber(
643636
self.raw_ref()
644637
.query_row(
645638
"select id from artifact where name = $1",
646-
params![&name],
639+
params![&info.name],
647640
|r| r.get::<_, i32>(0),
648641
)
649642
.unwrap() as u32,
@@ -1081,6 +1074,17 @@ impl Connection for SqliteConnection {
10811074
log::error!("did not end {} for {:?}", step, aid);
10821075
}
10831076
}
1077+
1078+
async fn collector_remove_step(&self, aid: ArtifactIdNumber, step: &str) {
1079+
self.raw_ref()
1080+
.execute(
1081+
"delete from collector_progress \
1082+
where aid = ? and step = ?",
1083+
params![&aid.0, &step],
1084+
)
1085+
.unwrap();
1086+
}
1087+
10841088
async fn in_progress_artifacts(&self) -> Vec<ArtifactId> {
10851089
let conn = self.raw_ref();
10861090
let mut aids = conn
@@ -1238,4 +1242,13 @@ impl Connection for SqliteConnection {
12381242
.collect::<Result<_, _>>()
12391243
.unwrap()
12401244
}
1245+
1246+
async fn purge_artifact(&self, aid: &ArtifactId) {
1247+
// Once we delete the artifact, all data associated with it should also be deleted
1248+
// thanks to ON DELETE CASCADE.
1249+
let info = aid.info();
1250+
self.raw_ref()
1251+
.execute("delete from artifact where name = ?1", [info.name])
1252+
.unwrap();
1253+
}
12411254
}

0 commit comments

Comments
 (0)