iOS内存深入研究

作者: hello_iOS程序媛 | 来源:发表于2019-04-19 20:00 被阅读62次

    参考资料:WWDC2018 iOS Memory Deep Dive

    WWDC2018 iOS Memory Deep Dive

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

    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 | <classes-pattern>

    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内存深入研究

        本文链接:https://www.haomeiwen.com/subject/fwwcgqtx.html