参考资料:WWDC2018 iOS Memory Deep Dive
WWDC2018 iOS Memory Deep Dive
iOS内存深入研究
尽管这篇文章研究iOS,但涉及的内容同样适用于其他平台。
- 1.Why reduce memory 为什么减少内存
- 2.Memory Footprint
- 3.高级的工具用于分析和研究App的内存占用情况
- 4.Images
- 5.在后台时候的优化
- 6.补充命令:
- 7.总结:
1.Why reduce memory 为什么减少内存
减少内存占用,系统整体表现更好,app启动更快,后台驻留时间更长
2.Memory Footprint
1)Pages:系统分配的内存页
Pages.jpgApp的实际使用内存大小.jpg通常16KB
Page types:Clean / Dirty
App的实际使用内存大小 = 页面数量 * 页面大小
2)Memory-mapped files
内存映射文件, 是一种在磁盘上的文件,但加载到了内存,内核实际上是在它们离开磁盘写入RAM时进行管理的。
3)一个典型的app内存
典型的app内存.jpg有一个dirty、compressed和一个clean的内存段。
dirty:有app写入的内存,所有堆分配内存、已解码的图像缓冲、Frameworks中的__DATA、__DATA_DIRTY段。
Compressed:
iOS没有传统的磁盘交换系统, 却而代之,它使用内存压缩器memory compressor, 它是在iOS7中引入的。
内存压缩器memory compressor:压缩不访问的页面,解压访问的页面
4)Memory warnings内存警告
不要想当然的认为内存警告是app造成的,在一个低内存的设备上,接到一个电话,就可能引发内存警告。
内存压缩器是释放内存变得复杂,因为根据压缩的内容,实际上你可以比以前使用更多的内存。
5)Caching
在CPU和内存之间平衡
记住有内存压缩器
使用NSCache而不是NSDictonary,在内存警告的时候NSCache会自动释放
6)典型的内存分析
主要分析Dirty和compressed:
内存限制:
每个设备不同 app有一个相对高的内存限制 Extension有一个低得多的限制
内存超过限制的异常.jpg内存超过限制的异常:
3.高级的工具用于分析和研究App的内存占用情况
1)Xcode内存测量计
Xcode内存测量计.jpg2)Instruments
VM Tracker.jpgAllocations 分析由你的app所分配的堆
Leaks 检查一个进程中的内存泄漏
VM Tracker 为脏内存以及交互内存即iOS中的压缩内存分别提供了独立的追踪,并且告诉你关于常驻大小的信息。
常驻内存、脏内存、干净内存关系:
https://stackoverflow.com/questions/13437365/what-is-resident-and-dirty-memory-of-ios
Virtual Memory trace.jpgVirtual Memory trace 虚拟内存追踪:对与app相关的虚拟内存系统的性能进行深入的了解,它提供了虚拟内存系统文件。
3)Memory debugger
6cef4a038a824f4b836107f40eae95a5_8612451f05fff33eca9340a0eca676f2.jpg.jpg使用memgraph文件格式存储有关App的内存使用信息
⁃ 导出内存图⁃ 搭配命令行工具使用memgraph
第一个工具:vmmap 通过输出分配给进程的虚拟内存区域, 它给你的App提供了内存消耗的高级分析, summary参数是一个很好的起点,它可以打印出很多细节,比如该区域内存大小
显示进程中分配的虚拟内存区
vmmap App.memgraph
Mmap —summary App.memgraph
检查脏页面是否有一部分是由链接的框架或库造成的
vmmap -pages App.memgraph | grep '.dylib' | awk '{sum += $6} END { print "Total Dirty Pages:" sum} '
第二个工具 leaks 在运行时跟踪堆中的没有根的对象
leaks App.memgraph
第三个工具 heap 提供了关于进程堆中对象分配的各种信息,它可以帮助你追踪非常复杂的分配
heap App.memgraphheap App.memgraph -sortBySize
heap App.memgraph -addresses all | <classes-pattern>
heap App.memgraph -addresse NSConcreteData
第四个工具:malloc_history
malloc_history -callTree App.memgraph address
4)工具的选择:
工具的选择.jpg4.Images
1) 图片是内存中的大对象。
图片的大小决定内存,不是文件的大小。
如图片大小2048 px * 1536 px, 图片文件大小为590KB
,放到内存中图片所占内存大小:2048 pixels x 1536 pixels x 4 bytes per pixel 约等于 10M
2) 图片为什么占用这么大的内存:
图片为什么占用这么大的内存.jpgLoad阶段,将文件加载进内存
Decode阶段,将图片解压缩
Render阶段,显示图片
3) 图片渲染格式:
图片渲染格式.png每像素1字节-8字节的格式,应该选择哪种格式?
使用UIGraphicsBeginImageContextWithOptions.jpg不用自己选择格式,让代码选择格式:
停止使用UIGraphicsBeginImageContextWithOptions , 每个像素4个自己
开始使用UIGraphicsImageRenderer , iOS 10引入, iOS 12中自动为你选择最好的图像格式。
使用UIGraphicsImageRendererjpg
使用UIGraphicsImageRenderer的方式节约75%的内存。
4) 我们通常对图像做的另一件事是对它们进行下采样。
图像采用处理选择.jpg使用UIImage绘图缩小.jpg我们不应该用UIImage进行缩小,如果我们用UIImage绘图,由于内部坐标空间变换,这种方法性能并不高,它也会解压缩内存中的整个图像。
取而代之,我们可以使用ImageIO框架,使用streaming API,只会生成结果尺寸大小的图像,能节省内存峰值。
这种方法将有一个内存峰值。
使用ImageIO采用.jpg使用ImageIO采用快50%
5.在后台时候的优化
卸载看不到的大资源
两种方式:
App生命周期
iewController生命周期
6.补充命令:
vmmap —verbose app.memgraph | grep “str”
引用该地址的对象产生堆栈
leaks —trackTree 地址
malloc_history app.memgraph —fullStacks 地址
7.总结:
1)内存有限且是是共用资源
2)在Xcode里运行的时候监视内存使用
3)让IOS选择图片格式
4)使用ImageIO下采样图片
5)卸载不载屏幕上的大资源
6)使用memory graphs深入理解内存和减少内存
网友评论