Unity5-ABSystem(五):AssetBundle内存

2023-05-16

  • AssetBundle内存占用
    • 建议
  • 实测
    • www加载实测
    • LoadFromFile加载实测
  • 建议

AssetBundle内存占用

  先上图,Don’t panic。
AssetBundle内存
  我们从AssetBundle中加载资源一般会经过三个步骤:

  1. www、LoadFromFile、LoadFromMemory等接口加载AssetBundle本身。
  2. 通过AssetBundle.LoadAsset()等接口从AssetBundle中加载资源。
  3. 对于GameObject类资源,还需通过GameObject.Instantiate()创建clone。

  这几个步骤,都会产生内存分配,并且分别对应了图中不同颜色的部分。而图的左边已经写出了产生内存分配的接口,右边则标明了释放内存的方法。
  接下来详细看看每部分的含义。
    

  • 黑色部分:www类本身占用内存,通过www接口加载AssetBundle才会有这部分内存,www对象保留了一份对WebStream数据(粉色部分)的引用。使用www =null 或者 www.dispose()释放。其中www.dispose()会立即释放,而www = null会等待垃圾回收。释放www后WebStream的引用计数会相应减一。

  • 橙色部分:官方称为WebStream数据,是数据真正的存储区域。当AssetBundle被加载进来后,这部分内存就被分配了。它包含3个内容:压缩后的AssetBundle本身、解压后的资源以及一个解压缓冲区(图绿)。无论www(黑色部分)还是后面会提到的AssetBundle对象(粉色部分),都只是有一个结构指向了WebStream数据,从而能对外部提供操作真正资源数据的方法。而当www对象和AssetBundle对象释放时,WebStream数据的引用计数也会相应减1。当WebStream数据引用计数为0时,系统会自动释放。但为了不频繁地开辟和销毁解压Buffer,其中绿色Decompression解压缓冲区Unity会至少保留一份。例如同时加载3个AssetBundle时,系统会生成3个Decompression Buffer,当解压完成后,系统会销毁两个。

  • 粉色部分:AssetBundle对象,引用了橙色WebStream数据部分,并提供了从WebStream数据中加载资源的接口。通过AssetBundle.Unload(bool unloadAllLoadedObjects)释放。如果调用AssetBundle.Unload(false),将释放AssetBundle对象本身,其对WebStream引用也将减少,从而可能引起WebStream释放,我们也就无法再通过接口或依赖关系从该AssetBundle加载资源。但已加载的资源还可以正常使用。如果调用的是AssetBundle.Unload(true),不仅会释放WebStream部分,所有被加载出来的资源将被释放。无论true或false,AssetBundle.Unload()都将销毁AssetBundle,销毁后调用该AssetBundle对象的任何方法都不会生效或产生报错,也就是说这个接口只能被调用一次,不能先调用unload(false)再调用unload(true)。

  • 红色部分:上图中红色部分不是非常清楚,我们换一张图:
    这里写图片描述
      这里紫色区域”AssetBundle文件内存镜像”就是上面的WebStream和www(黑橙)部分,虚线里的资源就是从AssetBundle加载出来的原始资源了,也属于WebStream范围,我们不再讨论。
      而绿色实线内的资源(对应第一张图红色部分),也就是就是我们通过Instantiate()创建的GameObject所包含的资源。这些包含的资源又根据类型,与AssetBundle原始资源(WebStream资源部分)有不同的关系。有些如Texture、shader资源,我们通常只是使用,并不会对其做出改动,所以仅仅是引用关系;而每个GameObject都是特殊的,所以是完全复制了一份;至于Mesh和Material,则是引用+复制的关系。

建议

  • www加载完毕后调用www.dispose()或www = null。
  • 对于shader、通用图集等常驻且需要保留依赖关系的资源,在合适时机加载进来,不调用AssetBundle.Unload()接口。
  • 其他根据不同使用情况,选择AssetBundle.Unload()策略。
    • 对于界面等存在明确生命周期,又可能动态加载的资源,在生命周期结束后调用AssetBundle.Unload(true),将全部资源一起释放。
    • 对于加载完后不再需要主动和被动依赖加载的资源,在加载完成后调用AssetBundel.Unload(false),立即释放掉AssetBundle资源,当资源使用完毕,代用Resources.UnloadAsset()或Resources.UnloadUnusedAssets()释放资源内存。
  • Resources.UnloadUnusedAssets()有较大消耗,尽量减少调用次数。
  • 不能调用AssetBundle.Unload(false)后再调用AssetBundle.Unload(true).
  • 不再使用的GameObject直接Destroy即可。

实测

  以上图片和解释来自于官方资料总结,但从加载接口可以看到是Unity5.3之前的版本,而在Unity5.3.4中是否真的如上面所言,我们仍需要“眼见为实”。毕竟没有亲测都是不可信的。
  测试使用window平台,CPU i5-4750 3.2GHZ。从StreamingAsset下加载,测试时内存存在0.1M波动,但多次测试结果非常稳定。而加载耗时波动较大,不过不影响结论。
  测试过程为:启动空的场景,先加载AssetBundle,再调用LoadAllAssets加载全部资源。在这个过程中,通过profile查看内存。
  测试包含不压缩、LZMA压缩、LZ4压缩三种格式,压缩相关在Unity5-ABSystem(一):AssetBundle原理 中有解释。
  备注:unload(false)和unload(true)在一次测试中不能同时调用,所以其实是两次测试结果。由于表格显示关系,不要理解成unload(false)一次内存下降,unload(true)一次内存下降。例如下表第一行,调用前是203.3M,调用unload(true)直接降到37.4M,下降165.9M,但表格上标记(-82.1),仅仅是因为不想建立两个表格。

www加载实测

  使用www方式异步加载结果如下:

格式ab
大小
启动
内存
www加载LoadAllAssetsdispose()unload(false)unload(true)加载ab耗时加载全部耗时

压缩
81.3M37.4M121.4M(+84)203.3M(+81.9)203.3M(+0)119.5M(-83.8)37.4M(-82.1)99ms66ms
LZMA44.9M37.4M117.3M(+79.9)199.2M(+81.9)199.2M(+0)1195M(-79.7)37.4M(-82.1)3377ms119ms
LZ471.8M37.4M111.6(+74.2)193.5M(+81.9)193.5M(+0)119.4M(-74.1)37.4(-82)99.7ms176ms

  可以看到,使用www加载AssetBundle时,内存均有比未压缩之前ab包稍大的上涨,此时占用1倍AssetBundle大小内存。猜测这里www将整个AssetBundle原始文件均载入了内存,从加载耗时来看,如果是LZMA,还进行了3秒多的解压。这里不压缩居然内存涨幅最大,不知道www暗地里做了什么神奇的事情。
  接着加载所有资源,非常整齐地都增长了81.9M。这部分就是我们希望使用的资源。但此时内存占用是我们资源的两倍左右。
  测试中遇到比较奇怪的是,无论www.dispose或www = null是否调用,unload(false)均能释放WebStream数据内存,也就是上表中unload(false)减少部分。而调用www.dispose和www = null ,内存无明显变化。也就是并不需要释放www对WebStream的引用或www根本未引用WebStream。
  与官方大佬描述不符,感到十分惶恐,贴出原书压压惊。
这里写图片描述
  调用AssetBundle.Unload(true)之后,内存回到启动值。
  最后,不压缩的AssetBundle加载资源最快,成绩为82M/66ms,LZMA即使已经被解压过了,加载时间仍然接近不压缩的两倍,而LZ4因为加载时解压,加载时间接近不压缩的三倍。

LoadFromFile加载实测

  使用LoadFromFile和LoadFromFileAsync接口加载,除了异步时间以外,其余差异不大,以LoadFromFile为例,测试结果如下。

格式ab
大小
启动
内存
LoadFromFileLoadAllAssetsunload(false)unload(true)加载ab耗时加载全部耗时

压缩
81.3M38.5M38.5M(+0)120.5M(+82)120.5M(+0)38.5M(-82)1.3ms70.7ms
LZMA44.9M38.5M118.5M(+80)200.4M(+81.9)120.5M(-79.9)38.5M(-82)3312ms116ms
LZ471.8M38.5M38.5(+0)120.5M(+82)120.5M(+0)38.5(-82)1.2ms179ms

  其中LZMA内存表现与www加载结果相近,最终仍然是AssetBundle本身+所有资源两倍内存,应该是它需要立即全部解压导致。而不压缩和LZ4格式,在加载AssetBundle时没有带来任何内存和时间上的额外开销,只有加载全部资源时,有资源内存的占用。同时对于这两种格式,调用unload(false)也没有任何效果,因为本身就从未分配过这部分内存。

建议

  • 无论使用何种方式压缩AssetBundle,均使用AssetBundle.LoadFromFile和AssetBundle.LoadFromFileAsync接口加载AssetBundle。避免使用www加载。
  • 避免使用LZMA压缩,有较长的解压时间和两倍实际资源的内存占用,尽量使用LZ4压缩(需要升级5.3或更高)。
  • 如果使用LZ4或不压缩包体过大,可以自己再对AssetBundle进行压缩,首次进入游戏时解压。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity5-ABSystem(五):AssetBundle内存 的相关文章

  • Java基础之集合框架--Collections工具类之max()方法

    max 方法一个参数的源码 xff1a public static lt T extends Object amp Comparable lt super T gt gt T max Collection lt extends T gt c
  • python创建一个txt文件

    创建一个txt文件 xff0c 文件名为mytxtfile 并向文件写入msg 注意文件的路径不要错 xff0c 还有文件的格式 创建一个txt文件 xff0c 文件名为mytxtfile 并向文件写入msg def text create
  • Android--Jetpack的使用(一)

    目录 1 ViewModel 2 ViewModel 43 LiveData 3 ViewModel 43 LiveData 43 dataBinding 4 ViewModel 43 SavedStateHandle 43 LiveDat
  • Git 常用命令

    一 Git常用命令 1 配置用户名 xff08 上传代码的用户名 xff09 xff1a git config global user name 34 ljs 34 2 配置用户邮箱 xff08 其他作者联系你的邮箱 xff09 xff1a
  • 游戏开发图书推荐--我读过的技术经典图书

    很多同学问我学游戏开发应该看些什么书 xff0c 我在这里抛砖引玉 xff0c 给一份推荐表 xff0c 希望大家共同提高 由于本人英文不太好 xff0c 推荐的大部书籍都是国人编写的 xff0c 有些经典的外文图书可能是翻译不好 xff0
  • Git中使用.gitignore忽略文件的推送

    1 简介 在使用Git管理自己的代码版本时 xff0c 由于编译生成的中间文件 xff0c Git使用SHA 1算法来对文件进行加密 xff0c 进而得出来一个40位的十六进制加密字符串 325525d8b1f67b5ddd37956a8a
  • AFNetWorking3.0处理请求头和请求内容

    今天要处理用户的相关信息 xff0c 需要在HTTP请求中添加请求头 xff0c 网上大部分资料都是针对AFNetWorking2 0的 xff0c 我用3 0版本实现了相关功能 xff0c 见下面代码 首先是请求的URL xff0c sp

随机推荐

  • chrome浏览器安装插件,提示程序包无效

    chrome浏览器安装插件的时候 xff0c 如果提示 程序包无效 xff1a CRX HEADER INVALID xff0c 导致插件安装不上去 xff0c 这个时候该怎么办呢 xff1f 通常 xff0c 这种错误在chrome浏览器
  • viewpage+radiogroup

    lt xml version 61 34 1 0 34 encoding 61 34 utf 8 34 gt lt LinearLayout xmlns android 61 34 http schemas android com apk
  • 线程执行设置超时时间

    import java util concurrent 记录 xff0c 备忘 线程执行设置超时时间 public class Main2 定义线程池 xff0c 推荐手动创建线程池 xff1a https blog csdn net LL
  • Java集合工具类Collections常用方法详解

    文章目录 1 Collections介绍2 Collections常用方法2 1 reverse 2 2 sort 2 3 swap 2 4 min 和max 2 5 copy 2 6 fill 2 7 replaceAll 2 8 shu
  • 智慧小区智能物业管理系统综合解决方案

    因为传统的办公方式效率低 xff0c 工作强度大 人们需耗费大量的时间和精力去手工处理那些繁杂 重复的工作 xff0c 而手工处理的延时和差错 xff0c 正是现代化管理中应该去除的弊端 又由于物业管理企业的启动基金不足 xff0c 多种经
  • LAMP基础搭建

    目录 一 LAMP 1 LAMP环境 2 组成部分 xff08 1 xff09 Linux xff08 平台 xff09 xff08 2 xff09 Apache xff08 前台 xff09 xff08 3 xff09 Mysq xff0
  • python获取子窗口句柄

    2022 09 17 python获取子窗口句柄 python获取窗口句柄 python获取进程 python获取电脑微信小游戏的窗口句柄 上图为按键精灵的工具 python3 xff0c 简单的获取了下句柄 xff0c 想改改内存的 xf
  • Linux多线程编程(三)-----生产者与消费者(条件变量,信号量)

    Linux多线程编程 xff08 一 xff09 xff1a http blog csdn net llzk article details 55670172 Linux多线程编程 xff08 二 xff09 xff1a http blog
  • 微策略的笔试题

    觉得在收获Offer的季节应该为自己积累些人品了 xff0c 在这里将今天的情况向所有求Offer的童鞋分享下 从上个周末开始反应迟钝的我终于有了些求Offer的感觉 xff0c 几天参加了4场面试 xff0c 基本上没觉得有很大的挑战 x
  • 线程池定时任务添加任务以及停止线程

    最近有个需求 就是项目启动的时候需要创建个线程池去执行 而且有时间周期 而且根绝不同的情况可以随时通过接口停止该线程 1首先创建个线程池 默认核心为10 static ScheduledExecutorService threadPool
  • 冰冻三尺非一日之寒-自学篇 浅谈个人学习方法

    昨晚还在看比赛 xff08 war3 xff09 xff0c 小源跑过来问我明天1024 xff0c 不写篇文章么 xff0c 想想也是 xff0c 1024这也算个热点 xff0c 赶紧来蹭蹭 xff0c 哈 xff0c 开个玩笑 上次谈
  • 【附源码】Java计算机毕业设计社区团购服务系统(程序+LW+部署)

    项目运行 环境配置 xff1a Jdk1 8 43 Tomcat7 0 43 Mysql 43 HBuilderX xff08 Webstorm也行 xff09 43 Eclispe xff08 IntelliJ IDEA Eclispe
  • iOS---iOS10适配iOS当前所有系统的远程推送

    一 iOS推送通知简介 众所周知苹果的推送通知从iOS3开始出现 每一年都会更新一些新的用法 譬如iOS7出现的Silent remote notifications 远程静默推送 iOS8出现的Category 分类 也可称之为快捷回复
  • iOS总结_UI层自我复习总结

    UI层复习笔记 在main文件中 xff0c UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil xff0c 即创建的是UIApplication类型的对象 xff0c 此对象看成是整个
  • 【疯狂造轮子-iOS】JSON转Model系列之一

    1 前言 之前一直看别人的源码 xff0c 虽然对自己提升比较大 xff0c 但毕竟不是自己写的 xff0c 很容易遗忘 这段时间准备自己造一些轮子 xff0c 主要目的还是为了提升自身实力 xff0c 总不能一遇到问题就Google 之前
  • 解决fastboot 刷 system.img 尺寸限制问题

    fastboot S xxxM flash system system img 其中 S 后面为单次上传大小 C platform tools gt fastboot S 300M flash system system img sendi
  • 修改Gnome Terminal窗口的默认大小

    修改Gnome Terminal窗口的默认大小 以前一直比较别扭的是 xff0c Gnome Terminal窗口打开时总那么小 曾经找半天也不知道在哪里改 xff0c 甚至在官方论坛里也没查到 今天偶然间想到那个Preferred App
  • 前端基础练习题

    变量命名规则 xff1a 1 只能由字母 数字 下划线 美元符号组成 xff0c 并且不能以数字开头 2 变量命名要有意义 xff0c 杜绝a01 b0046 3 变量遵循小驼峰规则 第一个单词全小写 xff0c 从第二个单词开始 xff0
  • Unity5-ABSystem(三):AssetBundle加载

    Unity特殊路径 ResourcesStreamingAssetsPathPersistentDataPathDataPath 同步加载 核心函数安卓平台下不能同步加载问题示例 异步加载 核心函数示例WWW异步加载 资源加载 核心函数 加
  • Unity5-ABSystem(五):AssetBundle内存

    AssetBundle内存占用 建议 实测 www加载实测LoadFromFile加载实测 建议 AssetBundle内存占用 先上图 xff0c Don t panic 我们从AssetBundle中加载资源一般会经过三个步骤 xff1