[WWDC 21]Detect and diagnose memory issues 笔记
developer.apple.com/videos/play…
概述
本Session主要解释了App内存由哪些部分组成,并介绍了可以使用Performace XCTests工具对内存问题进行排查、分析
Impact of Memory footprint
好的内存管理可以提升用户体验,可以表现在
- Faster application activation,因为内存控制的好,所以app进入后台时不易被系统终止,重新激活回到前台时也更快
- Responsive experience,更高的响应速度
- Complex workflows,内存控制的好则意味着可以增加更多更消耗内存的功能
- Wider device compatibility,控制好内存则可以兼容到更老的机器
Memory footprint
本小节主要介绍Memory footprint都是有哪些内容组成
Dirty memory consists of memory written by your application. It also includes all heap allocations such as when you use malloc, decoded image buffers, and frameworks.
Compressed memory refers to any dirty pages that haven't recently been accessed that the memory compressor has compressed. These pages will be decompressed on access.
Tools for profiling memory
Performance XCTests
可以使用XCTests去检查各个功能的性能表现,比如
- Memory utilization,内存利用情况
- CPU usage
- Disk writes
- Hitch rate,卡顿率
- Wall clock time,功能的耗时情况
- Application launch time
Memory utilization 示例
func testSaveMeal() {
let app = XCUIApplication()
let options = XCTMeasureOptions()
options.invocationOptions = [.manuallyStart]
measure(metrics: [XCTMemoryMetric(application: aapp)1
options: options) {
app.launch()
startMeasuring()
app.cells.firstMatch.buttons["Save meal"].firstMatch.tap()
let savedButton = app.cells.firstMatch.buttons["Saved"].firstMatch
XCTAssertTrue (savedButton.waitForExistendce(timeout: 30)
}
}
上述代码检测的是点击“Save meal”按钮后内存的变化情况,变化情况如下图所示:
- Metric项可以选择不同的内存检测指标,如内存峰值还是普通内存值
- 底部柱状图表示是多次执行的情况
- Average项表示的是所选Metric的均值情况
- Baseline、Max STDDEV(最大标准差)则可以用来设置检测基线和上下浮动阈值
- 当检测结束后,可以通过Result查看本次检测结果变好了还是变差了
Diagnostic collection
Xcode 13中引入了两个有力的诊断数据Ktrace files和Memory graphs
执行Performance XCTests时可以开启他们
Ktrace files
是一种专用的文件类型,用于分析卡顿问题,可以用Instrument直接打开
详情可以参考
Memory graphs
某一时刻,App内存中所有对象及引用关系数据
- 在日常使用Xcode debug App时,我们也能看到内置的Memory graphs功能
- 下图为运行完XCTests后,结果中Memory graphs文件,也可以单独进行分析
Types of memory issues
内存问题类型有多种,本session中会介绍到Leaks(内存泄漏)和Heap size issues
Leaks
对于内存泄漏问题,可以使用leaks命令对钱文忠的Memory graphs文件进行分析,查找泄漏的代码堆栈、是否存在循环引用
Heap size issues
Heap allocations regressions
堆内存占用的劣化问题
为减少使用堆内存开辟空间导致内存占用劣化,我们可以这样做:
- Remove unused allocations
- Shrink overly large allocations
- Deallocated memory you are finished with
- Wait to allocate memory until you need it
Session中提到,官方提供了如vmmap等一系列命令对前面生成的Memory graphs文件分析
Fragmentation
Fragmentation译为碎片化
如何可以减少碎片化
- Allocate objects with similar lifetimes close to each other
- Aim for 25% fragmentation
- Use autorelease pools
- Pay extra attention to long running processes
- Use allocations track in Instruments
也可以使用vmmap等命令查看碎片比例
- 上图中FRAG是碎片比例
- DIRTY SIZE表示碎片化导致的Dirty pages情况
- DIRTY+SWAP FRAG SIZE表示的是碎片空间大小
总结
总结一下官方推荐的检测、诊断内存问题的最佳实践
第一步:先是检测
- 针对业务功能/场景编写Performance XCTests
- 设置baseline(基线)进行测试
- 如果发现有regression(劣化),则收集诊断数据(Memory graphs or Ktrace)
第二步:诊断
- 检查最易发现的内存泄漏
- 再使用各种命令查看是否有堆内存劣化