MPがありません。

$liiu->mp == 0

Function::Parameters + Mouse::Util::TypeConstraints = パフォーマンス激強

概要

Perlのサブルーチンの引数バリデーションをするモジュールはいろいろありますが、 Function::Parameters が他の引数のバリデーションを行うモジュールと比べて高速にバリデーションできるという話を聞いて、であれば Mouse::Util::TypeConstraints と組み合わせて使えばとても良いパフォーマンスがでるのではと思い、実際にベンチマークをとってみました。

比較対象は以下のとおりです。
最近良く使われている印象があるモジュールと、何もチェックを行わない場合とで比較してみました。
Smart::ArgsData::Validator は、引数にハッシュを渡すほうがリストを渡すよりもパフォーマンスが良い(あるいはほとんど変わらない)ようなので、ハッシュを渡しています。

  • 何もチェックしない場合
  • Data::Validator 1.07
  • Smart::Args 0.14
  • Function::Parameters 2.001003 + Type::Tiny 1.004002
  • Function::Parameters 2.001003 + Mouse::Util::TypeConstraints v2.5.4

ベンチマークスクリプト

use v5.28;
use warnings;
use utf8;
use DDP;
use Benchmark qw( timethese cmpthese );
use Smart::Args qw( args args_pos );
use Data::Validator;

sub nomal {
  my ($id, $name, $pass) = @_;
}

sub smart_args {
  args my $id => 'Str', my $name => 'Str', my $pass => 'Str';
}

sub data_validator {
  state $rule = Data::Validator->new(
    id => 'Str',
    name => 'Str',
    pass => 'Str',
  );
  my $args = $rule->validate(@_);
  my ($id, $name, $pass) = @$args{qw/ id name pass /};
}

{
  use Function::Parameters;
  use constant Str => Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint('Str');
  fun function_parameters_mouse(Str $id, Str $name, Str $pass) {
  }
  use Types::Standard qw( Str );
  fun function_parameters_types_standard(Str $id, Str $name, Str $pass) {
  }
}

my $args = {
  id   => 'mp0liiu',
  name => 'Maybe_mp0liiu',
  pass => 'hogehoge!!!',
};
my @args = @$args{qw/ id name pass /};

cmpthese(
  timethese(
    100_0000,
    {
      nomal                              => sub { nomal(@args) },
      smart_args                         => sub { smart_args($args) },
      data_validator                     => sub { data_validator($args) },
      function_parameters_mouse          => sub { function_parameters_mouse(@args) },
      function_parameters_types_standard => sub { function_parameters_types_standard(@args) },
    }
  )
);

結果

                                        Rate smart_args data_validator function_parameters_types_standard function_parameters_mouse nomal
smart_args                           23068/s         --           -77%                               -93%                      -97%  -99%
data_validator                       99404/s       331%             --                               -68%                      -86%  -96%
function_parameters_types_standard  313480/s      1259%           215%                                 --                      -56%  -87%
function_parameters_mouse           719424/s      3019%           624%                               129%                        --  -69%
nomal                              2325581/s      9981%          2240%                               642%                      223%    --

感想

Function::ParametersMouse::Util::TypeConstraints を併用した場合の速度がとても速くて驚きました。
誤差などあると思いますが、何もチェックしない関数の1/3程度の時間でちゃんと引数の個数や型をチェックをしてくれるってすごくないですか???
Function::Parameters の書き方は微妙に気に入らないところもあるのですが、このパフォーマンスで引数の個数と型をチェックしてくれるのは非常に魅力的なので個人の開発では利用していきたいと思います。
ただ、型チェックオブジェクトを Types::Standard みたいにクールにかけないので、 Mouse::Util::TypeConstraints を使う場合も同じようにクールに書けると良さそうかなあ、、、