1
- use std:: collections:: HashSet ;
1
+ use std:: collections:: { BTreeMap , HashSet } ;
2
2
use std:: io:: Read ;
3
3
use std:: sync:: Arc ;
4
4
use std:: time:: { Duration , Instant } ;
5
5
6
6
use bytes:: Buf ;
7
+ use database:: ArtifactIdNumber ;
7
8
use headers:: { ContentType , Header } ;
8
9
use hyper:: StatusCode ;
9
10
11
+ use crate :: api:: self_profile:: ArtifactSizeDelta ;
10
12
use crate :: api:: { self_profile, self_profile_processed, self_profile_raw, ServerResult } ;
11
13
use crate :: db:: ArtifactId ;
12
14
use crate :: load:: SiteCtxt ;
@@ -142,6 +144,7 @@ pub async fn handle_self_profile_processed_download(
142
144
fn get_self_profile_data (
143
145
cpu_clock : Option < f64 > ,
144
146
self_profile : Option < crate :: selector:: SelfProfileData > ,
147
+ raw_data : Vec < u8 > ,
145
148
) -> ServerResult < self_profile:: SelfProfile > {
146
149
let profile = self_profile
147
150
. as_ref ( )
@@ -178,6 +181,7 @@ fn get_self_profile_data(
178
181
. map ( |qd| qd. incremental_load_time )
179
182
. sum ( ) ,
180
183
} ;
184
+ let artifact_sizes = raw_mmprof_data_to_artifact_sizes ( raw_data) . ok ( ) ;
181
185
let profile = self_profile:: SelfProfile {
182
186
query_data : profile
183
187
. query_data
@@ -195,6 +199,7 @@ fn get_self_profile_data(
195
199
} )
196
200
. collect ( ) ,
197
201
totals,
202
+ artifact_sizes,
198
203
} ;
199
204
200
205
Ok ( profile)
@@ -239,11 +244,11 @@ fn add_uninvoked_base_profile_queries(
239
244
fn get_self_profile_delta (
240
245
profile : & self_profile:: SelfProfile ,
241
246
base_profile : & Option < self_profile:: SelfProfile > ,
247
+ raw_data : Vec < u8 > ,
248
+ base_raw_data : Option < Vec < u8 > > ,
242
249
) -> Option < self_profile:: SelfProfileDelta > {
243
- let base_profile = match base_profile. as_ref ( ) {
244
- Some ( bp) => bp,
245
- None => return None ,
246
- } ;
250
+ let base_profile = base_profile. as_ref ( ) ?;
251
+ let base_raw_data = base_raw_data?;
247
252
248
253
let totals = self_profile:: QueryDataDelta {
249
254
self_time : profile. totals . self_time as i64 - base_profile. totals . self_time as i64 ,
@@ -283,7 +288,21 @@ fn get_self_profile_delta(
283
288
}
284
289
}
285
290
286
- Some ( self_profile:: SelfProfileDelta { totals, query_data } )
291
+ let first = raw_mmprof_data_to_artifact_sizes ( raw_data) . unwrap_or_else ( |_| Vec :: new ( ) ) ;
292
+ let base = raw_mmprof_data_to_artifact_sizes ( base_raw_data) . unwrap_or_else ( |_| Vec :: new ( ) ) ;
293
+ let artifact_sizes = first
294
+ . into_iter ( )
295
+ . zip ( base. into_iter ( ) )
296
+ . map ( |( a1, a2) | ArtifactSizeDelta {
297
+ bytes : a1. bytes - a2. bytes ,
298
+ } )
299
+ . collect ( ) ;
300
+
301
+ Some ( self_profile:: SelfProfileDelta {
302
+ totals,
303
+ query_data,
304
+ artifact_sizes,
305
+ } )
287
306
}
288
307
289
308
fn sort_self_profile (
@@ -489,10 +508,10 @@ pub async fn handle_self_profile_raw(
489
508
) -> ServerResult < self_profile_raw:: Response > {
490
509
log:: info!( "handle_self_profile_raw({:?})" , body) ;
491
510
let mut it = body. benchmark . rsplitn ( 2 , '-' ) ;
492
- let bench_ty = it. next ( ) . ok_or ( format ! ( "no benchmark type" ) ) ?;
511
+ let profile = it. next ( ) . ok_or ( format ! ( "no benchmark type" ) ) ?;
493
512
let bench_name = it. next ( ) . ok_or ( format ! ( "no benchmark name" ) ) ?;
494
513
495
- let cache = body
514
+ let scenario = body
496
515
. run_name
497
516
. parse :: < database:: Scenario > ( )
498
517
. map_err ( |e| format ! ( "invalid run name: {:?}" , e) ) ?;
@@ -506,7 +525,7 @@ pub async fn handle_self_profile_raw(
506
525
date : database:: Date :: empty ( ) ,
507
526
} ) ,
508
527
bench_name,
509
- bench_ty ,
528
+ profile ,
510
529
& body. run_name ,
511
530
)
512
531
. await ;
@@ -526,20 +545,20 @@ pub async fn handle_self_profile_raw(
526
545
_ => first_cid,
527
546
} ;
528
547
548
+ let cids = aids_and_cids
549
+ . into_iter ( )
550
+ . map ( |( _, cid) | cid)
551
+ . collect :: < Vec < _ > > ( ) ;
552
+
529
553
let url_prefix = format ! (
530
554
"https://perf-data.rust-lang.org/self-profile/{}/{}/{}/{}/self-profile-{}" ,
531
555
aid. 0 ,
532
556
bench_name,
533
- bench_ty ,
534
- cache . to_id( ) ,
557
+ profile ,
558
+ scenario . to_id( ) ,
535
559
cid,
536
560
) ;
537
561
538
- let cids = aids_and_cids
539
- . into_iter ( )
540
- . map ( |( _, cid) | cid)
541
- . collect :: < Vec < _ > > ( ) ;
542
-
543
562
return match fetch ( & cids, cid, format ! ( "{}.mm_profdata.sz" , url_prefix) ) . await {
544
563
Ok ( fetched) => Ok ( fetched) ,
545
564
Err ( new_error) => Err ( format ! ( "mm_profdata download failed: {:?}" , new_error, ) ) ,
@@ -570,6 +589,21 @@ pub async fn handle_self_profile_raw(
570
589
}
571
590
}
572
591
592
+ pub async fn fetch_raw_self_profile_data (
593
+ aid : ArtifactIdNumber ,
594
+ benchmark : & str ,
595
+ profile : & str ,
596
+ scenario : & str ,
597
+ cid : i32 ,
598
+ ) -> Result < Vec < u8 > , Response > {
599
+ let url = format ! (
600
+ "https://perf-data.rust-lang.org/self-profile/{}/{}/{}/{}/self-profile-{}.mm_profdata.sz" ,
601
+ aid. 0 , benchmark, profile, scenario, cid,
602
+ ) ;
603
+
604
+ get_self_profile_raw_data ( & url) . await
605
+ }
606
+
573
607
pub async fn handle_self_profile (
574
608
body : self_profile:: Request ,
575
609
ctxt : & SiteCtxt ,
@@ -653,30 +687,76 @@ pub async fn handle_self_profile(
653
687
. await ?;
654
688
assert_eq ! ( cpu_responses. len( ) , 1 , "all selectors are exact" ) ;
655
689
let mut cpu_response = cpu_responses. remove ( 0 ) . series ;
656
-
690
+ let mut raw_self_profile_data = Vec :: new ( ) ;
691
+ let conn = ctxt. conn ( ) . await ;
692
+ for commit in commits. iter ( ) {
693
+ let aids_and_cids = conn
694
+ . list_self_profile ( commit. clone ( ) , bench_name, profile, & body. run_name )
695
+ . await ;
696
+ if let Some ( ( aid, cid) ) = aids_and_cids. first ( ) {
697
+ match fetch_raw_self_profile_data ( * aid, bench_name, profile, & body. run_name , * cid) . await
698
+ {
699
+ Ok ( d) => raw_self_profile_data. push ( d) ,
700
+ Err ( _) => return Err ( format ! ( "could not fetch raw profile data" ) ) ,
701
+ } ;
702
+ }
703
+ }
704
+ let raw_data = raw_self_profile_data. remove ( 0 ) ;
657
705
let mut profile = get_self_profile_data (
658
706
cpu_response. next ( ) . unwrap ( ) . 1 ,
659
707
sp_response. next ( ) . unwrap ( ) . 1 ,
708
+ raw_data. clone ( ) ,
660
709
)
661
710
. map_err ( |e| format ! ( "{}: {}" , body. commit, e) ) ?;
662
- let base_profile = if body. base_commit . is_some ( ) {
663
- Some (
664
- get_self_profile_data (
665
- cpu_response. next ( ) . unwrap ( ) . 1 ,
666
- sp_response. next ( ) . unwrap ( ) . 1 ,
667
- )
668
- . map_err ( |e| format ! ( "{}: {}" , body. base_commit. as_ref( ) . unwrap( ) , e) ) ?,
711
+ let ( base_profile, base_raw_data) = if body. base_commit . is_some ( ) {
712
+ let base_raw_data = raw_self_profile_data. remove ( 0 ) ;
713
+ let profile = get_self_profile_data (
714
+ cpu_response. next ( ) . unwrap ( ) . 1 ,
715
+ sp_response. next ( ) . unwrap ( ) . 1 ,
716
+ base_raw_data. clone ( ) ,
669
717
)
718
+ . map_err ( |e| format ! ( "{}: {}" , body. base_commit. as_ref( ) . unwrap( ) , e) ) ?;
719
+ ( Some ( profile) , Some ( base_raw_data) )
670
720
} else {
671
- None
721
+ ( None , None )
672
722
} ;
673
723
674
724
add_uninvoked_base_profile_queries ( & mut profile, & base_profile) ;
675
- let mut base_profile_delta = get_self_profile_delta ( & profile, & base_profile) ;
725
+ let mut base_profile_delta =
726
+ get_self_profile_delta ( & profile, & base_profile, raw_data, base_raw_data) ;
676
727
sort_self_profile ( & mut profile, & mut base_profile_delta, sort_idx) ;
677
728
678
729
Ok ( self_profile:: Response {
679
730
base_profile_delta,
680
731
profile,
681
732
} )
682
733
}
734
+
735
+ fn raw_mmprof_data_to_artifact_sizes (
736
+ data : Vec < u8 > ,
737
+ ) -> anyhow:: Result < Vec < self_profile:: ArtifactSize > > {
738
+ let profiling_data = analyzeme:: ProfilingData :: from_paged_buffer ( data, None )
739
+ . map_err ( |_| anyhow:: Error :: msg ( "could not parse profiling data" ) ) ?;
740
+
741
+ let mut artifact_sizes: BTreeMap < _ , u64 > = Default :: default ( ) ;
742
+
743
+ for event in profiling_data. iter_full ( ) {
744
+ // TODO: Use constant from measureme::rustc
745
+ if event. event_kind == "ArtifactSize" {
746
+ if !event. payload . is_integer ( ) {
747
+ anyhow:: bail!( "Found ArtifactSize payload that is not an integer" )
748
+ }
749
+
750
+ let bytes = event. payload . integer ( ) . unwrap ( ) ;
751
+ * artifact_sizes. entry ( event. label ) . or_default ( ) += bytes;
752
+ }
753
+ }
754
+
755
+ Ok ( artifact_sizes
756
+ . iter ( )
757
+ . map ( |( k, v) | self_profile:: ArtifactSize {
758
+ label : k[ ..] . into ( ) ,
759
+ bytes : * v,
760
+ } )
761
+ . collect ( ) )
762
+ }
0 commit comments