ios开发之内存泄漏和性能优化

什么是内存泄漏?

本应释放的内存没有释放,导致可用空间减少的现象。(摘自百度知道,看你敢不敢信)
举个例子:你dismiss了一个视图控制器,但是最终却没有执行这个视图控制器的dealloc方法。
目前遇到的导致内存泄漏比较严重的有这几个地方:
一.delegate
不知为何之前那个开发者全部用的retain修饰符,导致很多应该释放的视图控制器都没释放。这个修改很简单:将retain改成weak即可。
二.block
不管是自己写的block、还是三方的甚至系统的,都要小心,尤其是当你对循环引用没有较好的把控时,更是要当心再当心,多一个心眼总是没错的。
比如说使用MJRefresh时,这样写会导致内存泄漏:
1
2
3
self.tableView.header = [CQHeader headerWithRefreshingBlock:^{
    [self getLocation];
}];

这样写则不会:

1
2
3
4
__weak typeof (self) weakSelf = self;
self.tableView.header = [CQHeader headerWithRefreshingBlock:^{
    [weakSelf getLocation];
}];

一般我们会将weakSelf和strongSelf配合使用。

三.timer
根据实际情况在恰当时间主动将timer置为nil。
1
2
[_timer invalidate];
_timer = nil;


iOS性能优化:Instruments工具

Instruments提供了很多功能,重点介绍一下我最常用的几类:
1.Time Profiler:CPU分析工具分析代码的执行时间。
2.Core Animation:离屏渲染,图层混合等GPU耗时。
3.Leaks:内存检测,内存泄漏检测工具。
4.Energy Log:耗电检测工具。
5.Network:流量检测工具。

使用Xcode自带的Instruments工具首先需要打开它。



之后便可以根据想调试不同的性能来选择对应的调试工具。


一.Time Profiler使用简介

TimeProfiler见名知意:时间分析工具,它会按照设定的时间间隔(默认1毫秒)来跟踪每一线程的堆栈信息(stacktrace),并通过比较时间间隔之间的堆栈状态,来推算出某个方法执行了多久,给出一个近似值。具体步骤如下:

1.双击TimeProfiler进入到调试界面点击左上角红色原点(启动程序按钮)之后便可以看到如下图的时间消耗。


但是我们发现这些信息只能显示到底层的线程Runloop耗时,并不能帮助我们定位到具体的代码中去,下面介绍CallTree选项的勾选操作以及含义。这些选项默认是不选的,但把它们勾选上可以帮你更快定位到关键的代码上,往往这也是问题的源头。


Separate by Thread:按线程分开做分析,这样更容易揪出那些吃资源的问题线程。特别是对于主线程,它要处理和渲染所有的接口数据,一旦受到阻塞,程序必然卡顿或停止响应。

Invert Call Tree:反向输出调用树。把调用层级最深的方法显示在最上面,更容易找到最耗时的操作。

Hide Missing Symbols:隐藏缺失符号。如果dSYM文件或其他系统架构缺失,列表中会出现很多奇怪的十六进制的数值,用此选项把这些干扰元素屏蔽掉,让列表回归清爽。

Hide System Libraries:隐藏系统库文件。过滤掉各种系统调用,只显示自己的代码调用。

Flattern Recursion:拼合递归。将同一递归函数产生的多条堆栈(因为递归函数会调用自己)合并为一条。

Top Functions:找到最耗时的函数或方法。

将以上勾选之后便可以看到对应的具体代码,此时选中一行耗时操作双击便可以进入到对应的代码中并且显示详细的消耗时间等如下图:


根据这些时间对应代码便可以做一些优化,减少重复的耗时逻辑优化CPU。


二.Core Animation动画渲染使用简介:

CoreAnimation系要注意的一点是必须是真机调试,用于调试离屏渲染,绘图,动画,等操作。调试需注意以下几个选项的勾选:


比较重要的:

·"Color BlendedLayers":图层混合

显示出被混合的图层BlendedLayer(用红色标注),BlendedLayer是因为这些Layer是透明的(Transparent),系统在渲染这些view时需要将该view和下层view混合(Blend)后才能计算出该像素点的实际颜色。所以红色越少越好

·"Color HitsGreen and Misses Red":图层缓存

很多视图Layer由于Shadow、Mask和Gradient等原因渲染很高,因此UIKit提供了API用于缓存这些Layer:[layersetShouldRasterize:YES],系统会将这些Layer缓存成Bitmap位图供渲染使用,如果失效时便丢弃这些Bitmap重新生成。所以绿色越多,红色越少越好

·"ColorOffscreen-Rendered Yellow":离屏渲染

Offscreen-Rendering离屏渲染意思是iOS要显示一个视图时,需要先在后台用CPU计算出视图的Bitmap,再交给GPU做Onscreen-Rendering显示在屏幕上,因为显示一个视图需要两次计算,所以这种Offscreen-Rendering会导致app的图形性能下降。所以黄色越少越好。

次要的:

·"ColorMisaligned Images":图片缩放

MisalignedImage表示要绘制的点无法直接映射到频幕上的像素点,此时系统需要对相邻的像素点做anti-aliasing反锯齿计算,增加了图形负担,通常这种问题出在对某些View的Frame重新计算和设置时产生的。

·"Color Copiedimages":标注应用绘制时被Core Animation复制的图片

·"ColorImmediately":Instruments在做color-flush操作时取消10毫秒的延时

·"ColorCompositing Fast-Path Blue":标记由硬件绘制的路径

·"Flash UpdatedRegions":重绘的区域

勾选这些不同的选项可以在真机上看到不同颜色的渲染标注。


三.Leaks内存调试使用简介

Leaks是iOS程序中用来检测内存泄漏的工具,灵活的运用Leaks可以帮助我们预防程序中的内存泄漏防止程序内存耗用过大被挂起。首先双击Leaks点击左上角红色圆点运行,并且选中CallTree,在CallTree选项中勾选InvertCallTree和HideSystemLibraries选项如下图所示



然后程序跑起来我们观察上方的内存变化区域,工具中按照时间把所耗内存的大小都以填充图的形式展现出来,当鼠标移动到图的位置时直接显示出那一时刻所占用的内存大小,如果内存途中下方显示出红色叉号则代表此处存在内存泄漏。可以通过鼠标在图中圈出此区域,此时下面的CallTree就会打印出对应的函数堆栈调用以及所占内存大小信息,双击便可进入到对应的代码区域来查看。如下图:


双击函数名称进入到代码对应的位置查看具体:


此时便可以根据代码中对应的位置来进行内存调试工作。


四.Energy Log耗电量检测使用简介:

双击打开EnergyLog直接点击红色圆点运行程序,左侧依次即可看到CPU活动比例,网络活动比例,亮度状态,手机睡眠状态,手机连接蓝牙状态,手机连接wifi状态,手机GPS状态这次都是手机耗电的构成部分。如下图:


我们也可以在Xoce启动程序时点击Xcode左侧状态栏,选择EnergyImpact选项,在右侧即可看到手机实时的耗电情况。如下图:

左上部分是资源实时消耗情况仪表盘,右上部分是资源平均消耗情况,下方是资源具体消耗情况。


注意资源实时消耗情况仪表盘中指针指向的区域

绿色—合理

黄色—资源消耗高.你的程序比较耗电.

红色—资源消耗非常高.仅仅轻度使用你的app,用户就可以明显感到电量在消耗。

下图为具体电量消耗情况:


四个最主要的耗电原因,分别是CPU(唤醒及使用),Network(网络访问),Location(定位功能),Background(后台运行功能)。

每秒刷新.不同功能分别的资源消耗情况.如果消耗资源小方块显示深灰色,没有消耗资源的时候小方块显示白色。


五.Network网络检测使用简介:

双击打开Network直接点击红色圆点运行程序在上方便可以看到手机网络的输入输出大小,用鼠标拦截住一块区域就可以查看这个区间内是我们的App发生的网络消耗还是其他进程发生的,我们还可以查看到网络请求的本地地址和服务地址,输入和输出的大小等信息下面将详细介绍各种查看检测等方式:


上图随便圈出一块消耗网络资源的地方,此时在下方有三个选项:


第一个:Processes代表查看网络进程,也就是你的App和其他程序的使用流量总大小。

第二个:Connections代表所有的访问网络请求的端口,输入输出大小,本地地址,数据包大小,往返时间等信息。

第三个:interfaces即在用户的角度当前手机的整体网络使用情况(不区分线程,只区分网络使用类型- wifi Or流量)。

1.选择Processes


我们可以发现工具把整个网络访问划分为两部分,我们的App和其他的进程,分别显示出它们的:

1.process:进程名。

2.data in请求数据大小。

3.packets in请求数据包大小。

4.data out发送数据大小。

5.packets out发送数据包大小。

6.duplicate Data Recv重传数据大小。

7.out-of-Order data传输失败数据大小。

8.retransmissions网络重传次数。

2.选择Connections


这个选项把所有的网络请求发生的数据交互明细都打印出来可以让我们一目了然的发现数据来自哪里,到哪里去,大小是多少,帧率是多少等信息。

相比Processes选项Connections选项多出了

1.local代表本地访问地址。

2.remote远程服务地址。

3.shortest Roundtrip:最短往返时间。

4.avg. Roundtrip:平均往返时间。

3.选择interfaces


interfaces代表在用户层面上的手机的网络使用情况,其中Interface选项代表网络环境,Connections代表总体连接次数其他选项和以上意义相同。

根据以上三个选项的不同信息我们就可以全面系统的掌握我们的App和用户当前手机的网络使用情况。


小结:整理总结关于优化部分实在有限,如上仅供各位参考.另外Instruments确实是把分析代码利器.目前没有任何一个第三方工具可以去替代.推荐各位使用.



  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值