Skip to content

Commit 5cf48db

Browse files
committed
Do not use the benchmark index for computing the request queue
1 parent e953943 commit 5cf48db

File tree

7 files changed

+140
-108
lines changed

7 files changed

+140
-108
lines changed

database/src/lib.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,29 +1041,23 @@ impl BenchmarkRequest {
10411041
}
10421042

10431043
/// Cached information about benchmark requests in the DB
1044-
/// FIXME: only store non-try requests here
10451044
pub struct BenchmarkRequestIndex {
10461045
/// Tags (SHA or release name) of all known benchmark requests
10471046
all: HashSet<String>,
1048-
/// Tags (SHA or release name) of all benchmark requests in the completed status
1049-
completed: HashSet<String>,
10501047
}
10511048

10521049
impl BenchmarkRequestIndex {
10531050
/// Do we already have a benchmark request for the passed `tag`?
10541051
pub fn contains_tag(&self, tag: &str) -> bool {
10551052
self.all.contains(tag)
10561053
}
1054+
}
10571055

1058-
/// Return tags of already completed benchmark requests.
1059-
pub fn completed_requests(&self) -> &HashSet<String> {
1060-
&self.completed
1061-
}
1062-
1063-
pub fn add_tag(&mut self, tag: &str) {
1064-
self.all.insert(tag.to_string());
1065-
self.completed.insert(tag.to_string());
1066-
}
1056+
/// Contains pending (ArtifactsReady or InProgress) benchmark requests, and a set of their parents
1057+
/// that are already completed.
1058+
pub struct PendingBenchmarkRequests {
1059+
pub requests: Vec<BenchmarkRequest>,
1060+
pub completed_parent_tags: HashSet<String>,
10671061
}
10681062

10691063
#[derive(Debug, Clone, PartialEq)]

database/src/pool.rs

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use crate::selector::CompileTestCase;
22
use crate::{
33
ArtifactCollection, ArtifactId, ArtifactIdNumber, BenchmarkJob, BenchmarkJobConclusion,
44
BenchmarkRequest, BenchmarkRequestIndex, BenchmarkRequestStatus, BenchmarkRequestWithErrors,
5-
BenchmarkSet, CodegenBackend, CollectorConfig, CompileBenchmark, Target,
5+
BenchmarkSet, CodegenBackend, CollectorConfig, CompileBenchmark, PendingBenchmarkRequests,
6+
Target,
67
};
78
use crate::{CollectionId, Index, Profile, QueuedCommit, Scenario, Step};
89
use chrono::{DateTime, Utc};
@@ -189,7 +190,8 @@ pub trait Connection: Send + Sync {
189190
async fn purge_artifact(&self, aid: &ArtifactId);
190191

191192
/// Add an item to the `benchmark_requests`, if the `benchmark_request`
192-
/// exists an Error will be returned
193+
/// exists an Error will be returned.
194+
/// We require the caller to pass an index, to ensure that it is always kept up-to-date.
193195
async fn insert_benchmark_request(
194196
&self,
195197
benchmark_request: &BenchmarkRequest,
@@ -200,7 +202,9 @@ pub trait Connection: Send + Sync {
200202

201203
/// Load all pending benchmark requests, i.e. those that have artifacts ready, but haven't
202204
/// been completed yet. Pending statuses are `ArtifactsReady` and `InProgress`.
203-
async fn load_pending_benchmark_requests(&self) -> anyhow::Result<Vec<BenchmarkRequest>>;
205+
/// Also returns their parents, so that we can quickly check which requests are ready for being
206+
/// enqueued.
207+
async fn load_pending_benchmark_requests(&self) -> anyhow::Result<PendingBenchmarkRequests>;
204208

205209
/// Update the status of a `benchmark_request` with the given `tag`.
206210
/// If no such request exists in the DB, returns an error.
@@ -426,6 +430,7 @@ mod tests {
426430
use crate::tests::run_postgres_test;
427431
use crate::{tests::run_db_test, BenchmarkRequestType, Commit, CommitType, Date};
428432
use chrono::Utc;
433+
use std::collections::BTreeSet;
429434
use std::str::FromStr;
430435

431436
/// Create a Commit
@@ -629,43 +634,48 @@ mod tests {
629634
async fn load_pending_benchmark_requests() {
630635
run_postgres_test(|ctx| async {
631636
let db = ctx.db();
632-
let time = chrono::DateTime::from_str("2021-09-01T00:00:00.000Z").unwrap();
633-
let target = Target::X86_64UnknownLinuxGnu;
634-
let collector_name = "collector-1";
635-
let benchmark_set = 1;
636-
637-
db.add_collector_config(collector_name, target, benchmark_set, true)
638-
.await
639-
.unwrap();
640637

641638
// ArtifactsReady
642-
let req_a = BenchmarkRequest::create_master("sha-1", "parent-sha-1", 42, time);
639+
let req_a = ctx.insert_master_request("sha-1", "parent-sha-1", 42).await;
643640
// ArtifactsReady
644-
let req_b = BenchmarkRequest::create_release("1.80.0", time);
641+
let req_b = ctx.insert_release_request("1.80.0").await;
645642
// WaitingForArtifacts
646-
let req_c = BenchmarkRequest::create_try_without_artifacts(50, "", "");
643+
ctx.insert_try_request(50).await;
647644
// InProgress
648-
let req_d = BenchmarkRequest::create_master("sha-2", "parent-sha-2", 51, time);
645+
let req_d = ctx.insert_master_request("sha-2", "parent-sha-2", 51).await;
649646
// Completed
650-
let req_e = BenchmarkRequest::create_release("1.79.0", time);
647+
ctx.insert_release_request("1.79.0").await;
651648

652-
for &req in &[&req_a, &req_b, &req_c, &req_d, &req_e] {
653-
db.insert_benchmark_request(req).await.unwrap();
654-
}
655-
656-
complete_request(db, "1.79.0", collector_name, benchmark_set, target).await;
649+
ctx.complete_request("1.79.0").await;
650+
ctx.insert_master_request("parent-sha-1", "grandparent-sha-0", 100)
651+
.await;
652+
ctx.complete_request("parent-sha-1").await;
653+
ctx.insert_master_request("parent-sha-2", "grandparent-sha-1", 101)
654+
.await;
655+
ctx.complete_request("parent-sha-2").await;
657656

658657
db.update_benchmark_request_status("sha-2", BenchmarkRequestStatus::InProgress)
659658
.await
660659
.unwrap();
661660

662-
let requests = db.load_pending_benchmark_requests().await.unwrap();
661+
let pending = db.load_pending_benchmark_requests().await.unwrap();
662+
let requests = pending.requests;
663663

664664
assert_eq!(requests.len(), 3);
665665
for req in &[req_a, req_b, req_d] {
666666
assert!(requests.iter().any(|r| r.tag() == req.tag()));
667667
}
668668

669+
assert_eq!(
670+
pending
671+
.completed_parent_tags
672+
.into_iter()
673+
.collect::<BTreeSet<_>>()
674+
.into_iter()
675+
.collect::<Vec<_>>(),
676+
vec!["parent-sha-1".to_string(), "parent-sha-2".to_string()]
677+
);
678+
669679
Ok(ctx)
670680
})
671681
.await;
@@ -687,6 +697,7 @@ mod tests {
687697
.load_pending_benchmark_requests()
688698
.await
689699
.unwrap()
700+
.requests
690701
.into_iter()
691702
.next()
692703
.unwrap();

database/src/pool/postgres.rs

Lines changed: 50 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ use crate::{
55
BenchmarkJobConclusion, BenchmarkJobStatus, BenchmarkRequest, BenchmarkRequestIndex,
66
BenchmarkRequestStatus, BenchmarkRequestType, BenchmarkRequestWithErrors, BenchmarkSet,
77
CodegenBackend, CollectionId, CollectorConfig, Commit, CommitType, CompileBenchmark, Date,
8-
Index, Profile, QueuedCommit, Scenario, Target, BENCHMARK_JOB_STATUS_FAILURE_STR,
9-
BENCHMARK_JOB_STATUS_IN_PROGRESS_STR, BENCHMARK_JOB_STATUS_QUEUED_STR,
10-
BENCHMARK_JOB_STATUS_SUCCESS_STR, BENCHMARK_REQUEST_MASTER_STR, BENCHMARK_REQUEST_RELEASE_STR,
8+
Index, PendingBenchmarkRequests, Profile, QueuedCommit, Scenario, Target,
9+
BENCHMARK_JOB_STATUS_FAILURE_STR, BENCHMARK_JOB_STATUS_IN_PROGRESS_STR,
10+
BENCHMARK_JOB_STATUS_QUEUED_STR, BENCHMARK_JOB_STATUS_SUCCESS_STR,
11+
BENCHMARK_REQUEST_MASTER_STR, BENCHMARK_REQUEST_RELEASE_STR,
1112
BENCHMARK_REQUEST_STATUS_ARTIFACTS_READY_STR, BENCHMARK_REQUEST_STATUS_COMPLETED_STR,
1213
BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR, BENCHMARK_REQUEST_STATUS_WAITING_FOR_ARTIFACTS_STR,
1314
BENCHMARK_REQUEST_TRY_STR,
@@ -500,6 +501,7 @@ pub struct CachedStatements {
500501
get_compile_test_cases_with_measurements: Statement,
501502
get_last_n_completed_requests_with_errors: Statement,
502503
get_jobs_of_in_progress_benchmark_requests: Statement,
504+
load_pending_benchmark_requests: Statement,
503505
}
504506

505507
pub struct PostgresTransaction<'a> {
@@ -683,7 +685,7 @@ impl PostgresConnection {
683685
where aid = $1
684686
").await.unwrap(),
685687
load_benchmark_request_index: conn.prepare("
686-
SELECT tag, status
688+
SELECT tag
687689
FROM benchmark_request
688690
WHERE tag IS NOT NULL
689691
").await.unwrap(),
@@ -751,6 +753,18 @@ impl PostgresConnection {
751753
-- Only get the jobs of in_progress requests
752754
SELECT * FROM job_queue INNER JOIN requests ON job_queue.request_tag = requests.tag
753755
")).await.unwrap(),
756+
// Load pending benchmark requests, along with information whether their parent is
757+
// completed or not
758+
load_pending_benchmark_requests: conn.prepare(&format!("
759+
WITH pending AS (
760+
SELECT {BENCHMARK_REQUEST_COLUMNS}
761+
FROM benchmark_request AS req
762+
WHERE status IN ('{BENCHMARK_REQUEST_STATUS_ARTIFACTS_READY_STR}', '{BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR}')
763+
)
764+
SELECT (parent.status = '{BENCHMARK_REQUEST_STATUS_COMPLETED_STR}') AS parent_done, pending.*
765+
FROM pending
766+
LEFT JOIN benchmark_request as parent ON parent.tag = pending.parent_sha
767+
")).await.unwrap(),
754768
}),
755769
conn,
756770
}
@@ -809,7 +823,7 @@ where
809823
None => Date(Utc.with_ymd_and_hms(2001, 1, 1, 0, 0, 0).unwrap()),
810824
}
811825
},
812-
r#type: CommitType::from_str(&row.get::<_, String>(3)).unwrap()
826+
r#type: CommitType::from_str(&row.get::<_, String>(3)).unwrap(),
813827
},
814828
)
815829
})
@@ -1188,13 +1202,13 @@ where
11881202
Some(aid) => aid.get::<_, i32>(0) as u32,
11891203
None => {
11901204
self.conn()
1191-
.query_opt("insert into artifact (name, date, type) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING RETURNING id", &[
1192-
&info.name,
1193-
&info.date,
1194-
&info.kind,
1195-
])
1196-
.await
1197-
.unwrap();
1205+
.query_opt("insert into artifact (name, date, type) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING RETURNING id", &[
1206+
&info.name,
1207+
&info.date,
1208+
&info.kind,
1209+
])
1210+
.await
1211+
.unwrap();
11981212
self.conn()
11991213
.query_one("select id from artifact where name = $1", &[&info.name])
12001214
.await
@@ -1623,18 +1637,11 @@ where
16231637
.await
16241638
.context("Cannot load benchmark request index")?;
16251639

1626-
let mut all = HashSet::with_capacity(requests.len());
1627-
let mut completed = HashSet::with_capacity(requests.len());
1628-
for request in requests {
1629-
let tag = request.get::<_, String>(0);
1630-
let status = request.get::<_, &str>(1);
1631-
1632-
if status == BENCHMARK_REQUEST_STATUS_COMPLETED_STR {
1633-
completed.insert(tag.clone());
1634-
}
1635-
all.insert(tag);
1636-
}
1637-
Ok(BenchmarkRequestIndex { all, completed })
1640+
let all = requests
1641+
.into_iter()
1642+
.map(|row| row.get::<_, String>(0))
1643+
.collect();
1644+
Ok(BenchmarkRequestIndex { all })
16381645
}
16391646

16401647
async fn update_benchmark_request_status(
@@ -1705,25 +1712,30 @@ where
17051712
Ok(())
17061713
}
17071714

1708-
async fn load_pending_benchmark_requests(&self) -> anyhow::Result<Vec<BenchmarkRequest>> {
1709-
let query = format!(
1710-
r#"
1711-
SELECT {BENCHMARK_REQUEST_COLUMNS}
1712-
FROM benchmark_request
1713-
WHERE status IN('{BENCHMARK_REQUEST_STATUS_ARTIFACTS_READY_STR}', '{BENCHMARK_REQUEST_STATUS_IN_PROGRESS_STR}')"#
1714-
);
1715-
1715+
async fn load_pending_benchmark_requests(&self) -> anyhow::Result<PendingBenchmarkRequests> {
17161716
let rows = self
17171717
.conn()
1718-
.query(&query, &[])
1718+
.query(&self.statements().load_pending_benchmark_requests, &[])
17191719
.await
17201720
.context("Failed to get pending benchmark requests")?;
17211721

1722-
let requests = rows
1723-
.into_iter()
1724-
.map(|it| row_to_benchmark_request(&it, None))
1725-
.collect();
1726-
Ok(requests)
1722+
let mut completed_parent_tags = HashSet::new();
1723+
let mut requests = Vec::with_capacity(rows.len());
1724+
for row in rows {
1725+
let parent_done = row.get::<_, Option<bool>>(0);
1726+
let request = row_to_benchmark_request(&row, Some(1));
1727+
if let Some(true) = parent_done {
1728+
if let Some(parent) = request.parent_sha() {
1729+
completed_parent_tags.insert(parent.to_string());
1730+
}
1731+
}
1732+
requests.push(request);
1733+
}
1734+
1735+
Ok(PendingBenchmarkRequests {
1736+
requests,
1737+
completed_parent_tags,
1738+
})
17271739
}
17281740

17291741
async fn enqueue_benchmark_job(

database/src/pool/sqlite.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
ArtifactCollection, ArtifactId, Benchmark, BenchmarkJob, BenchmarkJobConclusion,
55
BenchmarkRequest, BenchmarkRequestIndex, BenchmarkRequestStatus, BenchmarkRequestWithErrors,
66
BenchmarkSet, CodegenBackend, CollectionId, CollectorConfig, Commit, CommitType,
7-
CompileBenchmark, Date, Profile, Target,
7+
CompileBenchmark, Date, PendingBenchmarkRequests, Profile, Target,
88
};
99
use crate::{ArtifactIdNumber, Index, QueuedCommit};
1010
use chrono::{DateTime, TimeZone, Utc};
@@ -1306,7 +1306,7 @@ impl Connection for SqliteConnection {
13061306
no_queue_implementation_abort!()
13071307
}
13081308

1309-
async fn load_pending_benchmark_requests(&self) -> anyhow::Result<Vec<BenchmarkRequest>> {
1309+
async fn load_pending_benchmark_requests(&self) -> anyhow::Result<PendingBenchmarkRequests> {
13101310
no_queue_implementation_abort!()
13111311
}
13121312

database/src/tests/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,20 @@ impl TestContext {
139139
req
140140
}
141141

142+
/// Create a new release benchmark request and add it to the DB.
143+
pub async fn insert_release_request(&self, tag: &str) -> BenchmarkRequest {
144+
let req = BenchmarkRequest::create_release(tag, Utc::now());
145+
self.db().insert_benchmark_request(&req).await.unwrap();
146+
req
147+
}
148+
149+
/// Create a new try benchmark request without artifacts and add it to the DB.
150+
pub async fn insert_try_request(&self, pr: u32) -> BenchmarkRequest {
151+
let req = BenchmarkRequest::create_try_without_artifacts(pr, "", "");
152+
self.db().insert_benchmark_request(&req).await.unwrap();
153+
req
154+
}
155+
142156
pub async fn complete_request(&self, tag: &str) {
143157
// Note: this assumes that there are not non-completed jobs in the DB for the request
144158
self.db()

0 commit comments

Comments
 (0)