移动端性能优化
移动端性能优化
00 前言
01 检测工具
01.1 Android GPU Inspector
google出品的GPU性能检测工具(包含部分CPU数据, 需要详细的CPU数据直接使用Android Studio). 本质上是调用了各个厂商的GPU分析工具. 但支持的设备仍旧有限. 如下表(截止2023年12月5日).
| 设备名称 | GPU 名称 |
|---|---|
| Google Pixel 4(标准版和 XL) | Qualcomm® AdrenoTM 640 |
| Google Pixel 4a | Qualcomm® AdrenoTM 618 |
| Google Pixel 4a 5G | Qualcomm® AdrenoTM 620 |
| Google Pixel 5 | Qualcomm® AdrenoTM 620 |
| Google Pixel 6(标准版和 Pro) | Arm® MaliTM G78 接口 |
| Google Pixel 6a | Arm® MaliTM G78 接口 |
| Google Pixel 7(标准版和 Pro) | Arm® MaliTM G710 |
| 三星 Galaxy S10 系列 | Qualcomm® AdrenoTM 640 和 Arm® MaliTM G76 |
| 三星 Galaxy S20 系列 | Qualcomm® AdrenoTM 650 和 Arm® MaliTM G77 |
| 三星 Galaxy Note 10 系列 | Qualcomm® AdrenoTM 640 和 Arm® MaliTM G76 |
| 三星 Galaxy Note 20 系列 | Qualcomm® AdrenoTM 650 和 Arm® MaliTM G77 |
| 三星 Galaxy S21 系列 | Qualcomm® AdrenoTM 660 和 Arm® MaliTM G78 |
| OPPO Find X3 Pro | Qualcomm® AdrenoTM 660 |
| OPPO Find X3 | Qualcomm® AdrenoTM 650 |
| OPPO Reno 6 Pro+ | Qualcomm® AdrenoTM 650 |
| 一加 9R | Qualcomm® AdrenoTM 650 |
同时, 即便是获取基本数据, 仍旧需要apk包本身为debuggable, 越狱+全局debuggable无效.
01.2 Snapdragon Profiler
建议使用2021.2版, 该版本之后的Snapdragon Profiler取消了Power部分的指标. 注意, 安装2021.2版时会需要gtk-sharp-2.12.45, 而安装程序给出的下载地址疑似失效. 可以尝试使用下面的下载地址:
顾名思义, 这款分析工具主要针对搭载Snapdragon系列SoC的手机(实测, Mali). 该Profiler可以截帧. 仅获取CPU/GPU数据时apk包无需debuggable, 但如果需要截帧, 还是需要设置debuggable. 优点是截帧后可以看到大部分渲染流程的性能参数. 缺点是, 卡/慢/容易奔溃.
01.3 PVRCarbon
PVR系列开发工具之一, 与高通不同, 其性能数据和截帧工具并不整合在一起, PVRTune是性能数据工具, PVRCarbon是截帧工具. 相比Snapdragon Profiler, PVRCarbon可以支持local模拟渲染, 即可以通过PC本机的显卡去模拟渲染结果, 速度更快. 缺点是没有每个渲染步骤本身的数据.
01.4 Arm Mobile Studio
Arm移动端开发工具套件, 根据说明文档, 同样可以获取到性能数据. 但是否可以截帧并分析待验证(因为该款分析工具没有真正实践使用过).
适用于maliGPU.
02 基础概念
02.1 内存带宽-发热
移动端目前使用的LPDDR4X是一种低功耗的DDR4内存。它同样使用双倍数据率技术,但与标准DDR4相比,它在功耗方面进行了优化。LPDDR4X通常也支持多通道传输,比如四通道。
对于一个四通道16位(每通道)的LPDDR4X内存,其总线宽度将是64位(16位 x 4通道)。如果时钟频率是2133 MHz,我们可以使用以下公式来计算带宽:
1
2
总线宽度(位)= 单通道位数 × 通道数
带宽(GB/s)= 时钟频率(MHz)× 数据倍率(DDR即双倍数据率) × 总线宽度(位)/ 8 / 1,000
在这个例子中,数据倍率是2,因为LPDDR4X也是在每个时钟周期的上升沿和下降沿传输数据。
1
带宽(GB/s)= 2133 MHz × 2 × 64位 / 8 / 1,000
将这些数字代入计算:
1
2
3
4
带宽(GB/s)= 2133 × 2 × 64 / 8 / 1,000
带宽(GB/s)= 273024 / 8 / 1,000
带宽(GB/s)= 34128 / 1,000
带宽(GB/s)= 34.128
所以,一个四通道16位的LPDDR4X内存在2133 MHz的频率下,大约可以提供17.064 GB/s的带宽。这是理论上的最大带宽,实际性能可能会因系统架构和其他因素而有所不同。
对于一个八通道16位(每通道)的LPDDR4X内存,其总线宽度将是128位(16位 x 8通道)。如果时钟频率是2133 MHz,则类似的有
1
2
3
4
带宽(GB/s)= 2133 × 2 × 128 / 8 / 1,000
带宽(GB/s)= 546048 / 8 / 1,000
带宽(GB/s)= 68256 / 1,000
带宽(GB/s)= 68.256
与wiki数据68.26GB/s近似. 计算存储这类指标时, 芯片厂家默认按照1000来进行换算.
通常, 为了考虑散热的因素, 所有的性能指标建议按照67%来进行评估. 之后不再赘述.
x00 全屏渲染所需带宽
要计算渲染一屏所消耗的带宽,我们需要知道屏幕的颜色深度(每个像素的比特数)。例如,如果我们假设屏幕使用的是32位色(这意味着每个像素使用32比特即4字节来表示颜色),我们可以用以下公式计算渲染一屏像素所需的带宽:
1
带宽 (bytes) = 屏幕宽 (pixels) × 屏幕高 (pixels) × 颜色深度 (bytes/pixel)
同时涉及半透明混合的OverDraw还会回读一次屏幕缓冲区的数据, 这个结果需要乘以2.
1
带宽 (bytes) = 屏幕宽 (pixels) × 屏幕高 (pixels) × 颜色深度 (bytes/pixel) * 2
最终的Blit还会写入深度, 深度一般为16 bit, 即2 bytes/pixel.
1
最终Blit的带宽 = 屏幕宽 (pixels) × 屏幕高 (pixels) × (颜色深度 (bytes/pixel) + 深度图深度(bytes/pixel)
注意:
- 这里的结果是每一帧的消耗;
- 带宽还需要减去纹理, 顶点, 程序数据, Prefab数据, 粒子系统数据, 材质数据等等的带宽消耗(这部分根据项目不同而不同);
- 一次全屏后处理等于一次全屏OverDraw的带宽消耗.
02.2 填充率-帧率
像素填充率指的是GPU在一秒内可以渲染到屏幕并写入显示存储器的像素数量,纹理填充率指的是GPU可以在一秒内映射到像素的纹理贴图元素(纹理元素)的数量[1]。 像素填充率以百万像素/秒(早期)或千兆像素/秒为单位,透过将图形处理器单元的时钟频率乘以光栅输出单元(ROP)的数量来获得。 纹理填充率以百万纹素/秒(早期)或千兆纹素/秒为单位,将图形处理单元的时钟频率乘以纹理映射单元(TMU)的数量来获得纹理填充率。然而,关于如何计算和报告填充率没有完全一致的意见。其他可能的方法是:将像素流水线的数量乘以时钟频率。[2]这些乘法的结果为理论数字,实际填充率会被许多其它因素影响(例如显示存储器的规格)。过去,填充率被ATI和NVIDIA等显卡制造商用作性能指针,但是随着图形应用程序瓶颈的转移,填充率作为衡量性能的重要性下降了,统一着色器处理单元的数量和速度越来越受到关注。[3]
当一系列场景非常复杂时,每个场景必须绘制许多像素,该场景的帧速率可能会下降。在设计图形密集型应用程序时,可以通过查看应用程序在以较低分辨率或较小视窗运行时帧速率是否显著增加来判断应用程序是否为填充单元满载(或着色器满载)。[4]
对应填充率的就是全屏OverDraw的次数.
03 实际案例
| 项目 | 信息 |
|---|---|
| 开发者 | |
| 生产商 | 富士康 |
| 系列 | Pixel |
| 首次发布 | 2019年10月15日,4年前 |
| 上市日期 | 2019年10月24日 |
| 系统芯片 | 高通骁龙855 |
| CPU | 八核(1×2.84 GHz Kryo 485 + 3×2.42 GHz Kryo 485 + 4×1.78 GHz Kryo 485) |
| GPU | Adreno 640 |
| 存储器 | 6GB LPDDR4X 4通道 16bit 2133MHz |
| 存储空间 | 64GB或128GB |
| 电池 | Pixel 4:2800 mAh |
| 显示器 | Pixel 4:5.7英寸(140 mm) FHD+P-OLED,2280×1080(19:9,444ppi)支持90Hz刷新率 |
| 项目 | Adreno 640 GPU参数 |
|---|---|
| ALUs (SIMDs, FP32) | 768 [384](MP(Multiprocessor)数为2, 单核384, 总数768) |
| On-chip graphics memory | 1024 KB |
| TMU | 12*2 [45] |
| 制造工艺 (nm) | 7 |
| 时钟频率 (MHz) | 585 - 675 |
| 内存技术 | LPDDR4X-4266 Quad-channel 16-bit (64-bit) |
| 内存带宽 | 34.1 GB/s (@ 2133 MHz) |
| 三角形处理能力 (MT/s) | ? |
| 像素填充率 (GP/s) | 9.4 |
| 纹理填充率 (GT/s) | 28.1 |
| GFLOPS (FP64) | 224.6 |
| GFLOPS (FP32) | 1036.8 |
| GFLOPS (FP16) | 2073.6 |
| Vulkan API | 1.1 [32] [26] |
| OpenGL ES | 3.2 |
| OpenVG API | 2.0 Full |
| OpenCL API | WIP (freedreno driver) |
| OpenGL API | ? |
| Direct3D API | 12 (feature level 12_1) [17] |
| 兼容的Qualcomm SoC | Snapdragon 855/855+ 和 Snapdragon 860 |
| 性能指标 | 指标数值 | 理论指标 | 实际指标(67%) |
|---|---|---|---|
| 带宽 | 34.128GB/s | 1137.6 MB/frame(30帧), 568.8 MB/frame(60帧) | 762.192 MB/frame(30帧),381.096 MB/Frame(60帧) |
| OverDraw + 全屏后处理次数 + 后处理缓存读取数 | 23.9 次/frame (30帧), 3.6 次/frame(60帧) | 16 次/frame (30帧), 2.4 次/frame(60帧) |
对于Pixel 4,其屏幕分辨率为2280×1080。如果使用32位色深,计算如下:
1
带宽 (bytes) = 2280 × 1080 × 4 bytes/pixel
1
带宽 (bytes) = 9,830,400 bytes
1
带宽 (MB) ≈ 9,830,400 bytes / (1024^2 bytes/MB) ≈ 9.37 MB
所以,渲染一个分辨率为2280×1080的屏幕,使用32位色深,大约需要9.37 MB的带宽。
同时OverDraw一般是半透明物体产生, 还会有一次全屏幕颜色(包括Alpha)的回读, 这部分消耗需要加倍
1
带宽 (MB) ≈ 9.37 MB × 2 ≈ 18.74 MB
这只是单纯从渲染一帧静态图像的数据量来计算的。如果你要计算每秒的带宽使用情况,需要乘以帧率:
1
带宽 (MB/s) ≈ 帧带宽 (MB) × 帧率 (frames/s)
例如,如果帧率分别为30帧/秒和60帧/秒,则每秒所需的带宽将是:
1
2
带宽 (MB/s) ≈ 18.74 MB/frame × 30 frames/s ≈ 562.2 MB/s
带宽 (MB/s) ≈ 18.74 MB/frame × 60 frames/s ≈ 1124.4 MB/s
这只考虑了渲染帧的带宽消耗,实际上,GPU在渲染过程中还会有额外的数据读写操作,如纹理加载、帧缓存更新等,实际的带宽需求会更高。
比如,最终的Blit的固定全屏填充消耗(包含的深度图数据, 一般为16位色深), 考虑到一般情况下(但并不绝对), 造成OverDraw的都是透明物体, 而透明物体一般不会写深度, FinalBlit的带宽消耗如下.
1
2
3
4
带宽 (bytes) = 2280 × 1080 × (4 bytes/pixel + 2 bytes/pixel) = 14,774,400 bytes
带宽 (MB) ≈ 14,774,400 bytes / (1024^2 bytes/MB) ≈ 14.09 MB
带宽 (MB/s) ≈ 14.09 MB/frame × 30 frames/s ≈ 422.7 MB/s
带宽 (MB/s) ≈ 14.09 MB/frame × 60 frames/s ≈ 845.4 MB/s
Pixel 4的每帧带宽上限是762.192MB/frame, 381.096MB/Frame,
| 条目 | 30帧 | 60帧 |
|---|---|---|
| 每帧带宽上限 | 762.192 MB | 381.096 MB |
| 最终Blit带宽 | 14.09 MB | 14.09 MB |
| 其他数据消耗,暂定300 MB | 300 MB | 300 MB |
| 剩余带宽 | 448.102 MB | 67.006 |
| 全屏OverDraw消耗(带宽限制) | 18.74 MB | 18.74 MB |
| 全屏OverDraw + 全屏后处理次数 + 后处理缓存读取数((带宽限制)) | 23.9 次 | 3.6 次 |
| 条目 | 30帧 | 60帧 |
|---|---|---|
| 每帧填充率上限 | 9.4GP/s/30=313.33MP | 156.67MP |
| 全屏一次OverDraw消耗(填充率限制) | 1080p(2.0736MP), 720p(0.9216MP) | 1080p(2.0736MP), 720p(0.9216MP) |
| 全屏OverDraw理论极限(填充率限制) | 1080p(151次), 720p(340次) | 1080p(75次), 720p(170次) |
| 全屏OverDraw实际建议(理论值*67%)(填充率限制) | 1080p(101次), 720p(227.79次) | 1080p(50次), 720p(113次) |
参考网页
Optimize game performance | Unity Blog
Games Focus: Profiling and performance optimization | Unity Blog
Unity E-Book: Optimize Your Mobile Game Performance
Unity - Manual: Profiler overview (unity3d.com)
Android Profiler | Android Studio | Android Developers
Android GPU 检查器 | Android 游戏开发 | Android Developers
Android GPU 检查器快速入门 | Android Developers
Unity合批(Batching)的限制与失败原因汇总 - 知乎 (zhihu.com)
Unity场景物体动态合批 - UWATech - 博客园 (cnblogs.com)
高通骁龙组件列表 - 维基百科,自由的百科全书 (wikipedia.org)
Snapdragon 855 Mobile Platform | Qualcomm
Pixel 4 - 维基百科,自由的百科全书 (wikipedia.org)
Overdraw概念、指标和分析工具 - 知乎 (zhihu.com)
ken48/UnityOverdrawMonitor: Overdraw profiler for Unity, shows fill rate (github.com)
移动设备渲染架构学习&优化小技巧 - 知乎 (zhihu.com)
【《Real-Time Rendering 3rd》 提炼总结】(十二) 渲染管线优化方法论:从瓶颈定位到优化策略 - 知乎 (zhihu.com)
Fixing Performance Problems - 2019.3 - Unity Learn
图形引擎实战:游戏GPU性能优化 - 知乎 (zhihu.com)
【Unity】使用Profiler进行性能分析 - 知乎 (zhihu.com)
分析 AGI 纹理数据并提升 GPU 性能 (androidweekly.io)
Unity移动端游戏性能优化简谱之 画面表现与GPU压力的权衡 - UWA问答 | 博客 | 游戏及VR应用性能优化记录分享 | 侑虎科技 (uwa4d.com)
Android Game Analysis with Arm Mobile Studio | Samsung Developers