【厚积薄发】Android 10系统下的PSS数值统计不准

1)Android 10系统下的PSS数值统计不准
​2)Memory Profiler中的类型内存大小计算
3)Addressable加载Bytes文件在手机上报错
4)使用SBP打Bundle,如何读取AssetBundleManifest
5)GameObject如何释放从Bundle中加载的Asset


这是第215篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)

Memory

Q:从下图测试的结果来看,Android 10.0的PSS的内存值是平的,没有任何变化。但如果用Android 9.0版本的测试机测试,数值就是正常。初步猜测这个就是Android 10的内存反馈,但到底是否为Bug还不确定。有遇到相同情况的小伙伴吗?

A:同样被Android 10坑了,来回答一下原因:

ActivityManager的

public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)

变了。

/** 

As of {@link android.os.Build.VERSION_CODES#Q Android Q}, for regular apps this method * will only return information about the memory info for the processes running as the * caller's uid; no other process memory info is available and will be zero. * Also of {@link android.os.Build.VERSION_CODES#Q Android Q} the sample rate allowed * by this API is significantly limited, if called faster the limit you will receive the * same data as the previous call.

*/

查了一下安卓源码,这个值居然默认是5分钟,也就是说5分钟更新一次,所以看起来是平的。

PS:可以直接用这个命令看到这个值:

$ dumpsys activity settings

memory_info_throttle_time=300000

感谢littlesome@UWA问答社区提供了回答

Memory

Q:在Unity 2019.3.1f1的版本中使用Memory Profiler使用Preview 0.2.5的版本,在进行分析时,看到Matrix4x4结构是值类型,但是大小只占用了64字节,即444的大小,类型中定义的只读属性在编译后自动生成的Backingfield没有占用空间?还是底层实现采取了什么机制?

同样,针对引用类型,大小计算是怎么样一种方式?希望研究过Memory Profiler源码的大佬帮忙解答下。

A1:初步怀疑这里的只读属性是在get方法中直接通过类似实时计算、new的方式(即方法返回值的方式)实现的(不缓存)——此时在IL层面不会生成Backingfield(不占用内存)。

感谢Wayland@UWA问答社区提供了回答

A2:你可以反编译一下Matrix4x4,会发现就像你怀疑的那样都是实时计算的。

其中一个原因就是:例如我们处理Instancing的时候,往往要准备一个Matrix4x4[],这种数据结构保证矩阵有效数据是最紧凑的,可以一次性发送给GPU,做到最优化。

感谢黄程@UWA问答社区提供了回答

Addressable

Q:利用Assdressable加载二进制文件,手机上报错。编辑器下这样加载var loadOp = Addressables.LoadAssetAsync(tablePath);但是打包后手机上报错:

[SYS_ERROR]: Exception encountered in operation Resource(table_c#_assets_all_1f4a006d39ea75ca48efd21a455601c1.bundle): RemoteAssetBundleProvider unable to load from url jar:file:///data/app/com.funplus.kingsgroup.wod-zHxfbteVjnHJeanZLbCPog==/base.apk!/assets/aa/Android/Android/table_c, result=‘HTTP/1.1 404 Not Found’.
UnityEngine.AsyncOperation:InvokeCompletionEvent()

A:先解压看一下APK里,确定Table_c这个Bundle是否真的打进去了。

补充:

Bundle名:

table_c#_assets_all_1f4a006d39ea75ca48efd21a455601c1.bundle

URL名:

jar:file:///data/app/com.funplus.kingsgroup.wod-zHxfbteVjnHJeanZLbCPog==/base.apk!/assets/aa/Android/Android/table_c

看上去是#被截断了,应该是URL规则中不允许使用这个符号,把Bundle改个名字吧。

感谢黄程@UWA问答社区提供了回答

AssetBundle

Q:升级到Unity 2019之后,使用BuildPipeline.BuildAssetBundles方法打Bundle变得很慢。我们发现Unity新推出的Scriptable Build Pipeline有更快的打包速度(1个小时降为15分钟),但是作为兼容之前AssetbundleManifest的新类型CompatibilityAssetbundleManifest并没有被打成Bundle,而是一个Yaml格式的文件:

想请教一下在用Scriptable Build Pipeline的伙伴,这里是如何处理的?或者说资源的依赖关系是如何存储的。

PS:没用Addressable,因为是线上运行项目,资源的路径都配在了Excel里,需要改的地方太多。

A:使用AssetDatabase.CreateAsset保存CompatibilityAssetBundleManifest,再单独打着一个Bundle。

感谢张斌@UWA问答社区提供了回答

AssetBundle

Q:从Bundle中加载的资源,如果是Texture、Material之类,用Resources.UnloadAsset() 就能直接把它从内存中释放。

如果是GameObject ,不能对它调用Resources.UnloadAsset。目前的做法是,只执行了Destroy,等到内存上涨到一定程度,调用Resources.UnloadUnusedAssets(),来释放它们。

总感觉很亏,请问有没有办法,可以像对付Texture那样,直接释放GameObject?

A1:一般不用主动释放。

Bundle里面一加载是一家子的,比如加载GameObject,会自动带上引用的材质,引用的材质又会自动带上引用的贴图和Shader等等。

要干净地释放,你要让这一家子都整整齐齐的,非常麻烦。建议是直接用Bundle.Unload(true) 实现完整释放。

感谢欧月松@UWA问答社区提供了回答

A2:DestroyImmediate(object,true);

感谢谢谢@UWA问答社区提供了回答

A3:测试了一下DestroyImmediate(object,true),发现它并不释放引用的材质和贴图,哪怕这个材质和贴图仅仅被该GameObject一个人调用,不过感觉还是需要调用这个函数,释放一点总比什么都不释放要好。

感谢题主李宏亮@UWA问答社区提供了回答

*

今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com

官方技术QQ群:793972859(原群已满员)

你可能感兴趣的:(memory)