@@ -98,6 +98,7 @@ pub struct Metric {
9898pub struct MetricMap ( TreeMap < ~str , Metric > ) ;
9999
100100/// Analysis of a single change in metric
101+ #[ deriving( Eq ) ]
101102pub enum MetricChange {
102103 LikelyNoise ,
103104 MetricAdded ,
@@ -774,8 +775,13 @@ impl MetricMap {
774775 json:: to_pretty_writer( f, & self . to_json( ) ) ;
775776 }
776777
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 ,
779785 noise_pct: Option < f64 > ) -> MetricDiff {
780786 let mut diff : MetricDiff = TreeMap :: new( ) ;
781787 for old. iter( ) . advance |( k, vold) | {
@@ -790,7 +796,7 @@ impl MetricMap {
790796 if delta. abs( ) < noise {
791797 LikelyNoise
792798 } else {
793- let pct = delta. abs( ) / v . value * 100.0 ;
799+ let pct = delta. abs( ) / vold . value * 100.0 ;
794800 if vold. noise < 0.0 {
795801 // When 'noise' is negative, it means we want
796802 // to see deltas that go up over time, and can
@@ -857,7 +863,7 @@ impl MetricMap {
857863 MetricMap :: new ( )
858864 } ;
859865
860- let diff : MetricDiff = self . compare_to_old ( old, pct) ;
866+ let diff : MetricDiff = self . compare_to_old ( & old, pct) ;
861867 let ok = do diff. iter ( ) . all ( ) |( _, v) | {
862868 match * v {
863869 Regression ( _) => false ,
@@ -1006,13 +1012,16 @@ pub mod bench {
10061012mod tests {
10071013 use test:: { TrFailed , TrIgnored , TrOk , filter_tests, parse_opts,
10081014 TestDesc , TestDescAndFn ,
1015+ Metric , MetricMap , MetricAdded , MetricRemoved ,
1016+ Improvement , Regression , LikelyNoise ,
10091017 StaticTestName , DynTestName , DynTestFn } ;
10101018 use test:: { TestOpts , run_test} ;
10111019
10121020 use std:: either;
10131021 use std:: comm:: { stream, SharedChan } ;
1014- use std:: option;
10151022 use std:: vec;
1023+ use tempfile;
1024+ use std:: os;
10161025
10171026 #[ test]
10181027 pub fn do_not_run_ignored_tests ( ) {
@@ -1208,4 +1217,95 @@ mod tests {
12081217 }
12091218 }
12101219 }
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+ }
12111311}
0 commit comments