保有一个较长的加载时间的心理预期,最好是,点击按键,瞬间整个场景出现,毕竟轻量应用场景不是重型游戏。针对这种需求,我们需要对资源加载做一个全面的性能排查与优化。
Steps
必要的。所以在我的优化工作中,我首先对整个系统做了较为完整的 profile. 我大致将整个资源加载部分逻辑分成了
自顶向下的三层:
meshrender 层:整个场景存在若干个 meshrender,该层级统计各个 meshrender 的加载时间
resource 层:每个meshrender 依赖若干资源:mesh, material, skin/animation 等等
detailed resource 层:对每个 resource 的详尽的分部统计,不同的 resource 步骤也不同
MeshRender
Mesh Material Skin 各占一部分,同时图片的加载已经使用了异步线程加载方式,故不统计在总时间内(加载图的子
线程在主加载线程完成任务之前就已经完成结束)。从下表数据看,Mesh 与 Material 均占较大部分的比例,所以在下面
detailed 层,专门针对这两个部分继续剖析。
- | Img Load(Async | Mesh | Material | Skin | Others | Total |
---|---|---|---|---|---|---|
Current | 31.07 | 40.85 | 101.70 | 8.27 | 3.04 | 153.86 |
Detailed
数据从文件中读取到内存,并没有发现其他可能浪费时间的耗时操作,逻辑上也比较简单,故结论是无优化空间。
创建与初始化,shader 的加载以及解析,启动异步读图线程等等。具体的耗时分布如下表所示。
- | Get AbsPath | Material Asset | Shader | Async load imgs | Others | Total |
---|---|---|---|---|---|---|
Current | 1.38 | 1.77 | 8.20 | 1.71 | 1.10 | 14.15 |
探究其逻辑发现两点
shader 文件读取存在一次多余的 copy
其中有一个超过20个 case 的 switch 语句
使用数据指针代替原有的 在传递时几乎没有损耗
使用查表的方式替代 switch-case 语句,提高性能同时也提升代码质量,减少圈复杂度,同时更便于维护和更新
优化以后的数据如下表
- | Get AbsPath | Material Asset | Shader | Async load imgs | Others | Total |
---|---|---|---|---|---|---|
Current | 1.38 | 1.77 | 8.20 | 1.71 | 1.10 | 14.15 |
Optimize | 1.52 | 1.85 | 7.44 | 1.28 | 0.52 | 12.61 |
总结
最后我们来看一下总体的性能提升情况
- | Img Load(Async | Mesh | Material | Skin | Others | Total |
---|---|---|---|---|---|---|
Current | 31.07 | 40.85 | 101.70 | 8.27 | 3.04 | 153.86 |
Optimize | 33.62 | 36.40 | 80.81 | 6.88 | 3.28 | 127.37 |
Performance of resource loading
Mesh Material Skin Others
before opt xxxxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx|xxx|x|
after opt xxxxxxxxxxxx|xxxxxxxxxxxxxxxxxxxxxxxxxxx|xx|x|