メソッド呼び出しのセマンティクスを使用してstrict 'refs'
制限を回避するという Sinan の提案は、最もクリーンで読みやすいソリューションです。
これに関する私の唯一の懸念は、このアプローチを使用することによる速度のペナルティが問題になる可能性があることでした. メソッド呼び出しのパフォーマンスの低下と、インライン化可能な関数の速度の利点については、誰もが聞いたことがあるでしょう。
そこで、ベンチマークを実行することにしました (コードと結果が続きます)。
結果は、通常のインライン定数は、リテラル サブルーチン名を使用したメソッド呼び出しの約 2 倍の速度で実行され、変数サブルーチン名を使用したメソッド呼び出しのほぼ 3 倍の速度で実行されることを示しています。最も遅いアプローチは、標準の deref と の呼び出しですno strict "refs";
。
しかし、最も遅いアプローチでさえ、私のシステムでは 1 秒間に 140 万回以上と非常に高速です。
これらのベンチマークは、この問題を解決するためにメソッド呼び出しアプローチを使用することに関する私の 1 つの留保を消し去ります。
use strict;
use warnings;
use Benchmark qw(cmpthese);
my $class = 'MyConstant';
my $name = 'VALUE';
my $full_name = $class.'::'.$name;
cmpthese( 10_000_000, {
'Normal' => \&normal_constant,
'Deref' => \&direct_deref,
'Deref_Amp' => \&direct_deref_with_amp,
'Lit_P_Lit_N' => \&method_lit_pkg_lit_name,
'Lit_P_Var_N' => \&method_lit_pkg_var_name,
'Var_P_Lit_N' => \&method_var_pkg_lit_name,
'Var_P_Var_N' => \&method_var_pkg_var_name,
});
sub method_lit_pkg_lit_name {
return 7 + MyConstant->VALUE;
}
sub method_lit_pkg_var_name {
return 7 + MyConstant->$name;
}
sub method_var_pkg_lit_name {
return 7 + $class->VALUE;
}
sub method_var_pkg_var_name {
return 7 + $class->$name;
}
sub direct_deref {
no strict 'refs';
return 7 + $full_name->();
}
sub direct_deref_with_amp {
no strict 'refs';
return 7 + &$full_name;
}
sub normal_constant {
return 7 + MyConstant::VALUE();
}
BEGIN {
package MyConstant;
use constant VALUE => 32;
}
そして結果:
Rate Deref_Amp Deref Var_P_Var_N Lit_P_Var_N Lit_P_Lit_N Var_P_Lit_N Normal
Deref_Amp 1431639/s -- -0% -9% -10% -29% -35% -67%
Deref 1438435/s 0% -- -9% -10% -28% -35% -67%
Var_P_Var_N 1572574/s 10% 9% -- -1% -22% -29% -64%
Lit_P_Var_N 1592103/s 11% 11% 1% -- -21% -28% -63%
Lit_P_Lit_N 2006421/s 40% 39% 28% 26% -- -9% -54%
Var_P_Lit_N 2214349/s 55% 54% 41% 39% 10% -- -49%
Normal 4353505/s 204% 203% 177% 173% 117% 97% --
Windows XP、YMMV で ActivePerl 826 を使用して生成された結果。