iOS:内存优化思路

前言:ARC

内存管理需要说说ARC:

ARC(Automatic Reference Counting):自动引用计数内存管理。ARC是一种编译器功能,它通过LLVM编译器和Runtime协作来进行自动管理内存。

ARC如何进行自动管理内存?
LLVM编译器会在编译时在合适的地方为 OC 对象插入retainreleaseautorelease代码来自动管理对象的内存。

计算机语言分为:编译型语言、直译式语言(脚本语言)

语言编译形式效率调试
编译型语言C++ Objective C Swift Kotlin先通过编译器生成机器码
机器码可以直接在 CPU 上执行
执行效率较高调试周期长
直译式语言JavaScript Python不需要经过编译,在执行时
通过一个中间的解释器将代码解释为 CPU 可以执行的代码
执行效率低编写调试方便

编译又分为前端编译和后端编译

1:前端编译

前端编译:主要是通过前端编译器Clang,生成中间码。Clang 主要处理:

  1. 预处理: 主要是宏替换(把宏嵌入到对应的位置),头文件的导入注释删除
  2. 词法分析: 这里把源文件中的代码转化为特殊的标记流,源码被分割成一个一个的字符和单词,在行尾Loc中都标记出了源码所在的对应源文件和具体行数,方便在报错时定位问题。
  3. 语法分析: 这一步是把词法分析生成的标记流,解析成一个抽象语法树,同样地,在这里面每一节点也都标记了其在源码中的位置。
  4. 静态分析:分析代码是否存在问题,给出错误信息和修复方案:如出现方法被调用但是未定义、定义但是未使用的变量等
  5. 前面的过程完了,就会生成中间代码(bitCode) IR:并会对bitcode进行各种类型的优化,将bitcode代码进行一些逻辑等价的转换,使得代码的执行效率更高,体积更小
2:后端编译

后端编译:主要由后端编译器LLVM,把优化后的中间码bitcode编译为指定目标架构的机器码,比如X86Backend负责把bitcode编译为x86指令集的机器码

在 iOS 编译中,编译器后端其实就是 LLVM 自己提供的一套后端。它包含了 机器码生成器、链接器等工具,会对 IR
进行机器无关的代码优化,生成机器语言。

二、内存优化思路

当内存使用过高,可能就会发生OOM(Out-Of-Memory)。所以内存使用过高,系统就会回收一些内存:

  1. 先回收优先级极低的进程和一些正常情况下随时可回收的进程。

  2. 如果还有内存压力,就会杀掉后台进程以及一些后台执行的任务

  3. 最终还有内存压力,就会发生OOM

内存问题主要包括两个部分

  1. 常见循环引用导致的内存泄露
  2. 大量数据加载及使用导致的内存警告

内存优化也是注意处理这两个部分

1、循环引用

循环引用对App有潜在的危害,会使内存消耗过高,性能变差和Crash等,主要从以下几个方面入手

  1. Delegate
    代理要声明为weak,不能用strong。
  2. NSTimer
    RunLoop会强引用target,可以使用weakProxy 消息转发。使用GCD timer
  3. Block
    _weak 修饰对象
  4. C语法,malloc之后调用free
二、大量数据加载导致内存暴涨

在一些使用场景里,比如整个页面初始化,要分配整个使用内存,批量的图片处理,会出现一段时间内需要加载大量内容,占用过高的内存。而iOS的低内存机制就是给你一个阈值,只要你的APP超过这个数值,哪怕只是一瞬间也会直接崩溃。因此我们就需要对这种瞬间的高增幅去进行优化。我们就需要用时间去换空间,拉长整个加载步骤。

  1. 懒加载:时间去换空间
  2. 单次出现的图片使用imageWithContentsOfFile加载
  3. 在循环里面使用autoreleasepool,让临时对象及时释放
  4. 图片内存使用优化:使用适当尺寸的图片、及时回收图片、注意图片缩放方式
a:使用适当尺寸的图片

解压后的图片是由一个个像素点组成的。每个像素点一般有R、G、B、A(红绿蓝透明度)四个通道,每个通道是8位,因此一个像素通常占用4字节。对于一张图片,如果同样是300300分辨率的jpeg和png两张图,文件大小可能差几倍,但是渲染后的内存开销是完全一样的。
如果一张图片尺寸是300
300,解压后大小是3003004。而在view的大小是6060,最终使用的是:6060*4,那么多出的内存将会抛弃。造成资源浪费。所以我们要协商好尺寸。

所以制定了一套方案,服务端将精确尺寸的图片下发到不同机型,从根本上将内存使用降低。

b:及时回收图片

单张图片占用内存不多,累计起来却非常可观。因此,当页面pop掉时,有必要清理页面内图片的内存缓存。其次,列表类的页面在滑动时,可以及时清理那些滑出屏幕图片的内存缓存。
使用imageNamed这个方法生成的UIImage对象,会在应用的bundle中寻找图片,如果找到,则Cache到系统缓存中,作为内存的cache,而程序员是无法操作cache的,只能由系统自动处理,网络图片就可以用自己的cache逻辑管理了

c:注意图片缩放方式

处理图片缩放时,直接使用UIImage会在解码时读取文件占用一部分内存,还会生成中间位图bitmap消耗大量内存,而ImageIO不存在上述两种内存消耗,只会占用最终图片大小的内存,可以使用UIGraphics相关函数

UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

检测工具:

Instruments
MLeaksFinder

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值