In response to your updated node:
Look at an ASCII chart (2, 3, 4). What's at position 0? It's a byte with all zeros, and yes it's called NUL. It's also referred to as a 'null byte' (all lowercase, four letters). While it's true a null/zero byte can represent something other than NUL, NUL is always represented as a null/zero byte (at least in ASCII and EBCDIC).
When dealing with eight-bit bytes, it shouldn't matter if you have an ASCII character, '\0', 0, "\x00", or "\0". vec(), ikegami's tr/\x00/\xFF/, and anything using use bytes; is working at the byte (or bit, in the case of vec()) level, and not necessarily working on "character" data. Update: it should matter if you have '\0'. It shouldn't matter about the rest. The test isn't failing, though.
I don't need your beer. I'm just trying to help. You can do whatever you like, but I'm not sure where you're getting the idea that '\0' is producing a different end product in these cases. Try "\000" or "\x00" instead, and see if it changes anything at all. I'm guessing using chr(0) is changing absolutely nothing but the speed. Update: and I based this on the results of the Test::More tests that said it was all producing the same output. Apparently, either it's working by some fluke, or the tests are broken.
Take a look at this:
Rate split1 mrm_7 mrm_8 mrm_6
split1 1.08/s -- -100% -100% -100%
mrm_7 1906/s 176180% -- -0% -44%
mrm_8 1910/s 176481% 0% -- -44%
mrm_6 3381/s 312486% 77% 77% --
1..4
ok 1 - split1 gets some value
ok 2 - mrm_7 gets same value
ok 3 - mrm_8 gets same value
ok 4 - mrm_6 gets same value
and here's the code:
#!/usr/bin/perl
use 5.6.0;
use strict;
use warnings FATAL => 'all';
use Benchmark qw( cmpthese );
my $s1 = do_rand(0, 100_000);
my $s2 = do_rand(1, 100_000);
my $subs = {
'split1' => sub { my $s3 = split1( $s1, $s2 ) },
'mrm_6' => sub { mrm_6( \$s1, \$s2 ); $s1 },
'mrm_7' => sub { mrm_7( \$s1, \$s2 ); $s1 },
'mrm_8' => sub { mrm_8( \$s1, \$s2 ); $s1 },
};
cmpthese( -5, $subs );
use Test::More;
plan 'tests' => scalar keys %{$subs};
my $s3;
foreach my $subname ( keys %{$subs} ) {
my $sub = $subs->{$subname};
if ( defined $s3 ) {
is( $sub->(), $s3, "$subname gets same value" );
}
else {
$s3 = $sub->();
ok( defined $s3, "$subname gets some value" );
}
}
sub split1 {
my ($s1, $s2) = @_;
my @s1 = split //, $s1;
my @s2 = split //, $s2;
foreach my $idx ( 0 .. $#s1 ) {
if ( $s1[$idx] eq chr(0) ) {
$s1[$idx] = $s2[$idx];
}
}
return join '', @s1;
}
sub mrm_6 {
# from mrn_5, testing bytes::misc explicitly instead of importing
# also in-place using of $s2
my ( $s1, $s2 ) = @_;
use bytes ();
my $pos = 0;
while ( -1 < ( $pos = bytes::index( $$s1, '\0', $pos ) ) ) {
bytes::substr( $$s1, $pos, 1, bytes::substr( $$s2, $pos, 1 ) )
+;
}
}
sub mrm_7 {
# from mrn_5, testing bytes::misc explicitly instead of importing
# also in-place using of $s2
my ( $s1, $s2 ) = @_;
use bytes ();
my $pos = 0;
while ( -1 < ( $pos = bytes::index( $$s1, "\000", $pos ) ) ) {
bytes::substr( $$s1, $pos, 1, bytes::substr( $$s2, $pos, 1 ) )
+;
}
}
sub mrm_8 {
# from mrn_5, testing bytes::misc explicitly instead of importing
# also in-place using of $s2
my ( $s1, $s2 ) = @_;
use bytes ();
my $pos = 0;
my $chr = chr 0;
while ( -1 < ( $pos = bytes::index( $$s1, $chr, $pos ) ) ) {
bytes::substr( $$s1, $pos, 1, bytes::substr( $$s2, $pos, 1 ) )
+;
}
}
# This makes sure that $s1 has chr(0)'s in it and $s2 does not.
sub do_rand {
my $min = shift;
my $len = shift;
my $n = "";
for (1 .. $len)
{
$n .= chr( rand(255-$min)+$min );
}
return $n;
}
#sub do_rand {
# my $n = (shift) ? int(rand(255)) : int(rand(254)) + 1;
# return chr( $n );
#}
__END__
If you don't trust Test::More, I guess you could make smaller sample data strings and visually inspect them.
Update:Maybe we should trust Test::More, but take a more carefullook at the tests for the benchmarking and testing code being used from above. |