perlquestion
spurperl
Something that comes up fairly often is a need to split a string to equal sized chunks. For instance, given the string "abcdefgh12345678", splitting it to 4-char chunks would produce ("abcd", "efgh", "1234", "5678"). Looking around the monastery, there're at least a [id://74815|couple] of [id://543195|posts] I have found. <p>
I tried to time some different techniques against each other:<p>
<code>
my $str = "abcdefgh12345678" x 20;
my $strlen = length $str;
cmpthese(50000, {
'grep_split' => sub
{
my @arr = grep {$_} split /(.{8})/, $str;
},
'split_pos' => sub
{
my @arr = split /(?(?{pos() % 8})(?!))/, $str;
},
'substr_map' => sub
{
my $len = length $str;
my @arr = map {substr($str, $_ * 8, 8)} (0 .. $strlen / 8 - 1);
},
'substr_loop' => sub
{
my @arr;
my $len = length $str;
for (my $i = 0; $i < $len; $i += 8)
{
push(@arr, substr($str, $i, 8));
}
},
'unpack' => sub
{
my @arr = unpack('(A8)*', $str);
}
});
</code><p>
And the results are quite surprising:
<p>
<code>
Rate
split_pos 3203/s
grep_split 6425/s
substr_map 8889/s
unpack 11348/s
substr_loop 15097/s
</code>
<p>
Contrary to what I have expected from my understanding (that built in functions should be faster than loops), the looping solution is the swiftest. It beats the unpack by a margin ranging from 15 to 50 percent, depending on the length of the string and the chunks.<p>
Any way to make it faster ?