Skip to content

Commit d7628d2

Browse files
Import from sqlite into postgres DB
This provides a pathway for us to import results from local machines into the official perf server so they can be incorporated into blog posts and similar material relatively easily.
1 parent 269b9c1 commit d7628d2

File tree

6 files changed

+181
-23
lines changed

6 files changed

+181
-23
lines changed

collector/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ fn bench(
236236
let mut tx = rt.block_on(conn.transaction());
237237
rt.block_on(
238238
tx.conn()
239-
.record_benchmark(benchmark.name.0.as_str(), benchmark.supports_stable()),
239+
.record_benchmark(benchmark.name.0.as_str(), Some(benchmark.supports_stable())),
240240
);
241241
eprintln!(
242242
"{}",

database/src/bin/import-sqlite.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use database::{Lookup, Pool};
2+
use std::collections::HashSet;
3+
4+
#[tokio::main]
5+
async fn main() {
6+
env_logger::init();
7+
8+
let sqlite = std::env::args()
9+
.nth(1)
10+
.unwrap_or_else(|| panic!("needs sqlite database as 1st argument"));
11+
let postgres = std::env::args()
12+
.nth(2)
13+
.unwrap_or_else(|| panic!("needs postgres database as 2nd argument"));
14+
15+
let sqlite = Pool::open(&sqlite);
16+
let mut sqlite_conn = sqlite.connection().await;
17+
let postgres = Pool::open(&postgres);
18+
let postgres_conn = postgres.connection().await;
19+
20+
let sqlite_idx = sqlite_conn.load_index().await;
21+
22+
let cid_name = format!("imported-{}", chrono::Utc::now().timestamp());
23+
println!("Collection ID for import is {}", cid_name);
24+
let cid = postgres_conn.collection_id(&cid_name).await;
25+
26+
let mut benchmarks = HashSet::new();
27+
28+
// Starting after the sqlite and postgres db args, the rest are artifact
29+
// names to import.
30+
for artifact in std::env::args().skip(3) {
31+
let aid = sqlite_conn
32+
.artifact_by_name(&artifact)
33+
.await
34+
.unwrap_or_else(|| {
35+
panic!("{} not found in sqlite db", artifact);
36+
});
37+
38+
let sqlite_aid = sqlite_conn.artifact_id(&aid).await;
39+
let postgres_aid = postgres_conn.artifact_id(&aid).await;
40+
41+
for &(krate, profile, cache, stat) in sqlite_idx.all_pstat_series() {
42+
if benchmarks.insert(krate) {
43+
postgres_conn.record_benchmark(krate.as_str(), None).await;
44+
}
45+
46+
let id = database::DbLabel::ProcessStat {
47+
krate,
48+
profile,
49+
cache,
50+
stat,
51+
}
52+
.lookup(&sqlite_idx)
53+
.unwrap();
54+
55+
let value = sqlite_conn
56+
.get_pstats(&[id], &[Some(sqlite_aid)])
57+
.await
58+
.pop()
59+
.unwrap()
60+
.pop()
61+
.unwrap();
62+
if let Some(value) = value {
63+
postgres_conn
64+
.record_statistic(
65+
cid,
66+
postgres_aid,
67+
&krate.to_string(),
68+
profile,
69+
cache,
70+
stat.as_str(),
71+
value,
72+
)
73+
.await;
74+
}
75+
}
76+
}
77+
}

database/src/pool.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,17 @@ pub trait Connection: Send + Sync {
1616

1717
async fn load_index(&mut self) -> Index;
1818

19+
async fn artifact_by_name(&self, artifact: &str) -> Option<ArtifactId>;
20+
1921
/// This records the duration of a collection run, i.e., collecting all of
2022
/// the statistics for a particular artifact.
2123
async fn record_duration(&self, artifact: ArtifactIdNumber, duration: Duration);
2224

2325
async fn collection_id(&self, version: &str) -> CollectionId;
2426
async fn artifact_id(&self, artifact: &ArtifactId) -> ArtifactIdNumber;
25-
async fn record_benchmark(&self, krate: &str, supports_stable: bool);
27+
/// None means that the caller doesn't know; it should be left alone if
28+
/// known or set to false if unknown.
29+
async fn record_benchmark(&self, krate: &str, supports_stable: Option<bool>);
2630
async fn record_statistic(
2731
&self,
2832
collection: CollectionId,

database/src/pool/postgres.rs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ where
941941
.await
942942
.unwrap();
943943
}
944-
async fn record_benchmark(&self, krate: &str, supports_stable: bool) {
944+
async fn record_benchmark(&self, krate: &str, supports_stable: Option<bool>) {
945945
if let Some(r) = self
946946
.conn()
947947
.query_opt(
@@ -951,18 +951,29 @@ where
951951
.await
952952
.unwrap()
953953
{
954-
if r.get::<_, bool>(0) == supports_stable {
954+
if Some(r.get::<_, bool>(0)) == supports_stable {
955955
return;
956956
}
957957
}
958-
self.conn()
959-
.execute(
960-
"insert into benchmark (name, stabilized) VALUES ($1, $2)
958+
if let Some(stable) = supports_stable {
959+
self.conn()
960+
.execute(
961+
"insert into benchmark (name, stabilized) VALUES ($1, $2)
961962
ON CONFLICT (name) DO UPDATE SET stabilized = EXCLUDED.stabilized",
962-
&[&krate, &supports_stable],
963-
)
964-
.await
965-
.unwrap();
963+
&[&krate, &stable],
964+
)
965+
.await
966+
.unwrap();
967+
} else {
968+
self.conn()
969+
.execute(
970+
"insert into benchmark (name, stabilized) VALUES ($1, $2)
971+
ON CONFLICT DO NOTHING",
972+
&[&krate, &false],
973+
)
974+
.await
975+
.unwrap();
976+
}
966977
}
967978

968979
async fn collector_start(&self, aid: ArtifactIdNumber, steps: &[String]) {
@@ -1197,4 +1208,30 @@ where
11971208

11981209
result
11991210
}
1211+
1212+
async fn artifact_by_name(&self, artifact: &str) -> Option<ArtifactId> {
1213+
let row = self
1214+
.conn()
1215+
.query_opt(
1216+
"select date, type from artifact where name = $1",
1217+
&[&artifact],
1218+
)
1219+
.await
1220+
.unwrap()?;
1221+
let date = row.get::<_, Option<DateTime<Utc>>>(0);
1222+
let ty = row.get::<_, String>(1);
1223+
1224+
match ty.as_str() {
1225+
"master" => Some(ArtifactId::Commit(Commit {
1226+
sha: artifact.to_owned(),
1227+
date: Date(date.expect("date present for master commits")),
1228+
})),
1229+
"try" => Some(ArtifactId::Commit(Commit {
1230+
sha: artifact.to_owned(),
1231+
date: Date::ymd_hms(2000, 1, 1, 0, 0, 0),
1232+
})),
1233+
"release" => Some(ArtifactId::Artifact(artifact.to_owned())),
1234+
_ => panic!("unknown artifact type: {:?}", ty),
1235+
}
1236+
}
12001237
}

database/src/pool/sqlite.rs

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl Connection for SqliteConnection {
255255
.unwrap()
256256
.query_map(params![], |row| {
257257
Ok((
258-
row.get::<_, i16>(0)? as u32,
258+
row.get::<_, i32>(0)? as u32,
259259
Commit {
260260
sha: row.get::<_, String>(1)?.as_str().into(),
261261
date: {
@@ -277,7 +277,7 @@ impl Connection for SqliteConnection {
277277
.unwrap()
278278
.query_map(params![], |row| {
279279
Ok((
280-
row.get::<_, i16>(0)? as u32,
280+
row.get::<_, i32>(0)? as u32,
281281
row.get::<_, String>(1)?.into_boxed_str(),
282282
))
283283
})
@@ -635,7 +635,7 @@ impl Connection for SqliteConnection {
635635
.query_row(
636636
"select id from artifact where name = $1",
637637
params![&name],
638-
|r| r.get::<_, i16>(0),
638+
|r| r.get::<_, i32>(0),
639639
)
640640
.unwrap() as u32,
641641
)
@@ -713,14 +713,24 @@ impl Connection for SqliteConnection {
713713
)
714714
.unwrap();
715715
}
716-
async fn record_benchmark(&self, krate: &str, supports_stable: bool) {
717-
self.raw_ref()
718-
.execute(
719-
"insert into benchmark (name, stabilized) VALUES (?, ?)
716+
async fn record_benchmark(&self, krate: &str, supports_stable: Option<bool>) {
717+
if let Some(stable) = supports_stable {
718+
self.raw_ref()
719+
.execute(
720+
"insert into benchmark (name, stabilized) VALUES (?, ?)
720721
ON CONFLICT (name) do update set stabilized = excluded.stabilized",
721-
params![krate, supports_stable],
722-
)
723-
.unwrap();
722+
params![krate, stable],
723+
)
724+
.unwrap();
725+
} else {
726+
self.raw_ref()
727+
.execute(
728+
"insert into benchmark (name, stabilized) VALUES (?, ?)
729+
ON CONFLICT DO NOTHING",
730+
params![krate, false],
731+
)
732+
.unwrap();
733+
}
724734
}
725735
async fn collector_start(&self, aid: ArtifactIdNumber, steps: &[String]) {
726736
// Clean out any leftover unterminated steps.
@@ -771,7 +781,7 @@ impl Connection for SqliteConnection {
771781
)
772782
.unwrap();
773783

774-
let aids = aids.query_map(params![], |r| r.get::<_, i16>(0)).unwrap();
784+
let aids = aids.query_map(params![], |r| r.get::<_, i32>(0)).unwrap();
775785

776786
let mut artifacts = Vec::new();
777787
for aid in aids {
@@ -932,4 +942,31 @@ impl Connection for SqliteConnection {
932942

933943
results
934944
}
945+
946+
async fn artifact_by_name(&self, artifact: &str) -> Option<ArtifactId> {
947+
let (date, ty) = self
948+
.raw_ref()
949+
.prepare("select date, type from artifact where name = ?")
950+
.unwrap()
951+
.query_row(params![&artifact], |r| {
952+
let date = r.get::<_, Option<i64>>(0)?;
953+
let ty = r.get::<_, String>(1)?;
954+
Ok((date, ty))
955+
})
956+
.optional()
957+
.unwrap()?;
958+
959+
match ty.as_str() {
960+
"master" => Some(ArtifactId::Commit(Commit {
961+
sha: artifact.to_owned(),
962+
date: Date(Utc.timestamp(date.expect("master has date"), 0)),
963+
})),
964+
"try" => Some(ArtifactId::Commit(Commit {
965+
sha: artifact.to_owned(),
966+
date: Date::ymd_hms(2000, 1, 1, 0, 0, 0),
967+
})),
968+
"release" => Some(ArtifactId::Artifact(artifact.to_owned())),
969+
_ => panic!("unknown artifact type: {:?}", ty),
970+
}
971+
}
935972
}

site/src/server.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ pub async fn handle_dashboard(data: Arc<InputData>) -> ServerResult<dashboard::R
101101
return Ok(dashboard::Response::default());
102102
}
103103

104-
let mut versions = index.artifacts().collect::<Vec<_>>();
104+
let mut versions = index
105+
.artifacts()
106+
.filter(|a| a.starts_with("1.") || a.starts_with("beta"))
107+
.collect::<Vec<_>>();
105108
versions.sort_by(|a, b| {
106109
match (
107110
a.parse::<semver::Version>().ok(),

0 commit comments

Comments
 (0)