FlashLite: 定数を変数に入れる基準
Flashでは変数名や定数など、頻繁に使用する文字列はLookup Tableに入れてコードサイズを節約してくれますが、FlashLite1.xにはその機能がありません。ですので、頻繁に使う定数などは短い名前の変数に入れてしまう、ということを自分でやることでコードサイズの節約ができる場合があります。FL1では、数値のデータも文字列としてコンパイルされるため、65536とかを大量に使う人には役に立つかもしれません。
で、このエントリーでは、何回使ったらお得なのかというのを計算してみようと思います。
65536を参照するときは、SWFでは65536をスタックにプッシュするという処理にコンパイルされます。
push [65536]
16進ダンプすると、以下の10バイトになります。
96 07 00 00 36 35 35 33 36 00
65536の5文字 + 5バイトというわけです。
一方変数Aの値の参照は、以下の7バイトになります。
push [A]
getvar
96 03 00 00 41 00 1C
また、A=65536の代入処理は、以下の17バイトになります。
push [A]
push [65536]
setvar
96 03 00 00 41 00 96 07 00 00 36 35 35 33 36 00 1D
これは、定数長5文字+12バイトです。
したがって、たとえば65536を10回使うとすると、定数のまま使うと10 x 10バイトで100バイト、変数Aに65536を代入してから使うと17バイト+10 x 7バイトで87バイトで、変数Aに代入するほうが13バイト少ないということになります。
もし、A=65536の代入を行うときに、Aと65536をまとめてpushしてよいことにすると、さらに3バイト節約になります。
一般に長さnの定数をk回使用するとき、1文字の変数に代入してから使うほうがバイトコードのサイズが小さくなる条件は、
12+n - (n + 5 - 7) x k < 0
である、ということになります。
これを整数kについて解くと、
minimum(k) = CEILING((13+n)/(n-2))
となります。ただし、CEILING(x)はxを下回らない最小の整数です。
(まとめプッシュありの場合はminimum(k) = CEILING((10+n)/(n-2)))
実際の値を入れて表にしてみました。65536ならn=5なので、6回以上使うならお得ということになります。
n | k(まとめpushなし) | k(まとめpushあり) |
---|---|---|
3 | 16 | 13 |
4 | 9 | 7 |
5 | 6 | 5 |
6 | 5 | 4 |
7 | 4 | 4 |
8 | 4 | 3 |
9 | 4 | 3 |
10 | 3 | 3 |
11 | 3 | 3 |
12 | 3 | 3 |
13 | 3 | 3 |
14 | 3 | 2 |
15 | 3 | 2 |
16 | 3 | 2 |
17 | 2 | 2 |
また、剰余(%)演算に定数が含まれる場合、たとえば
X = Y % 65536;は、
X = Y - int(Y / 65536) * 65536;
に変換されてコンパイルされるので、定数が使用される回数は1回ではなく2回とカウントします。
剰余演算をたくさん使っているときなどで、予想以上にコードサイズが大きくなってしまった場合など、定数を変数に代入することによってコードサイズの削減効果が期待できそうです。
とはいっても、せいぜい数10バイト程度かもしれませんが。