Skip to content

Commit 99cf314

Browse files
committed
Fetch self profile data from s3 on demand and parse artifact sizes
1 parent a70d306 commit 99cf314

File tree

2 files changed

+116
-13
lines changed

2 files changed

+116
-13
lines changed

site/src/api.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ pub mod self_profile {
296296
pub struct SelfProfile {
297297
pub totals: QueryData,
298298
pub query_data: Vec<QueryData>,
299+
pub artifact_sizes: Option<Vec<ArtifactSize>>,
299300
}
300301

301302
#[derive(Serialize, Deserialize, Clone, Debug)]
@@ -313,10 +314,17 @@ pub mod self_profile {
313314
pub incremental_load_time: u64,
314315
}
315316

317+
#[derive(Serialize, Deserialize, Clone, Debug)]
318+
pub struct ArtifactSize {
319+
pub label: QueryLabel,
320+
pub bytes: u64,
321+
}
322+
316323
#[derive(Serialize, Debug, Clone)]
317324
pub struct SelfProfileDelta {
318325
pub totals: QueryDataDelta,
319326
pub query_data: Vec<QueryDataDelta>,
327+
pub artifact_sizes: Vec<ArtifactSizeDelta>,
320328
}
321329

322330
#[derive(Serialize, Clone, Debug)]
@@ -327,6 +335,11 @@ pub mod self_profile {
327335
// Nanoseconds
328336
pub incremental_load_time: i64,
329337
}
338+
339+
#[derive(Serialize, Clone, Debug)]
340+
pub struct ArtifactSizeDelta {
341+
pub bytes: u64,
342+
}
330343
}
331344

332345
pub mod github {

site/src/request_handlers/self_profile.rs

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ use bytes::Buf;
77
use headers::{ContentType, Header};
88
use hyper::StatusCode;
99

10+
use crate::api::self_profile::ArtifactSizeDelta;
1011
use crate::api::{self_profile, self_profile_processed, self_profile_raw, ServerResult};
1112
use crate::db::ArtifactId;
1213
use crate::load::SiteCtxt;
1314
use crate::selector::{self, Tag};
1415
use crate::server::{Response, ResponseHeaders};
1516

17+
use std::collections::BTreeMap;
18+
1619
pub async fn handle_self_profile_processed_download(
1720
body: self_profile_processed::Request,
1821
ctxt: &SiteCtxt,
@@ -142,6 +145,7 @@ pub async fn handle_self_profile_processed_download(
142145
fn get_self_profile_data(
143146
cpu_clock: Option<f64>,
144147
self_profile: Option<crate::selector::SelfProfileData>,
148+
raw_data: Vec<u8>,
145149
) -> ServerResult<self_profile::SelfProfile> {
146150
let profile = self_profile
147151
.as_ref()
@@ -178,6 +182,7 @@ fn get_self_profile_data(
178182
.map(|qd| qd.incremental_load_time)
179183
.sum(),
180184
};
185+
let artifact_sizes = raw_mmprof_data_to_artifact_sizes(raw_data).ok();
181186
let profile = self_profile::SelfProfile {
182187
query_data: profile
183188
.query_data
@@ -195,6 +200,7 @@ fn get_self_profile_data(
195200
})
196201
.collect(),
197202
totals,
203+
artifact_sizes,
198204
};
199205

200206
Ok(profile)
@@ -239,6 +245,8 @@ fn add_uninvoked_base_profile_queries(
239245
fn get_self_profile_delta(
240246
profile: &self_profile::SelfProfile,
241247
base_profile: &Option<self_profile::SelfProfile>,
248+
raw_data: Vec<u8>,
249+
base_raw_data: Vec<u8>,
242250
) -> Option<self_profile::SelfProfileDelta> {
243251
let base_profile = match base_profile.as_ref() {
244252
Some(bp) => bp,
@@ -283,7 +291,21 @@ fn get_self_profile_delta(
283291
}
284292
}
285293

286-
Some(self_profile::SelfProfileDelta { totals, query_data })
294+
let first = raw_mmprof_data_to_artifact_sizes(raw_data).unwrap_or_else(|_| Vec::new());
295+
let base = raw_mmprof_data_to_artifact_sizes(base_raw_data).unwrap_or_else(|_| Vec::new());
296+
let artifact_sizes = first
297+
.into_iter()
298+
.zip(base.into_iter())
299+
.map(|(a1, a2)| ArtifactSizeDelta {
300+
bytes: a1.bytes - a2.bytes,
301+
})
302+
.collect();
303+
304+
Some(self_profile::SelfProfileDelta {
305+
totals,
306+
query_data,
307+
artifact_sizes,
308+
})
287309
}
288310

289311
fn sort_self_profile(
@@ -489,10 +511,10 @@ pub async fn handle_self_profile_raw(
489511
) -> ServerResult<self_profile_raw::Response> {
490512
log::info!("handle_self_profile_raw({:?})", body);
491513
let mut it = body.benchmark.rsplitn(2, '-');
492-
let bench_ty = it.next().ok_or(format!("no benchmark type"))?;
514+
let profile = it.next().ok_or(format!("no benchmark type"))?;
493515
let bench_name = it.next().ok_or(format!("no benchmark name"))?;
494516

495-
let cache = body
517+
let scenario = body
496518
.run_name
497519
.parse::<database::Scenario>()
498520
.map_err(|e| format!("invalid run name: {:?}", e))?;
@@ -506,7 +528,7 @@ pub async fn handle_self_profile_raw(
506528
date: database::Date::empty(),
507529
}),
508530
bench_name,
509-
bench_ty,
531+
profile,
510532
&body.run_name,
511533
)
512534
.await;
@@ -526,20 +548,20 @@ pub async fn handle_self_profile_raw(
526548
_ => first_cid,
527549
};
528550

551+
let cids = aids_and_cids
552+
.into_iter()
553+
.map(|(_, cid)| cid)
554+
.collect::<Vec<_>>();
555+
529556
let url_prefix = format!(
530557
"https://perf-data.rust-lang.org/self-profile/{}/{}/{}/{}/self-profile-{}",
531558
aid.0,
532559
bench_name,
533-
bench_ty,
534-
cache.to_id(),
560+
profile,
561+
scenario.to_id(),
535562
cid,
536563
);
537564

538-
let cids = aids_and_cids
539-
.into_iter()
540-
.map(|(_, cid)| cid)
541-
.collect::<Vec<_>>();
542-
543565
return match fetch(&cids, cid, format!("{}.mm_profdata.sz", url_prefix)).await {
544566
Ok(fetched) => Ok(fetched),
545567
Err(new_error) => Err(format!("mm_profdata download failed: {:?}", new_error,)),
@@ -570,6 +592,21 @@ pub async fn handle_self_profile_raw(
570592
}
571593
}
572594

595+
pub async fn fetch_raw_self_profile_data(
596+
aid: &str,
597+
benchmark: &str,
598+
profile: &str,
599+
scenario: &str,
600+
cid: i32,
601+
) -> Result<Vec<u8>, Response> {
602+
let url = format!(
603+
"https://perf-data.rust-lang.org/self-profile/{}/{}/{}/{}/self-profile-{}",
604+
aid, benchmark, profile, scenario, cid,
605+
);
606+
607+
get_self_profile_raw_data(&url).await
608+
}
609+
573610
pub async fn handle_self_profile(
574611
body: self_profile::Request,
575612
ctxt: &SiteCtxt,
@@ -653,17 +690,40 @@ pub async fn handle_self_profile(
653690
.await?;
654691
assert_eq!(cpu_responses.len(), 1, "all selectors are exact");
655692
let mut cpu_response = cpu_responses.remove(0).series;
656-
693+
let mut raw_data = Vec::new();
694+
let conn = ctxt.conn().await;
695+
for commit in commits.iter() {
696+
let aid = match commit {
697+
ArtifactId::Commit(c) => c.sha.as_str(),
698+
ArtifactId::Tag(t) => t.as_str(),
699+
};
700+
let aids_and_cids = conn
701+
.list_self_profile(commit.clone(), bench_name, profile, &body.run_name)
702+
.await;
703+
if let Some((_, cid)) = aids_and_cids.first() {
704+
match fetch_raw_self_profile_data(aid, bench_name, profile, &body.run_name, *cid).await
705+
{
706+
Ok(d) => raw_data.push(d),
707+
Err(_resp) => {
708+
eprintln!("could not fetch raw self_profile data");
709+
}
710+
};
711+
}
712+
}
713+
let raw_datum = raw_data.remove(0);
714+
let base_raw_datum = raw_data.remove(0);
657715
let mut profile = get_self_profile_data(
658716
cpu_response.next().unwrap().1,
659717
sp_response.next().unwrap().1,
718+
raw_datum.clone(),
660719
)
661720
.map_err(|e| format!("{}: {}", body.commit, e))?;
662721
let base_profile = if body.base_commit.is_some() {
663722
Some(
664723
get_self_profile_data(
665724
cpu_response.next().unwrap().1,
666725
sp_response.next().unwrap().1,
726+
base_raw_datum.clone(),
667727
)
668728
.map_err(|e| format!("{}: {}", body.base_commit.as_ref().unwrap(), e))?,
669729
)
@@ -672,11 +732,41 @@ pub async fn handle_self_profile(
672732
};
673733

674734
add_uninvoked_base_profile_queries(&mut profile, &base_profile);
675-
let mut base_profile_delta = get_self_profile_delta(&profile, &base_profile);
735+
let mut base_profile_delta =
736+
get_self_profile_delta(&profile, &base_profile, raw_datum, base_raw_datum);
676737
sort_self_profile(&mut profile, &mut base_profile_delta, sort_idx);
677738

678739
Ok(self_profile::Response {
679740
base_profile_delta,
680741
profile,
681742
})
682743
}
744+
745+
fn raw_mmprof_data_to_artifact_sizes(
746+
data: Vec<u8>,
747+
) -> anyhow::Result<Vec<self_profile::ArtifactSize>> {
748+
let profiling_data = analyzeme::ProfilingData::from_paged_buffer(data, None)
749+
.map_err(|_| anyhow::Error::msg("could not parse profiling data"))?;
750+
751+
let mut artifact_sizes: BTreeMap<_, u64> = Default::default();
752+
753+
for event in profiling_data.iter_full() {
754+
// TODO: Use constant from measureme::rustc
755+
if event.event_kind == "ArtifactSize" {
756+
if !event.payload.is_integer() {
757+
anyhow::bail!("Found ArtifactSize payload that is not an integer")
758+
}
759+
760+
let bytes = event.payload.integer().unwrap();
761+
*artifact_sizes.entry(event.label).or_default() += bytes;
762+
}
763+
}
764+
765+
Ok(artifact_sizes
766+
.iter()
767+
.map(|(k, v)| self_profile::ArtifactSize {
768+
label: k[..].into(),
769+
bytes: *v,
770+
})
771+
.collect())
772+
}

0 commit comments

Comments
 (0)