>perl -MO=Concise -e"\substr($_,1)" 2>&1 | find "substr"
5 <@> substr[t4] sKRM/2 ->6
^
|
"M"odifiable => magic created.
>perl -MO=Concise -e"$a = substr($_,1)" 2>&1 | find "substr"
5 <@> substr[t3] sK/2 ->6
^
|
Not modifiable => no magic created.
####
Pass 1: Creates a 79,999 char string & copies it into $a's buffer
Pass 2: Creates a 79,998 char string & copies it into $a's buffer
Pass 3: Creates a 79,997 char string & copies it into $a's buffer
...
Pass 79,999: Creates a 1 char string & copies it into $a's buffer
Pass 80,000: Creates a 0 char string & copies it into $a's buffer
####
$a =~ s/.//s; # Remove leading char with no copying.
substr($a, 0, 1, ''); # Remove leading char with no copying.
####
--------------------
20,000
Rate substr3 s/// substr4
substr3 1.61/s -- -93% -96%
s/// 23.1/s 1336% -- -44%
substr4 41.2/s 2460% 78% --
--------------------
40,000
Rate substr3 s/// substr4
substr3 0.884/s -- -96% -98%
s/// 23.1/s 2509% -- -45%
substr4 41.6/s 4606% 80% --
--------------------
80,000
Rate substr3 s/// substr4
substr3 0.445/s -- -98% -99% (warning: unreliable count)
s/// 23.4/s 5162% -- -42%
substr4 40.1/s 8897% 71% --
####
use strict;
use warnings;
use Benchmark qw( cmpthese );
my $OUTER = $ARGV[0] || -5;
my %tests = (
'substr3' => '$a = substr($a, 1)',
'substr4' => 'substr($a, 0, 1, "")',
's///' => '$a =~ s/.//s',
);
my %bench = map { $_ => "use strict;
use warnings;
for (1 .. our $inner) {
local our \$a = our \$arg;
$tests{$_} while length(\$a);
}
"
}
keys %tests;
for (
[ '20,000', 80_000/20_000, 'a' x 20_000 ],
[ '40,000', 80_000/40_000, 'a' x 40_000 ],
[ '80,000', 80_000/80_000, 'a' x 80_000 ],
) {
my $name = $_->[0];
local our $inner = $_->[1]
local our $arg = $_->[2];
print("--------------------\n");
print("$name\n");
print("\n");
cmpthese($OUTER, \%bench);
print("\n");
}