2

複数回参照している数レベルの深さでネストされたオブジェクトがあります。そのオブジェクトへの参照を作成して設定する方が速いですか、それとも重要ですか?

コンテキストローカル参照を作成する方が速いと聞きました。これは何年も前のことであり、VisualBasicプロジェクトの場合です。しかし、これはフラッシュです。そして、出力はSWF/バイトコードです。そして、コンパイラーはその参照を調べて、オブジェクトを毎回検索する必要がないように、私が行っていることを実行できます。

例えば:

public function doStuff():void {

    Model.instance.view1.button1 = button1;
    Model.instance.view1.button2 = button2;
    Model.instance.view1.button3 = button3;
    Model.instance.view1.button4 = button4;
    Model.instance.view1.button5 = button5;
    Model.instance.view1.button6 = button6;

    // more fake code referencing more something.something.something like things 

    for (var i:int;i<something.something.something.length;i++) {
        var result:Object = Controller.staticMethod(button1);
        var result2:Object = Controller.staticMethod(button1);
    }
}

対:

public function doStuff():void {
    var view1:View = Model.instance.view1;

    view1.button1 = button1;
    view1.button2 = button2;
    view1.button3 = button3;
    view1.button4 = button4;
    view1.button5 = button5;
    view1.button6 = button6;
}


バリスの提案を受けて、私はそれを自分でテストしました。以下に結果を示します(実際の違いに解釈する方法はわかりませんが、「メソッド1はメソッド2よりも.000001高速です」)。

結果

テスト1

            var instance:Model = Model.instance;

            var startTime:int = getTimer();
            for(var i:int = 0; i<10000000; i++){
                instance.url = "";
            }
            trace(getTimer()-startTime); // 826, 929, 823

            var startTime:int = getTimer();
            for(var i:int = 0; i<10000000; i++){
                Model.instance.url = "";
            }
            trace(getTimer()-startTime); // 3483, 3976, 3539

テスト2

            var instance:Model = Model.instance;

            var localLogo:BitmapImage = Model.instance.logo;

            var startTime:int = getTimer();
            for(var i:int = 0; i<10000000; i++){
                localLogo = logo;
            }
            trace(getTimer()-startTime); // 2070, 2083, 2110

            var startTime:int = getTimer();
            for(var i:int = 0; i<10000000; i++){
                instance.logo = logo;
            }
            trace(getTimer()-startTime); // 2028, 2509, 2154
4

3 に答える 3

3

一般的に、as3コンパイラは私たちが考えるほど賢くはありません。コンパイル時間を短縮するためだと思います。

このページhttp://upshots.org/actionscript/20-tips-to-optimize-your-actionscriptは、次のルールを提供します。

5:ワンドットルールネストされた変数にアクセスするとき、変数が検出するために1レベルのスコープシフトさえ必要とし、複数回参照されるときはいつでも、それをローカル変数に保存します。描画クラスでは、各フレームで数百回繰り返される可能性のあるループ内で参照されるMath.PI / 2がよく見られます。その値は、ローカル変数に格納する必要があります。メンバーメソッドを参照する場合、これは当てはまらないことに注意してください。Math.PIを変数に保存するのが適切です。Math.roundを変数に保存することはできません。

それは違いを生みますが、ソフトウェアビルドの観点からは、アプリの物理セクションのような重要なコードでない限り、より読みやすいコードが適切な方法です。

時間のベンチマークを作成する以外に、このツールhttp://www.swfwire.com/を使用してバイトコードを検査することもできます。

于 2012-08-09T22:18:22.500 に答える
2

私は好きです:

public function doStuff():void {
    var view1:View = Model.instance.view1;

    view1.button1 = button1;
    view1.button2 = button2;
    view1.button3 = button3;
    view1.button4 = button4;
    view1.button5 = button5;
    view1.button6 = button6;
}

見た目はすっきりしていると思います。どちらが速いかをプロファイリングして確認できますが、内部ループでこれを何度も実行していなければ、パフォーマンスは重要ではありません。

public function doStuff():void {
    var startTime:int = getTimer();
    for(var i:int = 0; i<1000000; i++){
        Model.instance.view1.button1 = button1;
        Model.instance.view1.button2 = button2;
        Model.instance.view1.button3 = button3;
        Model.instance.view1.button4 = button4;
        Model.instance.view1.button5 = button5;
        Model.instance.view1.button6 = button6;
    }
    trace(getTimer()-startTime);
}

public function doStuff():void {
    var startTime:int = getTimer();
    for(var i:int = 0; i<1000000; i++){
        var view1:View = Model.instance.view1;

        view1.button1 = button1;
        view1.button2 = button2;
        view1.button3 = button3;
        view1.button4 = button4;
        view1.button5 = button5;
        view1.button6 = button6;
    }
    trace(getTimer()-startTime);
}
于 2012-08-09T16:34:18.897 に答える
2

UI作業を行っているように見えるため、アクセスにかかる時間はおそらく関係ありません。数ミリ秒かかることは問題ではありません。ただし、他にも懸念事項があります。

  1. あなたは繰り返しのコードを書いています-これは常に悪いことです。繰り返す必要がある場合は、どこでも単一のソースから繰り返すプログラムを作成する必要があります。繰り返さない場合は、繰り返さないことを選択してください。懸念は単純です。ボタンが入っていることに気付いたらModelB.instance.view1、同じコードを複数回コピーして貼り付ける必要があります。もちろん、繰り返し作業をしていると、間違いを犯します。

  2. AS3コードは、副作用を許容するだけでなく、この場合、望ましくない影響を引き起こす可能性がある副作用も歓迎します。たとえば、Model.instance.view1アクセスされるたびにビューの新しいコピーを返すゲッターの場合もあれば、アクセスされると、インスタンスの内部状態にある他の何かを変更する場合もあり、この変更を複数回実行することは望ましくありません。 。

  3. デメテルのルールがあります。可能な限り単純化すると、1つ以上のドット演算子を連続して使用してはならないということです。つまり、オブジェクトはそれ自体のプロパティ(またはローカル変数)のプロパティのみを認識できますが、プロパティのプロパティのプロパティにアクセスしたり、さらに先にアクセスしたりすることはありません。これにより、プログラムの構造に不必要な制限が課せられます。ただし、回避するのが難しいように見える場合もあるため、より優れた自己完結型のコードを探す必要があります。デメテルの法則の詳細については、http://en.wikipedia.org/wiki/Law_of_Demeterをご覧ください。

特に副作用があるため、このようなコードを「最適化」するのはコンパイラの機能ではありません。コンパイラーは、プログラマーによって書かれた悪いコードに忠実に従い、このコードが実際に必要であるとプログラマーを信頼するため、多くの反復アセンブリを生成します。注意してください、私は最適化コンパイラではないアドビコンパイラについて話していません、そして静的分析がそれを示唆したとしてもこのコードを削除しません。問題のコードを最適にコンパイルする、言語用の抽象的な「理想的な」コンパイラについて話しています。

于 2012-08-10T01:29:05.847 に答える