ASC2.0 を使ってみると、従来のコンパイラとは、生成される swf のパフォーマンスの傾向が異なることが分かります。
この理由の 1 つは、ASC 2.0 が関数のインライン化をサポートしたことです。関数がインライン化されると、関数の呼び出しの記述が、呼び出している関数本体のコードと置き換わります。
記述された通りに実行されていれば、
「関数を呼び出し」 → 「関数内に記述された処理を実行」
となるところが、コンパイル時にインライン化されると、「関数を呼び出し」 の記述がなくなって、代わりに 「関数内に記述された処理」 と置き換えられるため、実行されるのは、
「関数内に記述された処理を実行」
だけとなります。
結果的に実行されるロジックは同じでも、関数呼び出しのオーバーヘッドがなくなるため、多少処理が早くなるという訳です。
通常のコーディング時にはそれほど神経質になる必要は無いと思いますが、ループ内の関数呼び出し等では、インライン化の有無により大きく差が出ることもありるかもしれません。
なので、チューニングの手段の 1 つとして覚えておいても良いかもです。(といっても、ASC 2.0 はまだベータ版なのですが)
インライン化される関数されない関数
関数をインライン化するかしないかは ASC 2.0 の判断です。その際の判断基準となる条件がいくつかあります。
まず、final や static の修飾子がついた関数は、インライン化の候補となります。ファイル内、あるいはパッケージ内からしか参照できない関数も候補です。
たとえば、
final public function get foo():int { return _foo; }
の様にして、ゲッターやセッターをインライン化させるのは良いアイデアかも知れません。
Inline メタデータを指定してもよいようです。
[Inline] final public function bar(i:int):int { var sum:int = i + _foo; return sum; }
しかし、インライン化の対象の関数でも、try を含む場合はインライン化されないようです。
[Inline] static public function baz(i:int):Number { try // この記述があるとインライン化されない { return i / _foo; } catch (e:Error) { return 0.0; } }
同様に、with を含む関数も対象外となるようです。
また、サブクラスやインターフェース経由での呼び出しもインライン化されないようです。
public interface MyInterface { function bar(i:int):int } public class MyClass implements MyInterface { private var _foo:int = 0; [Inline] final public function bar(i:int):int { var sum:int = i + _foo; return sum; } } var mc:MyClass = new MyClass(); mc.bar(0); // インライン化される var mi:MyInterface = mc; mi.bar(0); // インライン化されない
その他、含まれる式の数が 50 を超えるとインライン化されないという制限もあるようです。
非常に参考になるサンプル、ありがとうございます!
インターフェース経由だとインライン化されないのは残念です (−_−;)
Shigeru Nakagaki さん、こんにちは。
AS3 では、継承は実行時に動的に形成される関係です。そのため、コンパイル時にコードを単純に置き換えるという選択ができなかったのだと思われます。