読者です 読者をやめる 読者になる 読者になる

Perlのswitch文とif/else文のベンチマークを取ってみた

perl

ちょっとしたスクリプトをPerlで書いてて、

$hogeが文字列aのときは文字列a'を返す
$hogeが文字列bのときは文字列b'を返す
<略>
$hogeがどれにもマッチしない場合はhogeを返す

みたいなよくある処理をする必要が出てきて、見やすいからという理由で use Switch してswitch文を使ってたんだけど、if/else で書くのとどっちが早いのか気になったのでベンチマークを取ってみた。
別件でperldoc眺めてたら5.10.0から use feature "switch" でPerl6ライクなswitch文が使えることがわかったので、それも比較対象に。

テストコード

#!/usr/bin/env perl

use strict;
use warnings;
use Switch;
use feature "switch";
use Benchmark qw( cmpthese timethese );

my @letters = qw( a b c d );

my $r = timethese(-1, {
    switch_case => sub {
        for my $letter (@letters) {
            switch ($letter) {
                case (/a/) { return "apple"; }
                case (/b/) { return "banana"; }
                case (/c/) { return "coconut"; }
                else { return "something else"; }
            }
        }
    },
    given_when => sub {
        for my $letter (@letters) {
            given ($letter) {
                when (/a/) { return "apple"; }
                when (/b/) { return "banana"; }
                when (/c/) { return "coconut"; }
                default { return "something else"; }
            }
        }
    },
    if_else => sub {
        for my $letter (@letters) {
            if    ($letter =~ /a/) { return "apple"; }
            elsif ($letter =~ /b/) { return "banana"; }
            elsif ($letter =~ /c/) { return "coconut"; }
            else { return "something else"; }
        }
    },
});

cmpthese($r);

結果

                 Rate switch_case  given_when     if_else
switch_case   47287/s          --        -95%        -97%
given_when   998734/s       2012%          --        -38%
if_else     1607775/s       3300%         61%          --

if/elseが圧倒的に早かった。続いて given/when。switch/case は無かったことにしよう… 実際何万回も回すことはないので体感上の違いはないかもしれないけど、早いに越したことはない。ということで作っていたスクリプトは if/else に書き換えた。

ちなみに5.12.2でuse Switchしようとすると

Switch will be removed from the Perl core distribution in the next major release. Please install it from CPAN.

やっぱり無かったことになるみたい。