【Unity】5.3以降AssetBundleの各種圧縮形式のパフォーマンス比較
Unity5.3になりAssetBundleが変わりました。で、AssetBundleのパフォーマンスについても大分変化したので、そこについて検証してみようと思います。
AssetBundleの新しい設定LZ4
Unity 5.3より今までの圧縮(LZMA)と非圧縮に加えて「LZ4」が追加されました。
LZ4はどんなものかと言えば、「ファイルサイズはLZMAよりは大きいが無圧縮よりは圧倒的に小さい」「ロード時間が無圧縮よりは長いがLZMAよりは短い」という特性を持っています。
表にすると、こんな感じです。
では、これを前提にパフォーマンスについて比較してみます。
検証方法について
比較する内容についてですが、テクスチャのロード時間を比較します。何故コレかと言えば、大体のゲームでこんな感じの事をやっているからです。
内容は解像度が「1280x1920」のスプライトを24枚ロードし、その時間を比較します。
AssetBundle(AB)からロードする方法ですが、3つのパターンで比較します。
- ABに8枚ずつ格納し、全てのスプライトを逐次ロードする(コード)
- ABに8枚ずつ格納し、全てのスプライトを一括ロードする(コード)
- ABに8枚ずつ格納、AB毎にスプライトを1枚だけロードする(コード)
- スプライト1枚含むABを24個用意し、スプライト3枚ロード(コード)
1は読込の純粋な読込速度の比較、2は1の効率化版、3はチャンク読みと通常の比較、4は各々のファイルを読んだ時のオーバーヘッドを見ています。
AssetBundleをロードするAPIは幾つかあるのですが、今回は最も効率の良いAssetBundle.LoadFromFileを使用します。
結果。無圧縮でかい、LZMA遅い、LZ4はその間
結果はこんな感じです。予想以上に分かりやすい差が出ました。
総じて「1つのAssetBundleから逐次ロード」より「1つのAssetBundleから一括ロード」の方が速く動作しています。
特にLZMAの方は解凍コストが高いらしく、AssetBundleから1つのスプライトを抽出するのにかなり高いコストを支払っています。このコストは傾向としてWWWと大体同じ感じっぽいので、WWWでAssetBundleを引っ張ってきているプロジェクトは、圧縮形式に関係なくかなりパフォーマンス的に対価を支払っていそうです。
全体を比較すると、
まず、非圧縮とLZMAのAssetBundleのファイルサイズ差が大体7倍近くあるのが目につきます。今まではLoadFromCacheOrDownloadを実行すると非圧縮に解凍していたので、アプリサイズを超圧迫していましたが、これは納得です。
逆にローディングのパフォーマンスですが、LZMAはLZ4と無圧縮と比較してかなり時間がかかっています。特に1AssetBundle1スプライトで一つロードするよりも無圧縮のAssetBundleに纏めた物を全部ロードした方が高速というのは中々に興味深い話です。
LZ4は割と良い間を取っています。ファイルサイズがLZMAよりも50%程大きいですが無圧縮よりはかなり小さく、ロード時間は無圧縮と比較して1.5倍程度ですがLZMAよりもかなり短いと、落ち着いています。
キャッシュとLZ4変換について
現在はLoadFromCacheOrDownloadを行った時にCaching.compressionEnabledがtrueだと、LZMAをLZ4へ再圧縮してくれるみたいです。
上手く使うと、ダウンロードは最軽量のサイズでダウンロードしLZ4の速度で読み込めて、アプリサイズもLZ4並といった使い方が出来そうです。
ただ、まぁ、相変わらず*1起動時にキャッシュをチェックしてる感じの動きをするので、AssetBundleの数が膨大になる場合は自前でAssetBundleを管理運用する方が良いかもしれません。
もしくはLZMAをローカルで保持しておいて、必要な物だけローカルからLZMAをダウンロードしてLZ4としてキャッシュする方法。まぁ、これをするならLZ4を自前圧縮してネイティブプラグインで解凍・管理する方が理に適ってるかもしれませんが。
感想
LZ4対応や圧縮AssetBundleに対してLoadFromFileが使えるようになった事で、かなりAssetBundleを運用する上での選択肢が広がってる感じです。
ついでにUnityWebRequestと組み合わせれば、殆どmonoのヒープやLoadFromCacheOrDownloadを使わずAssetBundleをダウンロード→ロードの運用が出来るんじゃないかなって気がします。
各AssetBundleは使うと便利なタイミングが若干異なりますが、BuildPipeline的に異なる圧縮形式をビルドするのは面倒臭い所があるので、まぁケースバイケースで。
関連情報
*1:キャッシュ期限が過ぎたAssetBundleの破棄やサイズをチェックする為?