for(;;)とforeach()とLoop unrollingと

YappoLogs: CPUの気持ちは大事だけど、VMの気持ちも考えようよ
http://d.hatena.ne.jp/yappo/20090330/1238360153

会議中なので-MO=Consiseしてないし特に言いたいことはない。

use strict;
use warnings;
use Benchmark qw(:all);

cmpthese(
    timethese(
        0,
        {
            loop_for => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i++) {
                    $sum = $sum + $i;
                }
            },
            loop_foreach => sub {
                my $sum = 0;
                for my $i (0 .. 99) {
                    $sum = $sum + $i;
                }
            },
            loop_unrolling_5 => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i += 5) {
                    $sum = $sum + $i + 0;
                    $sum = $sum + $i + 1;
                    $sum = $sum + $i + 2;
                    $sum = $sum + $i + 3;
                    $sum = $sum + $i + 4;
                }
            },
            loop_unrolling_10 => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i += 10) {
                    $sum = $sum + $i + 0; $sum = $sum + $i + 1; $sum = $sum + $i + 2; $sum = $sum + $i + 3; $sum = $sum + $i + 4;
                    $sum = $sum + $i + 5; $sum = $sum + $i + 6; $sum = $sum + $i + 7; $sum = $sum + $i + 8; $sum = $sum + $i + 9;
                }
            },
            loop_unrolling_50 => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i += 50) {
                    $sum = $sum + $i + 0; $sum = $sum + $i + 1; $sum = $sum + $i + 2; $sum = $sum + $i + 3; $sum = $sum + $i + 4;
                    $sum = $sum + $i + 5; $sum = $sum + $i + 6; $sum = $sum + $i + 7; $sum = $sum + $i + 8; $sum = $sum + $i + 9;
                    $sum = $sum + $i + 10; $sum = $sum + $i + 11; $sum = $sum + $i + 12; $sum = $sum + $i + 13; $sum = $sum + $i + 14;
                    $sum = $sum + $i + 15; $sum = $sum + $i + 16; $sum = $sum + $i + 17; $sum = $sum + $i + 18; $sum = $sum + $i + 19;
                    $sum = $sum + $i + 20; $sum = $sum + $i + 21; $sum = $sum + $i + 22; $sum = $sum + $i + 23; $sum = $sum + $i + 24;
                    $sum = $sum + $i + 25; $sum = $sum + $i + 26; $sum = $sum + $i + 27; $sum = $sum + $i + 28; $sum = $sum + $i + 29;
                    $sum = $sum + $i + 30; $sum = $sum + $i + 31; $sum = $sum + $i + 32; $sum = $sum + $i + 33; $sum = $sum + $i + 34;
                    $sum = $sum + $i + 35; $sum = $sum + $i + 36; $sum = $sum + $i + 37; $sum = $sum + $i + 38; $sum = $sum + $i + 39;
                    $sum = $sum + $i + 40; $sum = $sum + $i + 41; $sum = $sum + $i + 42; $sum = $sum + $i + 43; $sum = $sum + $i + 44;
                    $sum = $sum + $i + 45; $sum = $sum + $i + 46; $sum = $sum + $i + 47; $sum = $sum + $i + 48; $sum = $sum + $i + 49;
                }
            },
            loop_unrolling_100 => sub {
                my $sum = 0;
                for (my $i = 0; $i < 100; $i += 100) {
                    $sum = $sum + $i + 0; $sum = $sum + $i + 1; $sum = $sum + $i + 2; $sum = $sum + $i + 3; $sum = $sum + $i + 4;
                    $sum = $sum + $i + 5; $sum = $sum + $i + 6; $sum = $sum + $i + 7; $sum = $sum + $i + 8; $sum = $sum + $i + 9;
                    $sum = $sum + $i + 10; $sum = $sum + $i + 11; $sum = $sum + $i + 12; $sum = $sum + $i + 13; $sum = $sum + $i + 14;
                    $sum = $sum + $i + 15; $sum = $sum + $i + 16; $sum = $sum + $i + 17; $sum = $sum + $i + 18; $sum = $sum + $i + 19;
                    $sum = $sum + $i + 20; $sum = $sum + $i + 21; $sum = $sum + $i + 22; $sum = $sum + $i + 23; $sum = $sum + $i + 24;
                    $sum = $sum + $i + 25; $sum = $sum + $i + 26; $sum = $sum + $i + 27; $sum = $sum + $i + 28; $sum = $sum + $i + 29;
                    $sum = $sum + $i + 30; $sum = $sum + $i + 31; $sum = $sum + $i + 32; $sum = $sum + $i + 33; $sum = $sum + $i + 34;
                    $sum = $sum + $i + 35; $sum = $sum + $i + 36; $sum = $sum + $i + 37; $sum = $sum + $i + 38; $sum = $sum + $i + 39;
                    $sum = $sum + $i + 40; $sum = $sum + $i + 41; $sum = $sum + $i + 42; $sum = $sum + $i + 43; $sum = $sum + $i + 44;
                    $sum = $sum + $i + 45; $sum = $sum + $i + 46; $sum = $sum + $i + 47; $sum = $sum + $i + 48; $sum = $sum + $i + 49;
                    $sum = $sum + $i + 50; $sum = $sum + $i + 51; $sum = $sum + $i + 52; $sum = $sum + $i + 53; $sum = $sum + $i + 54;
                    $sum = $sum + $i + 55; $sum = $sum + $i + 56; $sum = $sum + $i + 57; $sum = $sum + $i + 58; $sum = $sum + $i + 59;
                    $sum = $sum + $i + 60; $sum = $sum + $i + 61; $sum = $sum + $i + 62; $sum = $sum + $i + 63; $sum = $sum + $i + 64;
                    $sum = $sum + $i + 65; $sum = $sum + $i + 66; $sum = $sum + $i + 67; $sum = $sum + $i + 68; $sum = $sum + $i + 69;
                    $sum = $sum + $i + 70; $sum = $sum + $i + 71; $sum = $sum + $i + 72; $sum = $sum + $i + 73; $sum = $sum + $i + 74;
                    $sum = $sum + $i + 75; $sum = $sum + $i + 76; $sum = $sum + $i + 77; $sum = $sum + $i + 78; $sum = $sum + $i + 79;
                    $sum = $sum + $i + 80; $sum = $sum + $i + 81; $sum = $sum + $i + 82; $sum = $sum + $i + 83; $sum = $sum + $i + 84;
                    $sum = $sum + $i + 85; $sum = $sum + $i + 86; $sum = $sum + $i + 87; $sum = $sum + $i + 88; $sum = $sum + $i + 89;
                    $sum = $sum + $i + 90; $sum = $sum + $i + 91; $sum = $sum + $i + 92; $sum = $sum + $i + 93; $sum = $sum + $i + 94;
                    $sum = $sum + $i + 95; $sum = $sum + $i + 96; $sum = $sum + $i + 97; $sum = $sum + $i + 98; $sum = $sum + $i + 99;
                }
            },
            noloop => sub {
                my $sum = 0;
                $sum = $sum + 0; $sum = $sum + 1; $sum = $sum + 2; $sum = $sum + 3; $sum = $sum + 4;
                $sum = $sum + 5; $sum = $sum + 6; $sum = $sum + 7; $sum = $sum + 8; $sum = $sum + 9;
                $sum = $sum + 10; $sum = $sum + 11; $sum = $sum + 12; $sum = $sum + 13; $sum = $sum + 14;
                $sum = $sum + 15; $sum = $sum + 16; $sum = $sum + 17; $sum = $sum + 18; $sum = $sum + 19;
                $sum = $sum + 20; $sum = $sum + 21; $sum = $sum + 22; $sum = $sum + 23; $sum = $sum + 24;
                $sum = $sum + 25; $sum = $sum + 26; $sum = $sum + 27; $sum = $sum + 28; $sum = $sum + 29;
                $sum = $sum + 30; $sum = $sum + 31; $sum = $sum + 32; $sum = $sum + 33; $sum = $sum + 34;
                $sum = $sum + 35; $sum = $sum + 36; $sum = $sum + 37; $sum = $sum + 38; $sum = $sum + 39;
                $sum = $sum + 40; $sum = $sum + 41; $sum = $sum + 42; $sum = $sum + 43; $sum = $sum + 44;
                $sum = $sum + 45; $sum = $sum + 46; $sum = $sum + 47; $sum = $sum + 48; $sum = $sum + 49;
                $sum = $sum + 50; $sum = $sum + 51; $sum = $sum + 52; $sum = $sum + 53; $sum = $sum + 54;
                $sum = $sum + 55; $sum = $sum + 56; $sum = $sum + 57; $sum = $sum + 58; $sum = $sum + 59;
                $sum = $sum + 60; $sum = $sum + 61; $sum = $sum + 62; $sum = $sum + 63; $sum = $sum + 64;
                $sum = $sum + 65; $sum = $sum + 66; $sum = $sum + 67; $sum = $sum + 68; $sum = $sum + 69;
                $sum = $sum + 70; $sum = $sum + 71; $sum = $sum + 72; $sum = $sum + 73; $sum = $sum + 74;
                $sum = $sum + 75; $sum = $sum + 76; $sum = $sum + 77; $sum = $sum + 78; $sum = $sum + 79;
                $sum = $sum + 80; $sum = $sum + 81; $sum = $sum + 82; $sum = $sum + 83; $sum = $sum + 84;
                $sum = $sum + 85; $sum = $sum + 86; $sum = $sum + 87; $sum = $sum + 88; $sum = $sum + 89;
                $sum = $sum + 90; $sum = $sum + 91; $sum = $sum + 92; $sum = $sum + 93; $sum = $sum + 94;
                $sum = $sum + 95; $sum = $sum + 96; $sum = $sum + 97; $sum = $sum + 98; $sum = $sum + 99;
                }
        }
    )
);
Benchmark: running loop_for, loop_foreach, loop_unrolling_10, loop_unrolling_100, loop_unrolling_5, loop_unrolling_50, noloop for at least 3 CPU seconds...
  loop_for:  3 wallclock secs ( 3.16 usr +  0.00 sys =  3.16 CPU) @ 41487.34/s (n=131100)
loop_foreach:  3 wallclock secs ( 3.17 usr +  0.00 sys =  3.17 CPU) @ 53420.19/s (n=169342)
loop_unrolling_10:  3 wallclock secs ( 3.14 usr +  0.00 sys =  3.14 CPU) @ 42575.48/s (n=133687)
loop_unrolling_100:  4 wallclock secs ( 3.14 usr +  0.00 sys =  3.14 CPU) @ 43949.04/s (n=138000)
loop_unrolling_5:  3 wallclock secs ( 3.09 usr +  0.00 sys =  3.09 CPU) @ 37364.72/s (n=115457)
loop_unrolling_50:  3 wallclock secs ( 3.13 usr +  0.00 sys =  3.13 CPU) @ 44089.46/s (n=138000)
    noloop:  4 wallclock secs ( 3.21 usr +  0.00 sys =  3.21 CPU) @ 96098.44/s (n=308476)
                      Rate loop_unrolling_5 loop_for loop_unrolling_10 loop_unrolling_100 loop_unrolling_50 loop_foreach noloop
loop_unrolling_5   37365/s               --     -10%              -12%               -15%              -15%         -30%   -61%
loop_for           41487/s              11%       --               -3%                -6%               -6%         -22%   -57%
loop_unrolling_10  42575/s              14%       3%                --                -3%               -3%         -20%   -56%
loop_unrolling_100 43949/s              18%       6%                3%                 --               -0%         -18%   -54%
loop_unrolling_50  44089/s              18%       6%                4%                 0%                --         -17%   -54%
loop_foreach       53420/s              43%      29%               25%                22%               21%           --   -44%
noloop             96098/s             157%     132%              126%               119%              118%          80%     --