网站首页 > 技术文章 正文
背景介绍
性能测试是 SDK 发版的重要依据,VolcRTC 的业务方对于性能指标都比较重视,对于 RTC 准入有明确的准入标准。因此我们建立了线下的性能自动化测试系统,测试过程中我们发现 VolcRTC 的内存占用较高存在较大的优化空间。某个版本 1v1 语音通话 VolcRTC 1v1 语音通话内存占用:
占用的资源 | Memory[MB] |
Android 高端机 | 17.87 |
Android 中端机 | 17.58 |
Android 低端机 | 16.06 |
iOS 高端机 | 6.19 |
iOS 中端机 | 6.52 |
iOS 低端机 | 5.73 |
为了实现内存优化,首先需要理清两个问题:
- 哪些模块消耗多少内存?
- 如何优化?
内存组成
在回答以上两个问题之前,我们先了解下内存的主要组成部分有哪些。
在 Android 系统上,内存主要分为:
下图红框部分为 VolcRTC 通话过程
- Java Heap,从 Java 代码分配的对象;通话过程中 Java 内存的分布曲线,主要呈锯齿状的周期性变化。结合 VolcRTC 的业务特点,可以知道这部分内存主要在 JNI 调用时分配临时对象,累计到一定程度后由系统的 GC 机制回收。
- Native Heap,从 C 或 C++ 代码分配的对象。这部分为 VolcRTC 主要内存占用。
- Code,用于处理代码和资源(如 dex 字节码、经过优化或编译的 dex 代码、.so 库和字体)的内存。VolcRTC 库所占用内存,但不等于动态库的包大小,主要原因在于代码段是按需分页加载的,所以部分代码不会被加载到内存。VolcRTC 是一个动态库,因此 Code 的内存也是在通话过程中主要部分。
优化方向
根据上文的初步分析,可以确定 VolcRTC 的内存占用主要分布在 Native Heap 与 Code 段。因此我们明确大体的优化方向为:
- Native 内存优化
- 动态库包体优化
内存归因分析
哪些模块如何消耗多少内存?
- 内存分配堆栈信息
- 按模块归因
Heapprofd 实现原理
- hook malloc、calloc、realloc、free 等内存分配相关的函数
- 拷贝寄存器与栈内存,存储到共享内存,用于栈回溯
- 根据堆栈信息聚类生成 Trace 文件
模块归因
VolcRTC 归因规则
VolcRTC 主要分为底层媒体引擎与上层 RTC SDK 两部分。媒体引擎的整体架构是以流水线(Pipeline)的形式组成的,每个 Pipeline 由实现不同功能的 Node 构成。我们可以根据相关的命名空间进行堆栈过滤,再根据软件分层架构进行层层归因。
纯系统堆栈
VolcRTC 引起的系统堆栈内存分配,堆栈不包含 VolcRTC 符号信息,无法按前述规则归类,需要归类到由 VolcRTC 引起的系统内存分配。
归因示例
内存分配堆栈特征一般为栈底为__pthread_start(void*),栈顶为内存存分配方法,中间为 VolcRTC 堆栈信息。根据堆栈信息,结合归因规则然后层层向上归因,形成一个树状的结构,准确分析每一个 Pipeline、每一个 Node、每一个类型的对象所占用的内存大小。
碰到的问题
Hook malloc 得到的内存大小与 Native Heap 大小不一致
malloc 向内存分配器申请的内存,跟程序运行时传入的 size 一致。
内存分配器向操作系统申请的内存按页分配,一般每页为 4K,Native Heap 统计的是这部分的内存大小。
由于内存分配器的需要反复分配与释放内存,不可避免的产生内存空隙也就是内存碎片,另外内存分配器会缓存一部分小内存块以提升内存分配效率。
语音通话内存分析
通过性能自动化测试工具,生成分析报告。基于分析报告我们绘制语音通话内存全景图,再通过全景图识别出内存占用较高的几个模块,指引优化方向。
内存优化
编译优化
包大小会直接影响到内存大小,因此优化包大小也可以有效减少内存大小。通过打开 LTO、Oz 等编译选项,结合线下性能自动化测试评估是否对性能指标有负面影响来决定需要开启的编译优化选项。编译优化后 Android 端动态库包体减少了 900KB,通话过程内存优化 850KB 左右。
按需动态分配
VolcRTC 作为一个通用功能的 SDK,对于每个特定场景会有很多冗余逻辑与功能,这些逻辑与功能都存在较多的预分配内存。对应的优化方案是:
- 合理代码组件化,将不同的功能抽象成组件做到灵活组装与按需加载,如:AI 降噪功能内置的数据和模型会占用较大的内存空间。
- 内存尽量按需动态分配。如:AEC 回声消除在不同场景下有不同的算法,需要根据实际的场景按需分配内存,减少过多的内存预分配。
设置合理的缓存大小
不合理的缓存大小也会引起不必要的内存浪费。通过内存的归因分析,结合不同场景的业务特性,设置更加合理的缓存大小,可以减少内存占用。例如:RTC 采用了 RTP 包重传机制来对抗网络丢包,为了实现重传机制,需要缓存一定数量的包,缓存的数量需要跟进帧长、实时性要求等业务特性来设置合理的值。
合理的算法和数据结构设计
合理的算法和数据结构也可以有效降低内存。在保证计算准确性的前提下,通过减少数据值域范围,使用内存空间占用更小的数据类型来实现算法,比如统计与时间相关的数据时使用相对时间而非绝对时间、空间音频算法通过定点化使用short类型代替浮点型数据。另外数据结构设计时需要考虑内存对齐问题。
优化效果
1v1 语音通话
占用的资源 | 优化前 Memory[MB] | 优化后 Memory[MB] |
Android 高端机 | 17.87 | 13.59 |
Android 中端机 | 17.58 | 13.98 |
Android 低端机 | 16.06 | 12.93 |
iOS 高端机 | 6.19 | 3.87 |
iOS 中端机 | 6.52 | 3.84 |
iOS 低端机 | 5.73 | 3.14 |
本次内存优化,我们探索了 RTC 场景下性能归因分析驱动性能优化的实践。可以总结出以下经验:
- 构造稳定的测试用例
- 建立性能折损的数据归因模型
- 基于归因模型识别热点性能问题,形成优化方案
- 从 1v1 通话开始分析,然后逐步到多人、百人千人。
- 上一篇: 电动机驱动系统性能分析与优化 驱动电机系统功能
- 下一篇: 超细致的性能测试流程,你get了吗?
猜你喜欢
- 2024-11-11 光伏热水系统性能分析 光伏热水器怎么样
- 2024-11-11 国网考试《电力系统分析》这个知识点建议收藏
- 2024-11-11 Linux下系统 I/O 性能分析的套路 linux io_uring
- 2024-11-11 如何对Linux系统进行性能分析? linux性能调优有哪些
- 2024-11-11 架构师修炼之性能分析:Linux系统性能分析USE方法与工具
- 2024-11-11 性能分析工具——WindowsA 性能分析工具有哪些
- 2024-11-11 Linux系统性能分析命令 linux系统性能分析命令有哪些
- 2024-11-11 超细致的性能测试流程,你get了吗?
- 2024-11-11 电动机驱动系统性能分析与优化 驱动电机系统功能
- 2024-11-11 [性能优化]Perfetto - 系统性能分析、应用追踪和追踪分析
你 发表评论:
欢迎- 11-13第一次养猫的人养什么品种比较合适?
- 11-13大学新生活不适应?送你舒心指南! 大学新生的不适应主要有哪些方面
- 11-13第一次倒班可能会让人感到有些不适应,以下是一些建议
- 11-13货物大小不同装柜算法有哪些?怎么算?区别有哪些?
- 11-13五大基本算法 五大基本算法是什么
- 11-13高级程序员必备:分治算法分享 分冶算法
- 11-13最快速的寻路算法 Jump Point Search
- 11-13手机实时人工智能之「三维动作识别」:每帧只需9ms
- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)