1

perl サブルーチンへのパラメーターは @_ で渡されます。プログラムを読みやすくするために、私は常に次のパターンを使用して名前付きパラメーターを取得してきました。

sub foo1 {
    my ($bar, $baz) = @_;
    do_something($bar,$baz);
}

しかし、それは原因$_[0]であり$_[1]コピーされます。$_[0]上記のパターンでアクセスする代わりに直接アクセスする場合$bar、呼び出し元のパラメーターへの値渡し/エイリアス アクセスがあり、参照渡しの通常の注意事項がありますが、はるかに高速です (以下のデモを参照)。

私は、このmy ($param1, $param2 ...) = @_;パターンがパフォーマンス上の理由で悪いのではないかと疑っています。そのため、高速で読み取り可能なプログラムのどちらかを選択する必要があることがわかりましたが、これは不可能な選択です。

私は最終的に、パフォーマンスに重点を置いたサブを書き、$_[<n>]それ以外はすべて上記のパターンで書きます。問題は、多くの場合、ボトルネックがどこにあるかを事前に知らないことです;-)

高速な名前付きパラメーターを取得する方法はありますか? または、この問題について正典と思われるものは何ですか?$_[0]または$bar

付録: 速度のデモ

use Time::HiRes qw(time);

# Lets just do *something* with the parameters - here we just add up all
# their lengths
my $totalLength = 0;

sub foo1 {
    # Access $_[0] directly - effectively call-by-reference
    $totalLength += length($_[0]);
}

sub foo2 {
    # Access a copy of $_[0] - effectively call-by-value  - involves
    # copying
    my ($bar) = @_;
    $totalLength += length($bar);
}

my $a = 'b' x 10_000;
my $t0 = time;
foreach (0..1_000_000) {
    foo1($a);
}
printf "foo1 %2.6f\n", time - $t0;

$t0 = time;
foreach (0..1_000_000) {
    foo2($a);
}
printf "foo2 %2.6f\n", time - $t0;

プリントアウト

foo1 0.329470
foo2 1.280364

foo1 は、コピーを回避するため、foo2 よりもほぼ 4 倍高速です$_[0]

4

2 に答える 2

6

ハッシュリファレンスを介してそれらを渡します:

my %args = (bar=>1, baz=>2);
mySub(\%args);
sub mySub {
    my $args = shift;
    doSomething($args); # pass entire parameter list for cheap!
    doSomething2($args{bar}); # Use specific parameter
}

率直に言って、パフォーマンスの利点については少し疑問があります (ハッシュ アクセスは無料ではありません) が、本当に必要な場合はベンチマークを行うことができます。しかし、これは最高のパフォーマンスのオプションではなく (以下を参照)、必要でさえないかもしれません (最後の部分を参照)。これを試す必要はあまりないと思います。


もう 1 つのオプション (これはちょっとひどいですが、パフォーマンスには優れています) を使用すること$_[1]です。

           # pass `baz`
doSomething($_[1]);

さらにパフォーマンスは高いが設計が悪いオプションは、パラメーターの受け渡しをすべてバイパスし、グローバル変数を使用してパラメーターを渡すことです。

our $bar = 1;
mySub();
sub mySub {
    #do something with $bar. Pray some other code didn't clobber it
}

最後の考慮事項:

コードが非常によく調整されていて、パフォーマンスに敏感で、いくつかのスカラーをコピーするだけで大​​きな違いが生じる場合は、Perl からそれらの関数の純粋な C にドロップアウトすることをお勧めします。

しかし、クヌースが言ったように、時期尚早に最適化しないでください

まず、アプリ全体をプロファイリングし、スカラー パラメーターのコピーが実際に最大のボトルネックになっている場所であることを確認します。これがもっともらしいことに異論はありませんが、通常、ボトルネックは他の場所にあります (IO、DB、遅いデータ構造など)。

つまり、$operation_X4 倍速く実装できるという事実$operation_Xは、ランタイムの合計 0.01% を占めていれば意味がありません。読みやすさが低下することを考えると、4倍高速化することは、単に問題に値するものではありません。

于 2013-07-09T23:38:36.027 に答える
1

さて、$bar と $baz をこの順序でサブ do_something() に渡す場合、もう 1 つの悪いオプションは、次の恐ろしい (しかし文書化された) 構文を使用することです。

sub foo1 { goto &do_something}

...これにより、コンテキストがすぐに do_something() に渡されます。パラメーターを文書化することには何の助けもありませんが、これはおそらく、一連の別のルーチンへの最速の受け渡しメカニズムです。:-)

一体、私はこの答えを自分で反対票を投じます....

于 2013-07-10T01:59:09.913 に答える