36 / 36 lines covered (100.0%)
1unit module BDD::Behave::Benchmark;23our class BenchmarkResult {4 has Str $.label;5 has Int $.position;6 has Int $.iterations is required;7 has @.timings is required;8 has Real $.min;9 has Real $.max;10 has Real $.mean;11 has Real $.median;12 has Real $.total;1314 submethod TWEAK {15 return unless @!timings.elems;16 my @sorted = @!timings.sort;17 $!min = @sorted[0];18 $!max = @sorted[*-1];19 $!total = [+] @!timings;20 $!mean = $!total / @!timings.elems;21 my $n = @sorted.elems;22 $!median = $n %% 223 ?? (@sorted[$n div 2 - 1] + @sorted[$n div 2]) / 224 !! @sorted[$n div 2];25 }2627 method key(--> Str) {28 $!label.defined ?? "label:$!label" !! "pos:" ~ ($!position // 0);29 }30}3132sub attach-to-current-example(BenchmarkResult $result --> Nil) {33 my $current;34 try { $current = $*BEHAVE-CURRENT-EXAMPLE if $*BEHAVE-CURRENT-EXAMPLE.defined }35 return unless $current.defined;36 $current.benchmarks.push: $result;37}3839sub next-position(--> Int) {40 my $pos = 0;41 try {42 if $*BEHAVE-BENCHMARK-COUNTER.defined {43 $pos = $*BEHAVE-BENCHMARK-COUNTER;44 $*BEHAVE-BENCHMARK-COUNTER++;45 }46 }47 $pos;48}4950sub run-iterations(&block, Int $iterations, Int $warmup, $label --> BenchmarkResult) {51 die "benchmark iterations must be a positive integer (got: $iterations)"52 unless $iterations > 0;53 die "benchmark warmup must be 0 or a positive integer (got: $warmup)"54 if $warmup < 0;5556 my $position = next-position();5758 for ^$warmup { block() }5960 my @timings;61 for ^$iterations {62 my $start = now;63 block();64 my $finish = now;65 @timings.push: ($finish - $start).Real;66 }6768 my $result = BenchmarkResult.new(69 :label($label // Str),70 :$position,71 :$iterations,72 :@timings,73 );74 attach-to-current-example($result);75 $result;76}7778our proto sub benchmark(|) is export {*}7980our multi sub benchmark(&block, Int :$iterations = 100, Int :$warmup = 0, Str :$label) is export {81 run-iterations(&block, $iterations, $warmup, $label);82}8384our multi sub benchmark(Str:D $label, &block, Int :$iterations = 100, Int :$warmup = 0) is export {85 run-iterations(&block, $iterations, $warmup, $label);86}