2

我有一个嵌套了好几层的对象,我多次引用它。创建和设置对该对象的引用是否更快或是否重要?

上下文我听说创建本地引用会更快。这是多年前的一个 Visual Basic 项目。但这是Flash。并且输出是一个 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;
}

.
接受 Baris 的建议,我自己测试了它。下面是结果(尽管我不知道如何将它们解释为实际差异,即“方法 1 比方法 2 快 0.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:单点规则 访问嵌套变量时,只要变量需要甚至一级范围转移才能发现,并且被多次引用,则将其保存到局部变量中。在绘图类中,您经常会看到在可能每帧迭代数百次的循环中引用 Math.PI / 2 - 该值应存储在局部变量中。请注意,在引用成员方法时,情况并非如此。将 Math.PI 保存到变量是合适的;将 Math.round 保存到变量不是。

它确实有所作为,但从软件构建的角度来看,更易读的代码将是正确的方法,除非它是关键代码,比如应用程序的物理部分。

除了做时间基准,你也可以检查字节码,使用这个工具http://www.swfwire.com/

于 2012-08-09T22:18:22.500 回答
2

访问的时间可能无关紧要,因为您似乎在做一些 UI 工作,而且花费的毫秒数无关紧要。但还有其他担忧:

  1. 您正在编写重复的代码 - 这总是很糟糕。如果必须重复,您应该编写一个程序,在任何地方从单一来源重复它,如果它可能不会重复 - 选择不重复。担心很简单。一旦发现按钮在其中,ModelB.instance.view1您将需要多次复制和粘贴相同的代码 - 当然,在重复工作时您会犯错误。

  2. AS3 代码不仅允许,而且还欢迎副作用,在这种情况下可能会产生不良影响。例如,Model.instance.view1可能是一个 getter,每次访问它时都会返回一个新的视图副本,或者,当访问时,它可能会更改实例内部状态中的其他内容,无论是什么,并且多次执行此更改是不可取的.

  3. 有得墨忒耳的规则。当超出可能的简化时,它表示您不应该连续使用多个点运算符。即一个对象可能只知道它自己的属性(或局部变量)的属性,但永远不会访问该属性的属性,也永远不会更进一步。这对程序的结构施加了不必要的限制。但是,有时看起来很难避免,您应该争取更好的、独立的代码。更多关于得墨忒耳的规则在这里:http ://en.wikipedia.org/wiki/Law_of_Demeter

“优化”此类代码不是编译器的功能,尤其是因为副作用。编译器将忠实地遵循程序员编写的错误代码并生成大量重复的程序集,因为它相信程序员确实需要这些代码。请注意,我不是在谈论 Adob​​e 编译器,它不是优化编译器,即使静态分析表明,也不会删除此代码。我说的是该语言的一些抽象“理想”编译器,它可以最佳地编译相关代码。

于 2012-08-10T01:29:05.847 回答
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 回答