我刚刚通过了a slideshow from Grant Skinner来提高ActionScript的性能。他给出的一个提示是“直接调用方法而不是通过引用”。我不太明白这意味着什么......
是否意味着避免对引用函数对象的变量进行函数调用?
var someObjectsDoSomethingMethod:Function = someObj.doSomething;
someObjectsDoSomethingMethod();
或者是否避免对引用具有该方法的另一个对象的变量进行函数调用?
var someObject:Function = someObj;
someObject.doSomething();
或......?
答案 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();
我没有对此进行测试,因此可能存在语法错误。当然,你也需要适当的进口。不过,这应该是合乎逻辑的。
确保在浏览器中进行测试,而不仅仅是在调试播放器或预览播放器中。您的浏览器插件将具有更好的性能数字,并且更有可能是最终用户在其计算机上拥有的数据。