in reply to Sort this data

UPDATE

There was a huge error in this test (and I'm stupid for not using strict in it). I was testing @c where I should have been testing @a. I am now going to replace the bad results with the GOOD results.
Here's a benchmark. Six methods were tested, and run for 5 seconds, three times; once on a set of 100 elements, once on 1000, and once on 10000.
in_fr_pu
slices the array in chunks of 4, push()es the hash ref to the new array
140.9 Hz @ 100, 13.9 Hz @ 1000, 1.3 Hz @ 10000

sh_fr_pu
shift()s the array, push()es the hash ref to the new array
156.7 Hz @ 100, 15.7 Hz @ 1000, 1.4 Hz @ 10000

sp_bk_in
presizes the new array, splice()s from the back, inserts the hash ref via index into the new array
149.4 Hz @ 100, 14.8 Hz @ 1000, 1.4 Hz @ 10000

sp_bk_rv
splice()s from the back, push()es the hash ref to the new array, the reverse()s
151.5 Hz @ 100, 14.7 Hz @ 1000, 1.3 Hz @ 10000

sp_bk_un
splice()s from the back, unshift()s the hash ref to the new array
151.6 Hz @ 100, 11.9 Hz @ 1000, .4 Hz @ 10000

sp_fr_pu
splice()s from the front, push()es the hash ref to the new array
160.0 Hz @ 100, 15.6 Hz @ 1000, 1.4 Hz @ 10000
Notice how all of them appear rather linear in form, EXCEPT for sp_bk_un. This is because unshift() is rather inefficient. sp_fr_pu is the fastest because splice()ing from the front just moves the beginning-of-array marker forward in the array. Thus, the next fastest is sh_fr_pu, which just uses 4 calls to shift() instead of splice().
use Benchmark; for $SIZE (100, 1000, 10000) { timethese(-5, { sp_fr_pu => sub { my @a = (1..$SIZE); my @b; while (my @c = splice(@a, 0, 4)) { push @b, { @c } } }, sp_bk_un => sub { my @a = (1..$SIZE); my @b; while (@a and my @c = splice(@a, -4)) { unshift @b, { @c } } }, sp_bk_in => sub { my @a = (1..$SIZE); my @b; $#b = int(@a / 4); my $i = $#b; while (@a and my @c = splice(@a, -4)) { $b[$i--] = { @c } } }, in_fr_pu => sub { my @a = (1..$SIZE); my @b; my $i = 0; while ($i < @a) { push @b, { @a[$i .. $i + 3] }; $i += 4; } }, sh_fr_pu => sub { my @a = (1..$SIZE); my @b; while (@a) { push @b, { map shift(@a), 1..4 } } }, sp_bk_rv => sub { my @a = (1..$SIZE); my @b; while (@a and my @c = splice(@a, -4)) { push @b, { @c } } @b = reverse @b; }, }); }


japhy -- Perl and Regex Hacker

Replies are listed 'Best First'.
Re: Re: Sort this data
by japhy (Canon) on Nov 19, 2000 at 23:59 UTC

    UPDATE

    These results were wrong. I'll get correct ones later.
    Those benchmarks were under 5.005_02. Here are the 5.6 results. They're for different sizes of the list, since the test hung horribly at 10,000 elements.
    Name Hz @ 100 Hz @ 1000 Hz @ 2000
    in_fr_pu 466.1 45.2 22.5
    sh_fr_pu 509.7 49.5 24.6
    sp_bk_in ??? ??? ???
    sp_bk_rv ??? ??? ???
    sp_bk_un ??? ??? ???
    sp_fr_pu 489.3 47.2 23.4


    japhy -- Perl and Regex Hacker
HUGE ERROR in results (Re: Re: Sort this data)
by japhy (Canon) on Nov 20, 2000 at 01:35 UTC
    Updated. I was stupid -- not using strict ended up kicking me in the ass with my benchmark. It's now working properly, and the results are far more... expected.

    japhy -- Perl and Regex Hacker