#!/usr/bin/env raku
# Find out for what problems Hyper and Race performs fast compared to single thread execution
# Note: for real world benchmarking you might want to use some library from
# https://raku.land/?q=Benchmark
my @problems = 2**8, 2**16;
my @batch-sizes = 2**8, 2**16;
my @degrees = 2, 4;
#my @problems = 1, 2, 4 ... 2^15;
#my @batch-sizes = 64, 128, 256 ... 4096;
#my @degrees = 2, 4, 8 ... 32;
my $lazy-list-of-all-positive-integers = ^∞;
my $input = $lazy-list-of-all-positive-integers;
my @colnames = 'problem', 'batch', 'degree', 'single', 'hyper', 'race', 'speed-up hyper [%]', 'speed-up race [%]';
say join "\t", @colnames;
for @problems -> $problem {
my $start = now;
my $result-single = $input.grep(*.is-prime)[$problem];
my $time-single = now - $start;
for @batch-sizes X @degrees -> ($batch, $degree) {
$start = now;
my $result-hyper = $input.hyper(:$batch, :$degree).grep(*.is-prime)[$problem];
# use the result - just to be sure it gets calculated (see lazyness)
sink "wrong result in race" if $result-single != $result-hyper;
my $time-hyper = now - $start;
$start = now;
my $result-race = $input.race(:$batch, :$degree).grep(*.is-prime)[$problem];
# race works according to specification as order is not preserved
# so we can not use it to get a specific prime by position
sink "wrong result in race" if $result-single != $result-race;
my $time-race = now - $start;
#$start = now;
# https://docs.raku.org/language/operators#methodop_%C2%BB._/_methodop_%3E%3E.
#my $result-arrow = $input».grep(*.is-prime)[$problem];
#sink "wrong result in »" if $result-single != $result-arrow;
#my $time-arrow = now - $start;
my @output = $problem, $batch, $degree, $time-single, $time-hyper, $time-race, speedup($time-single, $time-hyper), speedup($time-single, $time-race);
say join "\t", @output
}
}
sub speedup($t1, $t2) {
round(($t1 - $t2 ) / $t1 * 100);
}