“直接调用方法而不是通过引用”是什么意思?

时间:2011-08-18 16:54:16

标签: actionscript-3

我刚刚通过了a slideshow from Grant Skinner来提高ActionScript的性能。他给出的一个提示是“直接调用方法而不是通过引用”。我不太明白这意味着什么......

是否意味着避免对引用函数对象的变量进行函数调用?

var someObjectsDoSomethingMethod:Function = someObj.doSomething;
someObjectsDoSomethingMethod();

或者是否避免对引用具有该方法的另一个对象的变量进行函数调用?

var someObject:Function = someObj;
someObject.doSomething();

或......?

2 个答案:

答案 0 :(得分:1)

你是在正确的轨道上,他说,如果可能的话(特别是对于循环中的方法调用),最快的方法是根本不使用方法调用(参见幻灯片51),但是如果你必须那么试试直接调用方法(幻灯片52)。虽然这并不总是实用或不合适,但是根据您调用方法的方式以及调用它的对象,会有一些开销。

最大的收获是关闭真的很贵。

例如:

WithAnonymousFunction.Go(function() { /* Do Work */ });  // Slow
WithReference.Go(new WorkerClass()); // Faster
WithAnonymousReference.Go((new WorkerClass()).doWork); // Faster
WithMethod.Go(); // Even faster!
WithInlinedMthod.Go() // Fastest!

public class WithAnonymousFunction {
    public static function Go(func:Function):void { 
        func();         
    }
}

public class WorkerClass {
    public doWork() { // Do Work }
}

public class WithAnonymousReference {        
    public static function Go(func:Function) {
        func();         
    }
}

public class WithReference {
    public static function Go(cls:WorkerClass) {
        cls.doWork()
    }
}   

public class WithMethod {
    public static function Go() {
        doWork();
    }

    public static function doWork():void { // Do Work }
}

public class WithInlinedMethod {
    public static function Go() {
        // Do Work
    }
}

我不确定的一件事是使用具体类与接口之间的性能差异。

答案 1 :(得分:0)

var someFunction:Function = function():void{}

的执行速度比

public function someFunction():void{}

差异是否足够重要是完全不同的故事。我认为使用函数类型变量作为“事件”的临时回调(非Flash AS3事件,但“事件”一词的一般含义),每个更新循环不会发生一次,这是很有价值的。即使在更新循环中,这种策略比使用Flash本机事件调度模型更具性能友好性(特别是如果你使用事件冒泡,这是一个绝对的猪)。

当然,他也可能指的是Demeter法,它是一种封装深层嵌套的“has-a”类型关系的方法,这样你就不在乎“doFoo()”是否需要10个对象引用和函数只要foo完成,就会在引擎盖下打电话。 Demeter法则可能非常高性能,具体取决于调用doFoo()时调用栈的深度。

关于评论中的问题,测试自己很容易。在fla:

// on frame 1
var textField:TextField = new TextField();
this.addChild(textField);

var f:Function = this.stop();
var i:int = 0;
var ilen:int = 100000;

var time:int;

time = getTimer();
for(i = 0 ; i < ilen ; i++){
    f();
}
time = getTimer() - time;
textField.text = "f() :: "+String(time)+"\n";

this.gotoAndStop(2);

// on frame 2

var mc:MovieClip = new MovieClip();
time = getTimer();
for(i = 0 ; i < ilen ; i++){
    mc.stop();
}
time = getTimer() - time;
textField.appendText("mc.stop() :: " + String(time));
this.stop();

我没有对此进行测试,因此可能存在语法错误。当然,你也需要适当的进口。不过,这应该是合乎逻辑的。

确保在浏览器中进行测试,而不仅仅是在调试播放器或预览播放器中。您的浏览器插件将具有更好的性能数字,并且更有可能是最终用户在其计算机上拥有的数据。