iOS内存深入研究

参考资料:WWDC2018 iOS Memory Deep Dive

WWDC2018 iOS Memory Deep Dive

iOS内存深入研究
尽管这篇文章研究iOS,但涉及的内容同样适用于其他平台。

  • 1.Why reduce memory 为什么减少内存
  • 2.Memory Footprint
    • 1)Pages:系统分配的内存页
    • 2)Memory-mapped files
    • 3)一个典型的app内存
    • 4)Memory warnings内存警告
    • 5)Caching
    • 6)典型的内存分析
  • 3.高级的工具用于分析和研究App的内存占用情况
    • 1)Xcode内存测量计
    • 2)Instruments
    • 3)Memory debugger
    • 4)工具的选择:
  • 4.Images
    • 1) 图片是内存中的大对象。
    • 2) 图片为什么占用这么大的内存:
    • 3) 图片渲染格式:
    • 4) 我们通常对图像做的另一件事是对它们进行下采样。
  • 5.在后台时候的优化
  • 6.补充命令:
  • 7.总结:

1.Why reduce memory 为什么减少内存

减少内存占用,系统整体表现更好,app启动更快,后台驻留时间更长

2.Memory Footprint

1)Pages:系统分配的内存页

Pages.jpg

通常16KB

Page types:Clean / Dirty

App的实际使用内存大小 = 页面数量 * 页面大小

App的实际使用内存大小.jpg

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内存测量计.jpg

2)Instruments

Allocations 分析由你的app所分配的堆

Leaks 检查一个进程中的内存泄漏

VM Tracker 为脏内存以及交互内存即iOS中的压缩内存分别提供了独立的追踪,并且告诉你关于常驻大小的信息。

VM Tracker.jpg

常驻内存、脏内存、干净内存关系:
https://stackoverflow.com/questions/13437365/what-is-resident-and-dirty-memory-of-ios

Virtual Memory trace 虚拟内存追踪:对与app相关的虚拟内存系统的性能进行深入的了解,它提供了虚拟内存系统文件。

Virtual Memory trace.jpg

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 |

heap App.memgraph -addresse NSConcreteData

第四个工具:malloc_history

malloc_history -callTree App.memgraph address

4)工具的选择:

工具的选择.jpg

4.Images

1) 图片是内存中的大对象。

图片的大小决定内存,不是文件的大小。

如图片大小2048 px * 1536 px, 图片文件大小为590KB
,放到内存中图片所占内存大小:2048 pixels x 1536 pixels x 4 bytes per pixel 约等于 10M

2) 图片为什么占用这么大的内存:

图片为什么占用这么大的内存.jpg

Load阶段,将文件加载进内存

Decode阶段,将图片解压缩

Render阶段,显示图片

3) 图片渲染格式:

图片渲染格式.png

每像素1字节-8字节的格式,应该选择哪种格式?

不用自己选择格式,让代码选择格式:

停止使用UIGraphicsBeginImageContextWithOptions , 每个像素4个自己

开始使用UIGraphicsImageRenderer , iOS 10引入, iOS 12中自动为你选择最好的图像格式。

使用UIGraphicsBeginImageContextWithOptions.jpg

使用UIGraphicsImageRendererjpg

使用UIGraphicsImageRenderer的方式节约75%的内存。

4) 我们通常对图像做的另一件事是对它们进行下采样。

图像采用处理选择.jpg

我们不应该用UIImage进行缩小,如果我们用UIImage绘图,由于内部坐标空间变换,这种方法性能并不高,它也会解压缩内存中的整个图像。

取而代之,我们可以使用ImageIO框架,使用streaming API,只会生成结果尺寸大小的图像,能节省内存峰值。

使用UIImage绘图缩小.jpg

这种方法将有一个内存峰值。

使用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深入理解内存和减少内存

你可能感兴趣的:(iOS内存深入研究)