1- use crate :: query_data:: { ArtifactSize , ArtifactSizeDiff , QueryData , QueryDataDiff , Results } ;
2- use crate :: signed_duration:: SignedDuration ;
1+ use analyzeme:: { AnalysisResults , ArtifactSize , QueryData } ;
32use rustc_hash:: { FxHashMap , FxHashSet } ;
43use serde:: { Deserialize , Serialize } ;
4+ use std:: cmp:: Ordering ;
55use std:: collections:: HashSet ;
6+ use std:: fmt;
67use std:: time:: Duration ;
78
89#[ derive( Serialize , Deserialize ) ]
@@ -30,7 +31,7 @@ fn build_artifact_lookup(artifact_sizes: &[ArtifactSize]) -> FxHashMap<&str, usi
3031 lookup
3132}
3233
33- pub fn calculate_diff ( base : Results , change : Results ) -> DiffResults {
34+ pub fn calculate_diff ( base : AnalysisResults , change : AnalysisResults ) -> DiffResults {
3435 #[ inline]
3536 fn sd ( d : Duration ) -> SignedDuration {
3637 d. into ( )
@@ -54,9 +55,9 @@ pub fn calculate_diff(base: Results, change: Results) -> DiffResults {
5455 let c = change_data. get ( l) . map ( |i| & change. query_data [ * i] ) ;
5556
5657 match ( b, c) {
57- ( Some ( b) , Some ( c) ) => c. clone ( ) - b. clone ( ) ,
58- ( Some ( b) , None ) => b . invert ( ) ,
59- ( None , Some ( c) ) => c . as_query_data_diff ( ) ,
58+ ( Some ( b) , Some ( c) ) => QueryDataDiff :: sub ( c. clone ( ) , b. clone ( ) ) ,
59+ ( Some ( b) , None ) => QueryDataDiff :: invert_query_data ( b ) ,
60+ ( None , Some ( c) ) => QueryDataDiff :: query_data_as_diff ( c ) ,
6061 ( None , None ) => unreachable ! ( ) ,
6162 }
6263 } )
@@ -79,9 +80,9 @@ pub fn calculate_diff(base: Results, change: Results) -> DiffResults {
7980 let c = change_data. get ( l) . map ( |i| & change. artifact_sizes [ * i] ) ;
8081
8182 match ( b, c) {
82- ( Some ( b) , Some ( c) ) => c. clone ( ) - b. clone ( ) ,
83- ( Some ( b) , None ) => b . invert ( ) ,
84- ( None , Some ( c) ) => c . as_artifact_size_diff ( ) ,
83+ ( Some ( b) , Some ( c) ) => ArtifactSizeDiff :: sub ( c. clone ( ) , b. clone ( ) ) ,
84+ ( Some ( b) , None ) => ArtifactSizeDiff :: invert_artifact_size ( b ) ,
85+ ( None , Some ( c) ) => ArtifactSizeDiff :: artifact_size_as_diff ( c ) ,
8586 ( None , None ) => unreachable ! ( ) ,
8687 }
8788 } )
@@ -94,3 +95,234 @@ pub fn calculate_diff(base: Results, change: Results) -> DiffResults {
9495 total_time : sd ( change. total_time ) - sd ( base. total_time ) ,
9596 }
9697}
98+
99+ /// The diff between two `QueryData`
100+ #[ derive( Serialize , Deserialize ) ]
101+ pub struct QueryDataDiff {
102+ pub label : String ,
103+ pub time : SignedDuration ,
104+ pub time_change : f64 ,
105+ pub self_time : SignedDuration ,
106+ pub self_time_change : f64 ,
107+ pub number_of_cache_misses : i64 ,
108+ pub number_of_cache_hits : i64 ,
109+ pub invocation_count : i64 ,
110+ pub blocked_time : SignedDuration ,
111+ pub incremental_load_time : SignedDuration ,
112+ pub incremental_hashing_time : SignedDuration ,
113+ }
114+
115+ impl QueryDataDiff {
116+ fn sub ( lhs : QueryData , rhs : QueryData ) -> QueryDataDiff {
117+ #[ inline( always) ]
118+ fn sd ( d : Duration ) -> SignedDuration {
119+ d. into ( )
120+ }
121+
122+ #[ inline( always) ]
123+ fn i ( u : usize ) -> i64 {
124+ u as i64
125+ }
126+
127+ fn percentage_change ( base : Duration , change : Duration ) -> f64 {
128+ let nanos = change. as_nanos ( ) as i128 - base. as_nanos ( ) as i128 ;
129+ nanos as f64 / base. as_nanos ( ) as f64 * 100.0
130+ }
131+
132+ QueryDataDiff {
133+ label : lhs. label ,
134+ time : sd ( lhs. time ) - sd ( rhs. time ) ,
135+ time_change : percentage_change ( rhs. time , lhs. time ) ,
136+ self_time : sd ( lhs. self_time ) - sd ( rhs. self_time ) ,
137+ self_time_change : percentage_change ( rhs. self_time , lhs. self_time ) ,
138+ number_of_cache_misses : i ( lhs. number_of_cache_misses ) - i ( rhs. number_of_cache_misses ) ,
139+ number_of_cache_hits : i ( lhs. number_of_cache_hits ) - i ( rhs. number_of_cache_hits ) ,
140+ invocation_count : i ( lhs. invocation_count ) - i ( rhs. invocation_count ) ,
141+ blocked_time : sd ( lhs. blocked_time ) - sd ( rhs. blocked_time ) ,
142+ incremental_load_time : sd ( lhs. incremental_load_time ) - sd ( rhs. incremental_load_time ) ,
143+ incremental_hashing_time : sd ( lhs. incremental_hashing_time )
144+ - sd ( rhs. incremental_hashing_time ) ,
145+ }
146+ }
147+
148+ pub fn invert_query_data ( data : & QueryData ) -> QueryDataDiff {
149+ fn invert ( d : Duration ) -> SignedDuration {
150+ SignedDuration {
151+ duration : d,
152+ is_positive : false ,
153+ }
154+ }
155+
156+ QueryDataDiff {
157+ label : data. label . clone ( ) ,
158+ time : invert ( data. time ) ,
159+ time_change : -100.0 ,
160+ self_time : invert ( data. self_time ) ,
161+ self_time_change : -100.0 ,
162+ number_of_cache_misses : -( data. number_of_cache_misses as i64 ) ,
163+ number_of_cache_hits : -( data. number_of_cache_hits as i64 ) ,
164+ invocation_count : -( data. invocation_count as i64 ) ,
165+ blocked_time : invert ( data. blocked_time ) ,
166+ incremental_load_time : invert ( data. incremental_load_time ) ,
167+ incremental_hashing_time : invert ( data. incremental_hashing_time ) ,
168+ }
169+ }
170+
171+ pub fn query_data_as_diff ( data : & QueryData ) -> QueryDataDiff {
172+ QueryDataDiff {
173+ label : data. label . clone ( ) ,
174+ time : data. time . into ( ) ,
175+ time_change : std:: f64:: INFINITY ,
176+ self_time : data. self_time . into ( ) ,
177+ self_time_change : std:: f64:: INFINITY ,
178+ number_of_cache_misses : data. number_of_cache_misses as i64 ,
179+ number_of_cache_hits : data. number_of_cache_hits as i64 ,
180+ invocation_count : data. invocation_count as i64 ,
181+ blocked_time : data. blocked_time . into ( ) ,
182+ incremental_load_time : data. incremental_load_time . into ( ) ,
183+ incremental_hashing_time : data. incremental_hashing_time . into ( ) ,
184+ }
185+ }
186+ }
187+
188+ #[ derive( Serialize , Deserialize , Debug ) ]
189+ pub struct ArtifactSizeDiff {
190+ pub label : String ,
191+ pub size_change : i64 ,
192+ }
193+
194+ impl ArtifactSizeDiff {
195+ pub fn invert_artifact_size ( size : & ArtifactSize ) -> ArtifactSizeDiff {
196+ ArtifactSizeDiff {
197+ label : size. label . clone ( ) ,
198+ size_change : -( size. value as i64 ) ,
199+ }
200+ }
201+
202+ pub fn artifact_size_as_diff ( size : & ArtifactSize ) -> ArtifactSizeDiff {
203+ ArtifactSizeDiff {
204+ label : size. label . clone ( ) ,
205+ size_change : size. value as i64 ,
206+ }
207+ }
208+ fn sub ( lhs : ArtifactSize , rhs : ArtifactSize ) -> ArtifactSizeDiff {
209+ ArtifactSizeDiff {
210+ label : lhs. label ,
211+ size_change : lhs. value as i64 - rhs. value as i64 ,
212+ }
213+ }
214+ }
215+
216+ #[ derive( Serialize , Deserialize , Clone , Copy , Eq , PartialEq ) ]
217+ pub struct SignedDuration {
218+ pub duration : Duration ,
219+ pub is_positive : bool ,
220+ }
221+
222+ impl SignedDuration {
223+ pub fn as_nanos ( & self ) -> i128 {
224+ let sign = if self . is_positive { 1 } else { -1 } ;
225+
226+ sign * ( self . duration . as_nanos ( ) as i128 )
227+ }
228+
229+ pub fn from_nanos ( nanos : i128 ) -> SignedDuration {
230+ let is_positive = nanos >= 0 ;
231+
232+ SignedDuration {
233+ duration : Duration :: from_nanos ( nanos. abs ( ) as u64 ) ,
234+ is_positive,
235+ }
236+ }
237+ }
238+
239+ impl From < Duration > for SignedDuration {
240+ fn from ( d : Duration ) -> SignedDuration {
241+ SignedDuration {
242+ duration : d,
243+ is_positive : true ,
244+ }
245+ }
246+ }
247+
248+ impl Ord for SignedDuration {
249+ fn cmp ( & self , other : & SignedDuration ) -> Ordering {
250+ self . as_nanos ( ) . cmp ( & other. as_nanos ( ) )
251+ }
252+ }
253+
254+ impl PartialOrd for SignedDuration {
255+ fn partial_cmp ( & self , other : & SignedDuration ) -> Option < Ordering > {
256+ Some ( self . cmp ( other) )
257+ }
258+ }
259+
260+ impl std:: ops:: Sub for SignedDuration {
261+ type Output = SignedDuration ;
262+
263+ fn sub ( self , rhs : SignedDuration ) -> SignedDuration {
264+ SignedDuration :: from_nanos ( self . as_nanos ( ) - rhs. as_nanos ( ) )
265+ }
266+ }
267+
268+ impl fmt:: Debug for SignedDuration {
269+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
270+ if self . is_positive {
271+ write ! ( f, "+" ) ?;
272+ } else {
273+ write ! ( f, "-" ) ?;
274+ }
275+
276+ write ! ( f, "{:?}" , self . duration)
277+ }
278+ }
279+
280+ #[ cfg( test) ]
281+ mod test {
282+ use super :: SignedDuration ;
283+ use std:: time:: Duration ;
284+
285+ #[ test]
286+ fn op_subtract ( ) {
287+ let zero_d = Duration :: from_nanos ( 0 ) ;
288+ let one_d = Duration :: from_nanos ( 1 ) ;
289+ let two_d = Duration :: from_nanos ( 2 ) ;
290+
291+ let zero_sd = SignedDuration :: from ( zero_d) ;
292+ let one_sd = SignedDuration :: from ( one_d) ;
293+ let neg_one_sd = SignedDuration {
294+ duration : one_d,
295+ is_positive : false ,
296+ } ;
297+ let two_sd = SignedDuration :: from ( two_d) ;
298+ let neg_two_sd = SignedDuration {
299+ duration : two_d,
300+ is_positive : false ,
301+ } ;
302+
303+ assert_eq ! ( zero_d, zero_sd. duration) ;
304+ assert_eq ! ( true , zero_sd. is_positive) ;
305+
306+ assert_eq ! ( zero_sd, zero_sd - zero_sd) ;
307+
308+ assert_eq ! ( one_d, one_sd. duration) ;
309+ assert_eq ! ( true , one_sd. is_positive) ;
310+
311+ assert_eq ! ( one_sd, one_sd - zero_sd) ;
312+
313+ assert_eq ! ( one_d, neg_one_sd. duration) ;
314+ assert_eq ! ( false , neg_one_sd. is_positive) ;
315+
316+ assert_eq ! ( neg_one_sd, neg_one_sd - zero_sd) ;
317+
318+ assert_eq ! ( zero_sd, one_sd - one_sd) ;
319+
320+ assert_eq ! ( one_sd, two_sd - one_sd) ;
321+
322+ assert_eq ! ( neg_one_sd, one_sd - two_sd) ;
323+
324+ assert_eq ! ( neg_two_sd, neg_one_sd - one_sd) ;
325+
326+ assert_eq ! ( zero_sd, neg_one_sd - neg_one_sd) ;
327+ }
328+ }
0 commit comments