@@ -19,15 +19,21 @@ use core::prelude::*;
1919
2020use getopts;
2121use sort;
22+ use stats:: Stats ;
2223use term;
24+ use time:: precise_time_ns;
2325
2426use core:: comm:: { stream, SharedChan } ;
2527use core:: either;
2628use core:: io;
29+ use core:: num;
2730use core:: option;
31+ use core:: rand:: RngUtil ;
32+ use core:: rand;
2833use core:: result;
2934use core:: task;
3035use core:: to_str:: ToStr ;
36+ use core:: u64;
3137use core:: uint;
3238use core:: vec;
3339
@@ -609,152 +615,146 @@ fn calc_result(desc: &TestDesc, task_succeeded: bool) -> TestResult {
609615 }
610616}
611617
612- pub mod bench {
613- use core::prelude::*;
614-
615- use core::num;
616- use core::rand::RngUtil;
617- use core::rand;
618- use core::u64;
619- use core::vec;
620- use stats::Stats;
621- use test::{BenchHarness, BenchSamples};
622- use time::precise_time_ns;
623-
624- impl BenchHarness {
625- /// Callback for benchmark functions to run in their body.
626- pub fn iter(&mut self, inner:&fn()) {
627- self.ns_start = precise_time_ns();
628- let k = self.iterations;
629- for u64::range(0, k) |_| {
630- inner();
631- }
632- self.ns_end = precise_time_ns();
618+ impl BenchHarness {
619+ /// Callback for benchmark functions to run in their body.
620+ pub fn iter(&mut self, inner:&fn()) {
621+ self.ns_start = precise_time_ns();
622+ let k = self.iterations;
623+ for u64::range(0, k) |_| {
624+ inner();
633625 }
626+ self.ns_end = precise_time_ns();
627+ }
634628
635- pub fn ns_elapsed(&mut self) -> u64 {
636- if self.ns_start == 0 || self.ns_end == 0 {
637- 0
638- } else {
639- self.ns_end - self.ns_start
640- }
629+ pub fn ns_elapsed(&mut self) -> u64 {
630+ if self.ns_start == 0 || self.ns_end == 0 {
631+ 0
632+ } else {
633+ self.ns_end - self.ns_start
641634 }
635+ }
642636
643- pub fn ns_per_iter(&mut self) -> u64 {
644- if self.iterations == 0 {
645- 0
646- } else {
647- self.ns_elapsed() / self.iterations
648- }
637+ pub fn ns_per_iter(&mut self) -> u64 {
638+ if self.iterations == 0 {
639+ 0
640+ } else {
641+ self.ns_elapsed() / self.iterations
649642 }
643+ }
650644
651- pub fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) {
652- self.iterations = n;
653- debug!(" running benchmark for %u iterations",
654- n as uint);
655- f(self);
656- }
645+ pub fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) {
646+ self.iterations = n;
647+ debug!(" running benchmark for %u iterations",
648+ n as uint);
649+ f(self);
650+ }
657651
658- // This is the Go benchmark algorithm. It produces a single
659- // datapoint and always tries to run for 1s.
660- pub fn go_bench(&mut self, f: &fn(&mut BenchHarness)) {
661-
662- // Rounds a number down to the nearest power of 10.
663- fn round_down_10(n: u64) -> u64 {
664- let mut n = n;
665- let mut res = 1;
666- while n > 10 {
667- n = n / 10;
668- res *= 10;
669- }
670- res
671- }
652+ // This is the Go benchmark algorithm. It produces a single
653+ // datapoint and always tries to run for 1s.
654+ pub fn go_bench(&mut self, f: &fn(&mut BenchHarness)) {
672655
673- // Rounds x up to a number of the form [1eX, 2eX, 5eX].
674- fn round_up(n: u64) -> u64 {
675- let base = round_down_10(n);
676- if n < (2 * base) {
677- 2 * base
678- } else if n < (5 * base) {
679- 5 * base
680- } else {
681- 10 * base
682- }
656+ // Rounds a number down to the nearest power of 10.
657+ fn round_down_10(n: u64) -> u64 {
658+ let mut n = n;
659+ let mut res = 1;
660+ while n > 10 {
661+ n = n / 10;
662+ res *= 10;
683663 }
664+ res
665+ }
684666
685- // Initial bench run to get ballpark figure.
686- let mut n = 1_u64;
687- self.bench_n(n, f);
688-
689- while n < 1_000_000_000 &&
690- self.ns_elapsed() < 1_000_000_000 {
691- let last = n;
692-
693- // Try to estimate iter count for 1s falling back to 1bn
694- // iterations if first run took < 1ns.
695- if self.ns_per_iter() == 0 {
696- n = 1_000_000_000;
697- } else {
698- n = 1_000_000_000 / self.ns_per_iter();
699- }
700-
701- n = u64::max(u64::min(n+n/2, 100*last), last+1);
702- n = round_up(n);
703- self.bench_n(n, f);
667+ // Rounds x up to a number of the form [1eX, 2eX, 5eX].
668+ fn round_up(n: u64) -> u64 {
669+ let base = round_down_10(n);
670+ if n < (2 * base) {
671+ 2 * base
672+ } else if n < (5 * base) {
673+ 5 * base
674+ } else {
675+ 10 * base
704676 }
705677 }
706678
707- // This is a more statistics-driven benchmark algorithm.
708- // It stops as quickly as 50ms, so long as the statistical
709- // properties are satisfactory. If those properties are
710- // not met, it may run as long as the Go algorithm.
711- pub fn auto_bench(&mut self, f: &fn(&mut BenchHarness)) -> ~[f64] {
712-
713- let mut rng = rand::rng();
714- let mut magnitude = 10;
715- let mut prev_madp = 0.0;
679+ // Initial bench run to get ballpark figure.
680+ let mut n = 1_u64;
681+ self.bench_n(n, f);
716682
717- loop {
718- let n_samples = rng.gen_uint_range(50, 60);
719- let n_iter = rng.gen_uint_range(magnitude,
720- magnitude * 2);
683+ while n < 1_000_000_000 &&
684+ self.ns_elapsed() < 1_000_000_000 {
685+ let last = n;
721686
722- let samples = do vec::from_fn(n_samples) |_| {
723- self.bench_n(n_iter as u64, f);
724- self.ns_per_iter() as f64
725- };
687+ // Try to estimate iter count for 1s falling back to 1bn
688+ // iterations if first run took < 1ns.
689+ if self.ns_per_iter() == 0 {
690+ n = 1_000_000_000;
691+ } else {
692+ n = 1_000_000_000 / self.ns_per_iter();
693+ }
726694
727- // Eliminate outliers
728- let med = samples.median();
729- let mad = samples.median_abs_dev();
730- let samples = do vec::filter(samples) |f| {
731- num::abs(*f - med) <= 3.0 * mad
732- };
695+ n = u64::max(u64::min(n+n/2, 100*last), last+1);
696+ n = round_up(n);
697+ self.bench_n(n, f);
698+ }
699+ }
733700
734- debug!(" %u samples, median %f, MAD =%f, %u survived filter",
735- n_samples, med as float, mad as float,
736- samples.len());
737-
738- if samples.len() != 0 {
739- // If we have _any_ cluster of signal...
740- let curr_madp = samples.median_abs_dev_pct();
741- if self.ns_elapsed() > 1_000_000 &&
742- (curr_madp < 1.0 ||
743- num::abs(curr_madp - prev_madp) < 0.1) {
744- return samples;
745- }
746- prev_madp = curr_madp;
747-
748- if n_iter > 20_000_000 ||
749- self.ns_elapsed() > 20_000_000 {
750- return samples;
751- }
701+ // This is a more statistics-driven benchmark algorithm.
702+ // It stops as quickly as 50ms, so long as the statistical
703+ // properties are satisfactory. If those properties are
704+ // not met, it may run as long as the Go algorithm.
705+ pub fn auto_bench(&mut self, f: &fn(&mut BenchHarness)) -> ~[f64] {
706+
707+ let mut rng = rand::rng();
708+ let mut magnitude = 10;
709+ let mut prev_madp = 0.0;
710+
711+ loop {
712+ let n_samples = rng.gen_uint_range(50, 60);
713+ let n_iter = rng.gen_uint_range(magnitude,
714+ magnitude * 2);
715+
716+ let samples = do vec::from_fn(n_samples) |_| {
717+ self.bench_n(n_iter as u64, f);
718+ self.ns_per_iter() as f64
719+ };
720+
721+ // Eliminate outliers
722+ let med = samples.median();
723+ let mad = samples.median_abs_dev();
724+ let samples = do vec::filter(samples) |f| {
725+ num::abs(*f - med) <= 3.0 * mad
726+ };
727+
728+ debug!(" %u samples, median %f, MAD =%f, %u survived filter",
729+ n_samples, med as float, mad as float,
730+ samples.len());
731+
732+ if samples.len() != 0 {
733+ // If we have _any_ cluster of signal...
734+ let curr_madp = samples.median_abs_dev_pct();
735+ if self.ns_elapsed() > 1_000_000 &&
736+ (curr_madp < 1.0 ||
737+ num::abs(curr_madp - prev_madp) < 0.1) {
738+ return samples;
752739 }
740+ prev_madp = curr_madp;
753741
754- magnitude *= 2;
742+ if n_iter > 20_000_000 ||
743+ self.ns_elapsed() > 20_000_000 {
744+ return samples;
745+ }
755746 }
747+
748+ magnitude *= 2;
756749 }
757750 }
751+ }
752+
753+ pub mod bench {
754+ use core::prelude::*;
755+
756+ use core::vec;
757+ use test::{BenchHarness, BenchSamples};
758758
759759 pub fn benchmark(f: &fn(&mut BenchHarness)) -> BenchSamples {
760760
0 commit comments