2017-11-16 11 views
0

私は現在、perlプログラムのマイクロ最適化を行っていますが、いくつかのゲッターを最適化するのが好きです。 GetABCを呼び出すPerl、エイリアスから変数へ

package Test; 

our $ABC; 

sub GetABC { $ABC } # exported sub... 

()サブ関連のオーバーヘッドの多くを作成します。

私はこのゲッター構造のパッケージを持っています。 $ Test :: ABCを介して直接変数にアクセスすることは非常に高速です。

ゲッターを変数にエイリアスして、変数を直接呼び出すのと同じパフォーマンスを得る方法はありますか? "()"を使用したヒントのインライン展開はうまくいかないようです...

+1

この差は実際どのくらいですか? – Sobrique

+0

約100k :-)それは30-40msの違いです(私の現在のシナリオではかなりの数です)。 – xsign

+0

値を現在の名前空間におそらくインポートしますか? '$ Test :: ABC'を参照するだけで何が問題になっていますか? – Sobrique

答えて

5

変数をアクセササブに変換する方法、または変数を可変アクセスで置き換える方法はありません。オーバーヘッドで生きなければなりません。そのプロトタイプは単にインライン化のための潜在的に適格なサブになるので、一定のアクセスにごサブへの呼び出しをオンにしない()プロトタイプを使用して

  • 非ソリューション。サブのボディ自体は定数ではないので、このサブを定数にすることはできません。

  • オーバーヘッドは、perlが各呼び出しでかなりの簿記をしなければならないので、呼び出しごとです。したがって、XSのアクセサを書き換えることはあまり役に立ちません。

  • constantを作成すると、変数のエイリアスではなく、コピーが定数になるので役に立ちません。

しかしconstant.pm source codeを見ては、興味深いソリューションを開くように思われます。ここにハックがあり、すべてのバージョンのPerlでは動作しない可能性があります:シンボルテーブルエントリにスカラーrefを割り当て、そのエントリがまだタイプグロブを含んでいない場合は、インラインサブバンクが入ります:

package Foo; 
use strict; 
use warnings; 
use feature 'say'; 

my $x = 7; 
BEGIN { $Foo::{GetX} = \$x } # don't try this at home 
say GetX; #=> 7 
$x = 3; 
say GetX; #=> 3 

これは、現在インストールされているほとんどのperlバージョン(5.14,5.22,5.24,5.26)で動作します。しかし、私の5.22-multiと5.26-multiのダイは、 "Read-only値の変更を試みました"。これは、定数モジュールでは問題にはなりません。なぜなら、参照ターゲットを最初に読み取り専用にし、(もっと重要なことに)その変数を決して変更しないからです。

これは確実に機能しないだけでなく、これによっても一定の折り畳みが完全に乱されます。その後、は、ソースコードの中で自分自身をインライン化やっ


関数呼び出しのオーバーヘッドが実際に耐えられない場合には(例えば、あなたの処理時間の二桁のパーセンテージを取る)、あなたの最善の策になるだろう。通話場所が多い場合でも、簡単なケースを修正する簡単なスクリプトを作成することができます。モジュールをインポートするすべてのファイルを選択し、単一のpackage宣言のみを使用します。そのようなファイル内では、電話番号をGetABC(括弧の有無にかかわらず)に置き換えて、完全修飾型のアクセスに置き換えます。うまくいけば、そのトークンはどの文字列にも記述されていないことを望みますその後、これらのコールの残りの発生数を手動で調べることができます。

+0

非常に良い答えをありがとう。私の5.12.3-multiはその変数を書き込むことを許しません...私は運がなくても今は別のもので何時間も試しました。すべてのパッケージのメソッド呼び出しを検索して置き換えるのが最良の答えです(少なくとも今のところ) – xsign

関連する問題