@@ -98,6 +98,7 @@ pub struct Metric {
98
98
pub struct MetricMap ( TreeMap < ~str , Metric > ) ;
99
99
100
100
/// Analysis of a single change in metric
101
+ #[ deriving( Eq ) ]
101
102
pub enum MetricChange {
102
103
LikelyNoise ,
103
104
MetricAdded ,
@@ -774,8 +775,13 @@ impl MetricMap {
774
775
json:: to_pretty_writer( f, & self . to_json( ) ) ;
775
776
}
776
777
777
- /// Compare against another MetricMap
778
- pub fn compare_to_old( & self , old: MetricMap ,
778
+ /// Compare against another MetricMap. Optionally compare all
779
+ /// measurements in the maps using the provided `noise_pct` as a
780
+ /// percentage of each value to consider noise. If `None`, each
781
+ /// measurement's noise threshold is independently chosen as the
782
+ /// maximum of that measurement's recorded noise quantity in either
783
+ /// map.
784
+ pub fn compare_to_old( & self , old: & MetricMap ,
779
785
noise_pct: Option < f64 > ) -> MetricDiff {
780
786
let mut diff : MetricDiff = TreeMap :: new( ) ;
781
787
for old. iter( ) . advance |( k, vold) | {
@@ -790,7 +796,7 @@ impl MetricMap {
790
796
if delta. abs( ) < noise {
791
797
LikelyNoise
792
798
} else {
793
- let pct = delta. abs( ) / v . value * 100.0 ;
799
+ let pct = delta. abs( ) / vold . value * 100.0 ;
794
800
if vold. noise < 0.0 {
795
801
// When 'noise' is negative, it means we want
796
802
// to see deltas that go up over time, and can
@@ -857,7 +863,7 @@ impl MetricMap {
857
863
MetricMap :: new ( )
858
864
} ;
859
865
860
- let diff : MetricDiff = self . compare_to_old ( old, pct) ;
866
+ let diff : MetricDiff = self . compare_to_old ( & old, pct) ;
861
867
let ok = do diff. iter ( ) . all ( ) |( _, v) | {
862
868
match * v {
863
869
Regression ( _) => false ,
@@ -1006,13 +1012,16 @@ pub mod bench {
1006
1012
mod tests {
1007
1013
use test:: { TrFailed , TrIgnored , TrOk , filter_tests, parse_opts,
1008
1014
TestDesc , TestDescAndFn ,
1015
+ Metric , MetricMap , MetricAdded , MetricRemoved ,
1016
+ Improvement , Regression , LikelyNoise ,
1009
1017
StaticTestName , DynTestName , DynTestFn } ;
1010
1018
use test:: { TestOpts , run_test} ;
1011
1019
1012
1020
use std:: either;
1013
1021
use std:: comm:: { stream, SharedChan } ;
1014
- use std:: option;
1015
1022
use std:: vec;
1023
+ use tempfile;
1024
+ use std:: os;
1016
1025
1017
1026
#[ test]
1018
1027
pub fn do_not_run_ignored_tests ( ) {
@@ -1208,4 +1217,95 @@ mod tests {
1208
1217
}
1209
1218
}
1210
1219
}
1220
+
1221
+ #[test]
1222
+ pub fn test_metricmap_compare() {
1223
+ let mut m1 = MetricMap::new();
1224
+ let mut m2 = MetricMap::new();
1225
+ m1.insert_metric(" in-both-noise", 1000.0, 200.0);
1226
+ m2.insert_metric(" in-both-noise", 1100.0, 200.0);
1227
+
1228
+ m1.insert_metric(" in-first-noise", 1000.0, 2.0);
1229
+ m2.insert_metric(" in-second-noise", 1000.0, 2.0);
1230
+
1231
+ m1.insert_metric(" in-both-want-downwards-but-regressed", 1000.0, 10.0);
1232
+ m2.insert_metric(" in-both-want-downwards-but-regressed", 2000.0, 10.0);
1233
+
1234
+ m1.insert_metric(" in-both-want-downwards-and-improved", 2000.0, 10.0);
1235
+ m2.insert_metric(" in-both-want-downwards-and-improved", 1000.0, 10.0);
1236
+
1237
+ m1.insert_metric(" in-both-want-upwards-but-regressed", 2000.0, -10.0);
1238
+ m2.insert_metric(" in-both-want-upwards-but-regressed", 1000.0, -10.0);
1239
+
1240
+ m1.insert_metric(" in-both-want-upwards-and-improved", 1000.0, -10.0);
1241
+ m2.insert_metric(" in-both-want-upwards-and-improved", 2000.0, -10.0);
1242
+
1243
+ let diff1 = m2.compare_to_old(&m1, None);
1244
+
1245
+ assert_eq!(*(diff1.find(&~" in-both-noise").get()), LikelyNoise);
1246
+ assert_eq!(*(diff1.find(&~" in-first-noise").get()), MetricRemoved);
1247
+ assert_eq!(*(diff1.find(&~" in-second-noise").get()), MetricAdded);
1248
+ assert_eq!(*(diff1.find(&~" in-both-want-downwards-but-regressed").get()), Regression(100.0));
1249
+ assert_eq!(*(diff1.find(&~" in-both-want-downwards-and-improved").get()), Improvement(50.0));
1250
+ assert_eq!(*(diff1.find(&~" in-both-want-upwards-but-regressed").get()), Regression(50.0));
1251
+ assert_eq!(*(diff1.find(&~" in-both-want-upwards-and-improved").get()), Improvement(100.0));
1252
+ assert_eq!(diff1.len(), 7);
1253
+
1254
+ let diff2 = m2.compare_to_old(&m1, Some(200.0));
1255
+
1256
+ assert_eq!(*(diff2.find(&~" in-both-noise").get()), LikelyNoise);
1257
+ assert_eq!(*(diff2.find(&~" in-first-noise").get()), MetricRemoved);
1258
+ assert_eq!(*(diff2.find(&~" in-second-noise").get()), MetricAdded);
1259
+ assert_eq!(*(diff2.find(&~" in-both-want-downwards-but-regressed").get()), LikelyNoise);
1260
+ assert_eq!(*(diff2.find(&~" in-both-want-downwards-and-improved").get()), LikelyNoise);
1261
+ assert_eq!(*(diff2.find(&~" in-both-want-upwards-but-regressed").get()), LikelyNoise);
1262
+ assert_eq!(*(diff2.find(&~" in-both-want-upwards-and-improved").get()), LikelyNoise);
1263
+ assert_eq!(diff2.len(), 7);
1264
+ }
1265
+
1266
+ pub fn ratchet_test() {
1267
+
1268
+ let dpth = tempfile::mkdtemp(&os::tmpdir(),
1269
+ " test-ratchet").expect(" missing test for ratchet");
1270
+ let pth = dpth.push(" ratchet. json");
1271
+
1272
+ let mut m1 = MetricMap::new();
1273
+ m1.insert_metric(" runtime", 1000.0, 2.0);
1274
+ m1.insert_metric(" throughput", 50.0, 2.0);
1275
+
1276
+ let mut m2 = MetricMap::new();
1277
+ m2.insert_metric(" runtime", 1100.0, 2.0);
1278
+ m2.insert_metric(" throughput", 50.0, 2.0);
1279
+
1280
+ m1.save(&pth);
1281
+
1282
+ // Ask for a ratchet that should fail to advance.
1283
+ let (diff1, ok1) = m2.ratchet(&pth, None);
1284
+ assert_eq!(ok1, false);
1285
+ assert_eq!(diff1.len(), 2);
1286
+ assert_eq!(*(diff1.find(&~" runtime").get()), Regression(10.0));
1287
+ assert_eq!(*(diff1.find(&~" throughput").get()), LikelyNoise);
1288
+
1289
+ // Check that it was not rewritten.
1290
+ let m3 = MetricMap::load(&pth);
1291
+ assert_eq!(m3.len(), 2);
1292
+ assert_eq!(*(m3.find(&~" runtime").get()), Metric { value: 1000.0, noise: 2.0 });
1293
+ assert_eq!(*(m3.find(&~" throughput").get()), Metric { value: 50.0, noise: 2.0 });
1294
+
1295
+ // Ask for a ratchet with an explicit noise-percentage override,
1296
+ // that should advance.
1297
+ let (diff2, ok2) = m2.ratchet(&pth, Some(10.0));
1298
+ assert_eq!(ok2, true);
1299
+ assert_eq!(diff2.len(), 2);
1300
+ assert_eq!(*(diff2.find(&~" runtime").get()), LikelyNoise);
1301
+ assert_eq!(*(diff2.find(&~" throughput").get()), LikelyNoise);
1302
+
1303
+ // Check that it was rewritten.
1304
+ let m4 = MetricMap::load(&pth);
1305
+ assert_eq!(m4.len(), 2);
1306
+ assert_eq!(*(m4.find(&~" runtime").get()), Metric { value: 1100.0, noise: 2.0 });
1307
+ assert_eq!(*(m4.find(&~" throughput") . get( ) ) , Metric { value: 50.0 , noise: 2.0 } ) ;
1308
+
1309
+ os:: remove_dir_recursive ( & dpth) ;
1310
+ }
1211
1311
}
0 commit comments