关于LZMA和LZ4压缩的疑惑解析

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

UWA QQ群:465082844(仅限技术交流)

AssetBundle

Q:昨天看到问答社区上UWA_Xin对LZMA和LZ4压缩的解答,在此有些疑问。

关于LZMA和LZ4压缩的疑惑解析_第1张图片
image

问题1:我在网上看到这篇文章(https://www.cnblogs.com/AaronBlogs/p/6837828.html)提到,AssetBundle在加载的时候需要扩展出来一块内存来解压,我觉得解压这个说法是有问题的,因为如果都被解压出来了,就不需要LoadAsset了。资源都已经在内存中了,而我们测试的时候,用LZ4要比LZMA内存小了快200MB,所以我觉得LZMA是在加载AssetBundle的时候会把资源都解压出来的,并不是只是多了一个LZ4的AssetBundle大小。

我看了UWA关于《移动游戏加载性能和内存管理全解》的视频讲解,****上面说用LZMA压缩的时候LoadFromCache在第一次读取时会很耗时,是由于Cache会把AssetBundle包重新压缩成LZ4使得第二次读取的时候速度加快,所以上面截图说的LZMA会把AssetBundle再压缩成LZ4其实只是针对的LoadFromCache这个接口而言的,而不是针对的LoadFromFile,猜想LoadFromFile是直接从硬盘读取的,不存在Cache的操作,所以上图是不是说得有误?

问题2:LZ4压缩AssetBundle包是按照Chunk来读取的,那么在解压AssetBundle包的时候一般是在读取AssetBundle的头文件信息,那么解压AssetBundle包的时候LZ4的Chunk优势是没有优势的吗?加载AssetBundle的时候LZMA和LZ4的速度应该一样的吗?(如果LZMA是完全解压整个包体就另当别论了)。

UWA:问题1解答:我觉得解压这个说法是有问题的,因为如果都被解压出来了,就不需要Loadasset了,资源都已经在内存中了。

解压和加载是两回事的。题主给的文章里说的解压是针对WWW接口的,WWW加载LZMA,是需要解压进内存的,但这个只能算是二进制流,相当于是未压缩的AssetBundle,后续的LoadAsset依然是要做的…但第二次调用的LoadFromCache就不用了,因为磁盘的Cache里已经是“未压缩的AssetBundle”了。

上面截图说的LZMA会把AssetBundle再压缩成LZ4,这不仅仅是针对LoadFromCache的,LoadFromFile也是一样,只是LoadFromFile是不Cache到磁盘的,完全在内存中进行,所以这个接口加载LZMA的AssetBundle一样会变很慢,同时造成内存的明显上涨。

问题2解答:根据问题1的解释,LZ4相比LZMA在加载的时候还是有很大优势的。但最后还是留下了一个疑问,而我们测试的时候用LZ4,要比LZMA内存小了快200MB,所以我觉得LZMA是在加载AB的时候会把资源都解压出来的,并不是只是多了一个LZ4的大小。经过这边的一些测试,这个内存的差异确实更加接近未压缩的的大小,而不是LZ4的大小。

所以题主可不可以再多做一步,就是把用到的打成未压缩的,看看是不是确实接近200MB呢?

该回答由UWA提供,欢迎大家转至社区进行进一步交流


粒子系统

Q:粒子系统是否能够支持****GPU Instancing?做了些例子都没能看到****GPU Instancing生效。

UWA:Unity 2018已经支持Particle System的GPU Instancing了,不过必须是Mesh模式的,具体可以看这个文档:

https://docs.unity3d.com/Manual/PartSysInstancing.html

https://answer.uwa4d.com/question/5afe9bb56b104d27ac3aadaa


加载

Q:如果我代码中声明了个Texture然后加载了图片,是不是无论我的这个Component销毁或者这个GameObejct销毁,都不会释放这个Texture的内存?必须在OnDestroy 里销毁才可以呢?

A1:因为某张Texture的内存只会有一份,但是可能会被多个对象引用,所以不可能跟随Component或GameObject的销毁而销毁。

估计是考虑到资源管理(某张Texture当前帧不用了,可能过两帧又要用了,而这部分IO消耗不小,所以需要开发者自行管理),所以这部分并没有走GC。使用Resources.UnloadAsset卸载Texture。

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

A2:Component销毁 或者 Gameobject销毁都不会卸掉new出来的Texture的内存,需要调用Object.Destroy()方法,把new出来的Texture对象作为参数传进去,然后查看Profiler就可以验证。

感谢上午八点@UWA问答社区提供了回答


编辑器

Q:有办法临时屏蔽掉脚本的一些编译Warning吗?比如 The variable 'xxx' is declared but never used之类的。

A1:File->Build Settings->Player Settings->Logging

A2:强烈建议题主修掉这些Warning,而不是屏蔽掉它们。我觉得,程序保证代码没有Bug是底线,没有Warning是合格线……尤其是你举例的这种,虽然编译器会帮你做优化,但是保不齐什么时候写其他逻辑的时候会坑了你。

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


动画

Q:游戏在运行一段时间后,出现了一个CPU高占用函数:Director.ProcessPlaySateChanges ,它产生了3616ms的耗时,请问这是怎么产生的,确认C#代码中无此方法调用,有人遇到过这个问题吗?(版本Unity 5.6.5p3)

关于LZMA和LZ4压缩的疑惑解析_第2张图片
image

A:经排查已找到原因,是UI中的一个播放动画前调用了函数 Animator.Rebind()导致的。

感谢张剑@UWA问答社区提供了问题和回答


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

你可能感兴趣的:(关于LZMA和LZ4压缩的疑惑解析)