@@ -5,6 +5,7 @@ use crate::prelude::*;
55use crate :: results:: {
66 DeleteResults , EncodedLog , EncodingType , ReadResults , TestResult , WriteResults ,
77} ;
8+ use crate :: timings:: TimingInfo ;
89use crate :: toolchain:: Toolchain ;
910use base64:: Engine ;
1011use rustwide:: logging:: { self , LogStorage } ;
@@ -145,6 +146,69 @@ impl<'a> DatabaseDB<'a> {
145146 Ok ( ( ) )
146147 }
147148
149+ pub fn store_timings (
150+ & self ,
151+ ex : & Experiment ,
152+ krate : & Crate ,
153+ toolchain : & Toolchain ,
154+ timings : & [ TimingInfo ] ,
155+ ) -> Fallible < ( ) > {
156+ for timing in timings {
157+ let target_kind = timing. target . kind . join ( "," ) ;
158+ self . db . execute_cached (
159+ "INSERT INTO build_timings \
160+ (experiment, crate, toolchain, package_id, target_name, target_kind, mode, duration, rmeta_time) \
161+ VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9);",
162+ & [
163+ & ex. name as & dyn rusqlite:: types:: ToSql ,
164+ & krate. id ( ) ,
165+ & toolchain. to_string ( ) ,
166+ & timing. package_id ,
167+ & timing. target . name ,
168+ & target_kind,
169+ & timing. mode ,
170+ & timing. duration ,
171+ & timing. rmeta_time ,
172+ ] ,
173+ ) ?;
174+ }
175+ Ok ( ( ) )
176+ }
177+
178+ pub fn load_timings (
179+ & self ,
180+ ex : & Experiment ,
181+ krate : & Crate ,
182+ toolchain : & Toolchain ,
183+ ) -> Fallible < Vec < TimingInfo > > {
184+ self . db . query (
185+ "SELECT package_id, target_name, target_kind, mode, duration, rmeta_time \
186+ FROM build_timings \
187+ WHERE experiment = ?1 AND crate = ?2 AND toolchain = ?3;",
188+ [ & ex. name , & krate. id ( ) , & toolchain. to_string ( ) ] ,
189+ |row| {
190+ let target_kind: String = row. get ( "target_kind" ) ?;
191+ let kinds: Vec < String > = target_kind. split ( ',' ) . map ( |s| s. to_string ( ) ) . collect ( ) ;
192+ Ok ( TimingInfo {
193+ package_id : row. get ( "package_id" ) ?,
194+ target : crate :: timings:: TimingTarget {
195+ kind : kinds,
196+ crate_types : Vec :: new ( ) ,
197+ name : row. get ( "target_name" ) ?,
198+ src_path : String :: new ( ) ,
199+ edition : String :: new ( ) ,
200+ doc : false ,
201+ doctest : false ,
202+ test : false ,
203+ } ,
204+ mode : row. get ( "mode" ) ?,
205+ duration : row. get ( "duration" ) ?,
206+ rmeta_time : row. get ( "rmeta_time" ) ?,
207+ } )
208+ } ,
209+ )
210+ }
211+
148212 fn insert_into_results (
149213 & self ,
150214 ex : & Experiment ,
@@ -274,6 +338,16 @@ impl crate::runner::RecordProgress for DatabaseDB<'_> {
274338 }
275339 Ok ( ( ) )
276340 }
341+
342+ fn record_timings (
343+ & self ,
344+ ex : & Experiment ,
345+ krate : & Crate ,
346+ toolchain : & Toolchain ,
347+ timings : & [ TimingInfo ] ,
348+ ) -> Fallible < ( ) > {
349+ self . store_timings ( ex, krate, toolchain, timings)
350+ }
277351}
278352
279353impl DeleteResults for DatabaseDB < ' _ > {
@@ -470,6 +544,85 @@ mod tests {
470544 . is_none( ) ) ;
471545 }
472546
547+ #[ test]
548+ fn test_store_and_load_timings ( ) {
549+ let db = Database :: temp ( ) . unwrap ( ) ;
550+ let results = DatabaseDB :: new ( & db) ;
551+ let config = Config :: default ( ) ;
552+ let ctx = ActionsCtx :: new ( & db, & config) ;
553+
554+ crate :: crates:: lists:: setup_test_lists ( & db, & config) . unwrap ( ) ;
555+
556+ CreateExperiment :: dummy ( "dummy" ) . apply ( & ctx) . unwrap ( ) ;
557+ let ex = Experiment :: get ( & db, "dummy" ) . unwrap ( ) . unwrap ( ) ;
558+
559+ let krate = Crate :: Registry ( RegistryCrate {
560+ name : "lazy_static" . into ( ) ,
561+ version : "1" . into ( ) ,
562+ } ) ;
563+
564+ let timings = vec ! [
565+ crate :: timings:: TimingInfo {
566+ package_id: "serde 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)"
567+ . to_string( ) ,
568+ target: crate :: timings:: TimingTarget {
569+ kind: vec![ "lib" . to_string( ) ] ,
570+ crate_types: vec![ "lib" . to_string( ) ] ,
571+ name: "serde" . to_string( ) ,
572+ src_path: "/path/to/src/lib.rs" . to_string( ) ,
573+ edition: "2021" . to_string( ) ,
574+ doc: true ,
575+ doctest: true ,
576+ test: true ,
577+ } ,
578+ mode: "build" . to_string( ) ,
579+ duration: 12.5 ,
580+ rmeta_time: Some ( 8.3 ) ,
581+ } ,
582+ crate :: timings:: TimingInfo {
583+ package_id: "foo 0.1.0" . to_string( ) ,
584+ target: crate :: timings:: TimingTarget {
585+ kind: vec![ "bin" . to_string( ) ] ,
586+ crate_types: vec![ "bin" . to_string( ) ] ,
587+ name: "foo" . to_string( ) ,
588+ src_path: "/path/to/main.rs" . to_string( ) ,
589+ edition: "2021" . to_string( ) ,
590+ doc: false ,
591+ doctest: false ,
592+ test: false ,
593+ } ,
594+ mode: "build" . to_string( ) ,
595+ duration: 1.0 ,
596+ rmeta_time: None ,
597+ } ,
598+ ] ;
599+
600+ results
601+ . store_timings ( & ex, & krate, & MAIN_TOOLCHAIN , & timings)
602+ . unwrap ( ) ;
603+
604+ let loaded = results. load_timings ( & ex, & krate, & MAIN_TOOLCHAIN ) . unwrap ( ) ;
605+
606+ assert_eq ! ( loaded. len( ) , 2 ) ;
607+
608+ assert_eq ! ( loaded[ 0 ] . package_id, timings[ 0 ] . package_id) ;
609+ assert_eq ! ( loaded[ 0 ] . target. name, "serde" ) ;
610+ assert_eq ! ( loaded[ 0 ] . target. kind, vec![ "lib" ] ) ;
611+ assert_eq ! ( loaded[ 0 ] . mode, "build" ) ;
612+ assert ! ( ( loaded[ 0 ] . duration - 12.5 ) . abs( ) < f64 :: EPSILON ) ;
613+ assert ! ( ( loaded[ 0 ] . rmeta_time. unwrap( ) - 8.3 ) . abs( ) < f64 :: EPSILON ) ;
614+
615+ assert_eq ! ( loaded[ 1 ] . package_id, "foo 0.1.0" ) ;
616+ assert_eq ! ( loaded[ 1 ] . target. name, "foo" ) ;
617+ assert_eq ! ( loaded[ 1 ] . target. kind, vec![ "bin" ] ) ;
618+ assert ! ( ( loaded[ 1 ] . duration - 1.0 ) . abs( ) < f64 :: EPSILON ) ;
619+ assert ! ( loaded[ 1 ] . rmeta_time. is_none( ) ) ;
620+
621+ // Different toolchain should return empty
622+ let empty = results. load_timings ( & ex, & krate, & TEST_TOOLCHAIN ) . unwrap ( ) ;
623+ assert ! ( empty. is_empty( ) ) ;
624+ }
625+
473626 #[ test]
474627 fn test_store ( ) {
475628 let db = Database :: temp ( ) . unwrap ( ) ;
0 commit comments