@@ -64,7 +64,9 @@ impl ToStr for TestName {
64
64
pub enum TestFn {
65
65
StaticTestFn ( extern fn ( ) ) ,
66
66
StaticBenchFn ( extern fn ( & mut BenchHarness ) ) ,
67
+ StaticMetricFn ( ~fn ( & mut MetricMap ) ) ,
67
68
DynTestFn ( ~fn ( ) ) ,
69
+ DynMetricFn ( ~fn ( & mut MetricMap ) ) ,
68
70
DynBenchFn ( ~fn ( & mut BenchHarness ) )
69
71
}
70
72
@@ -95,6 +97,7 @@ pub struct Metric {
95
97
noise : f64
96
98
}
97
99
100
+ #[ deriving( Eq ) ]
98
101
pub struct MetricMap ( TreeMap < ~str , Metric > ) ;
99
102
100
103
/// Analysis of a single change in metric
@@ -218,7 +221,13 @@ pub struct BenchSamples {
218
221
}
219
222
220
223
#[ deriving( Eq ) ]
221
- pub enum TestResult { TrOk , TrFailed , TrIgnored , TrBench ( BenchSamples ) }
224
+ pub enum TestResult {
225
+ TrOk ,
226
+ TrFailed ,
227
+ TrIgnored ,
228
+ TrMetrics ( MetricMap ) ,
229
+ TrBench ( BenchSamples )
230
+ }
222
231
223
232
struct ConsoleTestState {
224
233
out : @io:: Writer ,
@@ -229,7 +238,7 @@ struct ConsoleTestState {
229
238
passed : uint ,
230
239
failed : uint ,
231
240
ignored : uint ,
232
- benchmarked : uint ,
241
+ measured : uint ,
233
242
metrics : MetricMap ,
234
243
failures : ~[ TestDesc ]
235
244
}
@@ -261,7 +270,7 @@ impl ConsoleTestState {
261
270
passed : 0 u,
262
271
failed : 0 u,
263
272
ignored : 0 u,
264
- benchmarked : 0 u,
273
+ measured : 0 u,
265
274
metrics : MetricMap :: new ( ) ,
266
275
failures : ~[ ]
267
276
}
@@ -279,11 +288,14 @@ impl ConsoleTestState {
279
288
self . write_pretty ( "ignored" , term:: color:: YELLOW ) ;
280
289
}
281
290
291
+ pub fn write_metric ( & self ) {
292
+ self . write_pretty ( "metric" , term:: color:: CYAN ) ;
293
+ }
294
+
282
295
pub fn write_bench ( & self ) {
283
296
self . write_pretty ( "bench" , term:: color:: CYAN ) ;
284
297
}
285
298
286
-
287
299
pub fn write_added ( & self ) {
288
300
self . write_pretty ( "added" , term:: color:: GREEN ) ;
289
301
}
@@ -332,6 +344,10 @@ impl ConsoleTestState {
332
344
TrOk => self . write_ok ( ) ,
333
345
TrFailed => self . write_failed ( ) ,
334
346
TrIgnored => self . write_ignored ( ) ,
347
+ TrMetrics ( ref mm) => {
348
+ self . write_metric ( ) ;
349
+ self . out . write_str ( ": " + fmt_metrics ( mm) ) ;
350
+ }
335
351
TrBench ( ref bs) => {
336
352
self . write_bench ( ) ;
337
353
self . out . write_str ( ": " + fmt_bench_samples ( bs) )
@@ -349,6 +365,7 @@ impl ConsoleTestState {
349
365
TrOk => ~"ok",
350
366
TrFailed => ~" failed",
351
367
TrIgnored => ~" ignored",
368
+ TrMetrics(ref mm) => fmt_metrics(mm),
352
369
TrBench(ref bs) => fmt_bench_samples(bs)
353
370
}, test.name.to_str()));
354
371
}
@@ -416,7 +433,7 @@ impl ConsoleTestState {
416
433
pub fn write_run_finish(&self,
417
434
ratchet_metrics: &Option<Path>,
418
435
ratchet_pct: Option<f64>) -> bool {
419
- assert!(self.passed + self.failed + self.ignored + self.benchmarked == self.total);
436
+ assert!(self.passed + self.failed + self.ignored + self.measured == self.total);
420
437
421
438
let ratchet_success = match *ratchet_metrics {
422
439
None => true,
@@ -448,12 +465,23 @@ impl ConsoleTestState {
448
465
} else {
449
466
self . write_failed ( ) ;
450
467
}
451
- self . out . write_str ( fmt ! ( ". %u passed; %u failed; %u ignored, %u benchmarked \n \n " ,
452
- self . passed, self . failed, self . ignored, self . benchmarked ) ) ;
468
+ self . out . write_str ( fmt ! ( ". %u passed; %u failed; %u ignored; %u measured \n \n " ,
469
+ self . passed, self . failed, self . ignored, self . measured ) ) ;
453
470
return success;
454
471
}
455
472
}
456
473
474
+ pub fn fmt_metrics ( mm : & MetricMap ) -> ~str {
475
+ use std:: iterator:: IteratorUtil ;
476
+ let v : ~[ ~str ] = mm. iter ( )
477
+ . transform ( |( k, v) | fmt ! ( "%s: %f (+/- %f)" ,
478
+ * k,
479
+ v. value as float,
480
+ v. noise as float) )
481
+ . collect ( ) ;
482
+ v. connect ( ", " )
483
+ }
484
+
457
485
pub fn fmt_bench_samples ( bs : & BenchSamples ) -> ~str {
458
486
if bs. mb_s != 0 {
459
487
fmt ! ( "%u ns/iter (+/- %u) = %u MB/s" ,
@@ -481,11 +509,19 @@ pub fn run_tests_console(opts: &TestOpts,
481
509
match result {
482
510
TrOk => st. passed += 1 ,
483
511
TrIgnored => st. ignored += 1 ,
512
+ TrMetrics ( mm) => {
513
+ let tname = test. name . to_str ( ) ;
514
+ for mm. iter( ) . advance( ) |( k, v) | {
515
+ st. metrics. insert_metric( tname + "." + * k,
516
+ v. value, v. noise) ;
517
+ }
518
+ st. measured += 1
519
+ }
484
520
TrBench ( bs) => {
485
521
st. metrics. insert_metric( test. name. to_str( ) ,
486
522
bs. ns_iter_summ. median,
487
523
bs. ns_iter_summ. max - bs. ns_iter_summ. min) ;
488
- st. benchmarked += 1
524
+ st. measured += 1
489
525
}
490
526
TrFailed => {
491
527
st. failed += 1 ;
@@ -533,7 +569,7 @@ fn should_sort_failures_before_printing_them() {
533
569
passed : 0 u,
534
570
failed : 0 u,
535
571
ignored : 0 u,
536
- benchmarked : 0 u,
572
+ measured : 0 u,
537
573
metrics : MetricMap :: new( ) ,
538
574
failures : ~[ test_b, test_a]
539
575
} ;
@@ -565,11 +601,11 @@ fn run_tests(opts: &TestOpts,
565
601
566
602
callback( TeFiltered ( filtered_descs) ) ;
567
603
568
- let ( filtered_tests, filtered_benchs ) =
604
+ let ( filtered_tests, filtered_benchs_and_metrics ) =
569
605
do filtered_tests. partition |e| {
570
606
match e. testfn {
571
607
StaticTestFn ( _) | DynTestFn ( _) => true ,
572
- StaticBenchFn ( _ ) | DynBenchFn ( _ ) => false
608
+ _ => false
573
609
}
574
610
} ;
575
611
@@ -607,7 +643,8 @@ fn run_tests(opts: &TestOpts,
607
643
}
608
644
609
645
// All benchmarks run at the end, in serial.
610
- for filtered_benchs. consume_iter( ) . advance |b| {
646
+ // (this includes metric fns)
647
+ for filtered_benchs_and_metrics. consume_iter( ) . advance |b| {
611
648
callback( TeWait ( copy b. desc) ) ;
612
649
run_test( !opts. run_benchmarks, b, ch. clone( ) ) ;
613
650
let ( test, result) = p. recv( ) ;
@@ -730,6 +767,18 @@ pub fn run_test(force_ignore: bool,
730
767
monitor_ch. send( ( desc, TrBench ( bs) ) ) ;
731
768
return ;
732
769
}
770
+ DynMetricFn ( f) => {
771
+ let mut mm = MetricMap :: new( ) ;
772
+ f( & mut mm) ;
773
+ monitor_ch. send( ( desc, TrMetrics ( mm) ) ) ;
774
+ return ;
775
+ }
776
+ StaticMetricFn ( f) => {
777
+ let mut mm = MetricMap :: new( ) ;
778
+ f( & mut mm) ;
779
+ monitor_ch. send( ( desc, TrMetrics ( mm) ) ) ;
780
+ return ;
781
+ }
733
782
DynTestFn ( f) => run_test_inner( desc, monitor_ch, f) ,
734
783
StaticTestFn ( f) => run_test_inner( desc, monitor_ch, || f( ) )
735
784
}
@@ -757,12 +806,12 @@ impl ToJson for Metric {
757
806
758
807
impl MetricMap {
759
808
760
- fn new( ) -> MetricMap {
809
+ pub fn new( ) -> MetricMap {
761
810
MetricMap ( TreeMap : : new( ) )
762
811
}
763
812
764
813
/// Load MetricDiff from a file.
765
- fn load( p: & Path ) -> MetricMap {
814
+ pub fn load( p: & Path ) -> MetricMap {
766
815
assert!( os:: path_exists( p) ) ;
767
816
let f = io:: file_reader( p) . get( ) ;
768
817
let mut decoder = json:: Decoder ( json:: from_reader( f) . get( ) ) ;
@@ -793,7 +842,7 @@ impl MetricMap {
793
842
None => f64:: max( vold. noise. abs( ) , v. noise. abs( ) ) ,
794
843
Some ( pct) => vold. value * pct / 100 . 0
795
844
} ;
796
- if delta. abs( ) < noise {
845
+ if delta. abs( ) <= noise {
797
846
LikelyNoise
798
847
} else {
799
848
let pct = delta. abs( ) / vold. value * 100.0 ;
@@ -1245,10 +1294,14 @@ mod tests {
1245
1294
assert_eq!(*(diff1.find(&~" in-both-noise").get()), LikelyNoise);
1246
1295
assert_eq!(*(diff1.find(&~" in-first-noise").get()), MetricRemoved);
1247
1296
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));
1297
+ assert_eq!(*(diff1.find(&~" in-both-want-downwards-but-regressed").get()),
1298
+ Regression(100.0));
1299
+ assert_eq!(*(diff1.find(&~" in-both-want-downwards-and-improved").get()),
1300
+ Improvement(50.0));
1301
+ assert_eq!(*(diff1.find(&~" in-both-want-upwards-but-regressed").get()),
1302
+ Regression(50.0));
1303
+ assert_eq!(*(diff1.find(&~" in-both-want-upwards-and-improved").get()),
1304
+ Improvement(100.0));
1252
1305
assert_eq!(diff1.len(), 7);
1253
1306
1254
1307
let diff2 = m2.compare_to_old(&m1, Some(200.0));
0 commit comments