Peter> my $str = "\000" x 20_000;
Peter> my @chr = map { chr $_ } 0 .. 255;
Peter> substr $str, $_, 1, $chr[rand 256] for 1 .. 20_000;
maybe:
pack "C*", map rand 256 for 1 .. 20_000;
If you read my other posts in this thread (those with the benchmarks)
you'll notice that this solution doesn't perform well if compared to a
naive loop of the kind of that used by the OP. But a pack() solution
wins if we pack at four[*] bytes at a time (and in the meanwhile we
discovered that this depends on the RANDBITS compile option).
However it also resulted that map()-versions of the naive loop
solutions were, reasonably, slower than these. So I wondered wether a
solution like 'Loop3' below could perform even better. For ease of
reading I'll repeat my complete test here:
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw/:all/;
# For 'Dev2'
open my $fh, '<', '/dev/urandom' or
die "Can't access `/dev/urandom': $!\n";
cmpthese 500, {
Loop1 => \&Loop1,
Loop2 => \&Loop2,
# Map1 => \&Map1,
# Map2 => \&Map2,
# Subst => \&Subst,
Vec => \&Vec,
Pack1 => \&Pack1,
Pack2 => \&Pack2,
# S => \&S,
Dev1 => \&Dev1,
Dev2 => \&Dev2,
Loop3 => \&Loop3 };
sub Loop1 {
my $str = '';
$str .= chr int rand 256 for 1..20_000;
$str;
}
sub Loop2 {
my @chrs = map chr, 0..255;
my $str = '';
$str .= $chrs[rand 256] for 1..20_000;
$str;
}
sub Map1 {
join '', map { chr int rand 256 } 1..20_000;
}
sub Map2 {
my @chrs = map chr, 0..255;
join '', map $chrs[rand 256], 1..20_000;
}
sub Subst {
my $str = "\000" x 20_000;
my @chrs = map chr, 0..255;
substr $str, $_, 1, $chrs[rand 256] for 0..19_999;
$str;
}
sub Vec {
my $str = ' ' x 20000;
vec($str, $_, 8) = rand 256 for 0..19_999;
$str;
}
sub Pack1 {
pack 'C*', map int rand 256, 1..20_000;
}
sub Pack2 {
# Is this OK, BTW?
pack 'L*', map rand ~0, 1..5_000;
}
sub S {
local $_ = ' ' x 20_000;
s/ /chr int rand 256/ge;
$_;
}
sub Dev1 {
open my $fh, '<', '/dev/urandom' or
die "Can't access `/dev/urandom': $!\n";
local $/ = \20_000;
scalar <$fh>;
}
sub Dev2 {
local $/ = \20_000;
scalar <$fh>;
}
sub Loop3 {
my $str = '';
$str .= pack 'L*', rand 2**32 for 1..5_000;
$str;
}
__END__
Results:
Rate Vec Pack1 Loop1 Loop2 Loop3 Dev1 Dev2 Pack2
Vec 74.7/s -- -5% -12% -16% -70% -71% -72% -77%
Pack1 78.7/s 5% -- -7% -11% -68% -70% -71% -75%
Loop1 84.7/s 13% 8% -- -4% -65% -67% -68% -74%
Loop2 88.5/s 18% 12% 4% -- -64% -66% -67% -72%
Loop3 245/s 228% 211% 189% 177% -- -6% -8% -24%
Dev1 260/s 248% 231% 207% 194% 6% -- -3% -19%
Dev2 267/s 258% 240% 216% 202% 9% 3% -- -17%
Pack2 321/s 329% 307% 278% 262% 31% 23% 20% --
So: no, it wasn't a good idea...
[*] Eight on 64-bit CPUs?
Michele