I think your benchmark is still flawed because you're applying a destructive operation multiple times without re-initializing the test data in between.
You're correct! (Strange how we all missed that.)
To correct for my error, I've re-visited the benchmark and corrected for that deficiency. (And hopefully not missed or introduced any other errors!)
I've tried to make this produce output as close to benchmarks as I can without getting anal about it:
#! perl -slw
use strict;
use Time::HiRes qw[ time ];
use Data::Dump qw[ pp ]; $Data::Dump::WIDTH = 1000;
our $N //= 1e3;
our $I //= 10;
my @tests = qw[ forSplice grep offsetCopy buildNew editInplace ];
my %times = map{ $_ => 0 } @tests;
my( $start, $end );
my @a;
for( 1 .. $I ) {
@a = 1 .. $N; $start = time; {
$a[$_] =~ /9/ and splice @a, $_, 1 for reverse 0 .. $#a;
# pp \@a;
} $times{ forSplice } += time() - $start;
@a = 1 .. $N; $start = time; {
@a = grep !/9/, @a;
# pp \@a;
} $times{ grep } += time() - $start;
@a = 1 .. $N; $start = time; {
my $o = 0;
for( 0 .. $#a ) {
$a[ $_ - $o ] = $a[ $_ ];
$a[ $_ ] =~ /9/ and ++$o;
}
$#a = $#a - $o;
# pp \@a;
} $times{ offsetCopy } += time() - $start;
@a = 1 .. $N; $start = time; {
my @b;
for( @a ) {
push @b, $_ unless /9/;
}
# pp \@b;
} $times{ buildNew } += time() - $start;
@a = 1 .. $N; $start = time; {
my $o = 0;
for( @a ) {
$a[ $o++ ] = $_ unless /9/;
}
$#a = $o - 1;
# pp \@a;
} $times{ editInplace } += time() - $start;
};
$times{ $_ } /= $I for @tests; #pp \%times;
@tests = sort{ $times{ $a } < $times{ $b } } @tests;
print join '', map sprintf( " %12s", $_ ), '', 'rate', @tests;
for my $a ( @tests ) {
printf "%12s %10g/s", $a, 1/$times{ $a };
for my $b ( @tests ) {
printf " %11.f%%", $times{ $b } / $times{ $a } * 100;
}
print '';
}
__END__
C:\test>1036622 -N=1e2
rate grep forSplice buildNew of
+fsetCopy editInplace
grep 7687.51/s 100% 61% 76%
+ 75% 58%
forSplice 12539/s 163% 100% 124%
+ 123% 95%
buildNew 10082.5/s 131% 80% 100%
+ 99% 76%
offsetCopy 10182.8/s 132% 81% 101%
+ 100% 77%
editInplace 13206.2/s 172% 105% 131%
+ 130% 100%
C:\test>1036622 -N=1e3
rate grep forSplice buildNew of
+fsetCopy editInplace
grep 760.637/s 100% 63% 78%
+ 75% 59%
forSplice 1201.22/s 158% 100% 123%
+ 119% 93%
buildNew 973.269/s 128% 81% 100%
+ 97% 75%
offsetCopy 1007.76/s 132% 84% 104%
+ 100% 78%
editInplace 1293.34/s 170% 108% 133%
+ 128% 100%
C:\test>1036622 -N=1e4
rate grep forSplice offsetCopy
+buildNew editInplace
grep 72.5919/s 100% 97% 79%
+ 73% 54%
forSplice 74.7857/s 103% 100% 81%
+ 75% 56%
offsetCopy 92.2046/s 127% 123% 100%
+ 92% 69%
buildNew 99.9543/s 138% 134% 108%
+ 100% 75%
editInplace 133.395/s 184% 178% 145%
+ 133% 100%
C:\test>1036622 -N=1e5
rate forSplice grep offsetCopy
+buildNew editInplace
forSplice 1.13766/s 100% 17% 13%
+ 13% 10%
grep 6.60517/s 581% 100% 77%
+ 73% 59%
offsetCopy 8.63102/s 759% 131% 100%
+ 95% 78%
buildNew 9.05601/s 796% 137% 105%
+ 100% 82%
editInplace 11.1044/s 976% 168% 129%
+ 123% 100%
C:\test>1036622 -N=1e6 -I=1
rate forSplice grep offsetCopy
+buildNew editInplace
forSplice 0.0106761/s 100% 1% 1%
+ 1% 1%
grep 0.798803/s 7482% 100% 86%
+ 73% 63%
offsetCopy 0.929497/s 8706% 116% 100%
+ 85% 73%
buildNew 1.09032/s 10213% 136% 117%
+ 100% 86%
editInplace 1.26927/s 11889% 159% 137%
+ 116% 100%
The upshot is that forSplice is a little faster than grep for small arrays; but editInPlace is hands down winner for arrays of any size; and one or two orders of magnitude for large arrays.
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
|