Flashにおけるメモリ管理

flash.sampler っていうパッケージを最近知ったので使ってみたかっただけです。
メモリ管理のコツとかそういう tips 的なことは一切書いてないですごめんなさい。。

注) 32bit CPU での検証結果です

flash.sampler.getSize() で各クラスのサイズを調べてみました。

・出力結果 (bytes)

きっと4バイト境界でメモリがアラインされてると思うのですが、
Function の値が不思議なのと、Number が4なのはどうして?
というかそもそも flash.sampler.getSize() で戻ってくる値は一体なんなのか。。

せっかくなので他のパッケージの主要(?なクラスも測ってみました。

Sound と TextField が一桁大きいです。

次に、ユーザー定義クラスについて。
以下のようなメンバを持たないクラスのサイズを調べます。

メンバを持つ場合は?

Sprite型のメンバを持っていても 416 とは返ってきません。
この場合、保持するデータ型自体のサイズではなく参照のサイズが加算されています。
なんとなくわかってきました。
次はコンテナに詰め込んで試してみます。

あれ?40bytes じゃない?
trace をループの中に置いてみます。

なるほど。一要素ずつちまちまとアロケートしないってことですね。
じゃあ Vector は?

ループの長さに比例した大きな単位でメモリを確保するようになっているようです。
(Array と Vector でルールは多少違うようですが)
ユーザ定義クラスではなく、int や Number でも同様でした。
気になる人は追試してみてください。
また、要素数100万のループでアロケートの回数を数えてみると、
Array:45回
Vector:57回
と、 Vector の方がアロケートの回数自体は多いという結果に。

Vector には fixed プロパティというものがあり、コンテナの長さを固定できるようになっています。
fixed を true にするとアロケートの回数は当然インスタンス生成時の1回限りです。
この fixed の有無でたいした差は出ないという内容のエントリーを国内外でたくさん見ましたが、
何十, 何百万要素のループくらいになると、メモリのアロケートがループ後半ではあまり起きないため、
たいしたパフォーマンスの差が出なかったということなんでしょう。

また、fixed を true にすると、コンテナのサイズは “参照のサイズ×要素数” ちょうどになります。
つまり要素数100万の場合は40,000,000bytesです。
fixed を false にすると、ループ中は上述のようにまとまった塊でメモリを確保していくので、
新たなメモリを確保した瞬間にループを抜けると、必要のない領域までガメてしまうことになります。
これは結構大切な事だと思うので覚えておくといいかもしれません。

せっかくなので ByteArray でも試してみます。

これ ByteArray はページ単位で管理してるってことですかね。
ページ境界をまたいだアクセスが頻発すると大変なことになりそうです。

インデックスの 1024 にアクセスしても返される値は変わりませんでしたが、
4096 にアクセスした瞬間にまたメモリをガメてきました。
ここでおもむろに、
getSize(struct_ba[1]) や getSize(struct_ba[1024])
とするといずれも 4 が返ってくることを確認。
なるほど、ByteArray と getSize() のことがわかってきました。

次に、最初に疑問を投げた Number型 が 4 を返すことについて。
F-size さんで以下のようなエントリーを見つけました。
F-site | [AS3] プリミティブ型データとメモリ
どうやら4bytesで抱えきれない値を代入すると8bytesにリアロケートするようです。

なんと、再度小さな値を入れると4bytesにリアロケートされます。
これけっこうなコストだと思うのですが、、
Flashで大きな数値を扱うことは少ないからでしょうか、ちょっとわかりません。

他にもいろいろ調べられそうですが、今回はこの辺で。
あとはFlash本業の方に任せようと思いますw

flash.sampler パッケージを使ってオレオレプロファイラ作るのも楽しいかもしれません。

あわせて読む:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です