性能优化小记

FPS

全称Frames Per Second,其实就是屏幕刷新率,苹果的iphone推荐的刷新率是60Hz,也就是说GPU每秒钟刷新屏幕60次,这每刷新一次就是一帧frame,FPS也就是每秒钟刷新多少帧画面。静止不变的页面FPS值是0,这个值是没有参考意义的,只有当页面在执行动画或者滑动的时候,FPS值才具有参考价值,FPS值的大小体现了页面的流畅程度高低,当低于45的时候卡顿会比较明显。

1.内存泄露检测

方法一: 使用 instrument 检测

Analyze

静态分析查找可疑的内存泄露

1.内存泄露
oc 对象存放在堆区, 堆区是需要程序员管理的, 如果使用变量之后没有释放变量所占用的内存空间(即这块空间没有指针指向), 导致这块空间不能再被回收使用, 这就叫内存泄漏.
2.什么情况下会发生内存泄漏?
*block 的循环引用
*潜在的内存泄露:这里主要是一些非OC对象,ARC不会对它进行释放,所以造成了一直没有释放。比如一些类型:CGImageRef(对应调用CGImageRelease)、CGContextRef(对应调用CGContextRelease)CGColorSpaceRef(对应CGColorSpaceRelease) 这些都是非OC对象,所以要自己记着释放掉。

使用方法:
1.菜单 product-Analyze
2.点击左侧感叹号就可看到分析结果,如下图

image.png

蓝色线的地方就是使用 Analyze 静态分析查找出来的泄漏点,称之为"可疑泄漏点".之所以称之为"可疑泄漏点",是因为这些点未必一定泄露,确认这些点是否泄露, 还要通过 Instruments 动态分析工具的 Leaks 和 Allocations 跟踪模板. Analyze 静态分析只是一个理论上的预测过程.

Leaks
使用方法.png
设置.png

方法二: MLeaksFinder

腾讯开发的 MLeaksFinder 使用很方便, 详细了解移步于此 MLeaksFinder:精准 iOS 内存泄露检测工具, 下面介绍一下我的使用过程, 分享一些内存泄露的例子.

1.1 UIAlertController 泄露
泄露截图.png

思路

  1. 在 viewController 中使用 dealloc 方法检测, 发现控制器没有被销毁,也出现了内存泄漏。猜测是UIAlertController 对控制器进行强引用。 看看我的代码,看出来问题出在哪里了吧!
    UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:nil  message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"相机" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self judgeAuthorization];
    }];

    UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"去相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
        [self showImagePickerController];
    }];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        [alertVc dismissViewControllerAnimated:YES completion:nil];
    }];

    [alertVc addAction:action1];
    [alertVc addAction:action2];
    [alertVc addAction:cancelAction];
    [self presentViewController:alertVc animated:YES completion:nil];

是block的循环引用导致了内存泄漏,解决办法就是用`__weak typeof(self) weakSelf = self;

    [weakSelf judgeAuthorization];
    [weakSelf showImagePickerController];
循环引用示意图.png
  1. vc 的内存泄露解决了,不过在点击确定类 Action push 到下一个 vc 时, 仍然报alertVc 内存泄露, 如何证明呢?相信你也一定想到,写一个类继承自UIAlertController 看看有没有走dealloc方法...... 然而.....真的没有。

想了一下, 原来是因为[self presentViewController:alertVc animated:YES completion:nil] vc 对 alertVc 在进行着强引用, 而 vc 还没有被释放, 所以 alertVc 无法释放。在 Google 后找到解决办法, 声明全局变量, 修改 dismiss 时的 alertVc。

 @property (strong, nonatomic) XSAlertController *alertController;     
  [weakSelf.alertController dismissViewControllerAnimated:YES completion:nil];
  //之前是 [alertVc dismissViewControllerAnimated:YES completion:nil];

在pop alertVc 所在的 vc 时, alertVc 调用了 dealloc 方法, MLeaksFinder 又弹框了, 没有泄漏 MLeaksFinder 为什么还弹框, 难道是我释放多了一次?
莫慌, 其实是 MLeaksFinder 的友情提示, 告诉你刚刚内存泄漏的对象现在已经正常释放了,详细的解释请看这里MLeaksFinder 新特性

内存泄露的对象已经释放了.png

2. 启动时间优化

在 scheme 中添加 DYLD_PRINT_STATISTICS 设置为1

DYLD_PRINT_STATISTICS.png

输出控制台会显示时间


console.png

3. UI 卡顿优化

CPU 资源消耗原因和解决方案
对象创建
对象的创建会分配内存、调整属性、甚至还有读取文件等操作,比较消耗 CPU 资源。尽量用轻量的对象代替重量的对象,可以对性能有所优化。比如 CALayer 比 UIView 要轻量许多,那么不需要响应触摸事件的控件,用 CALayer 显示会更加合适。如果对象不涉及 UI 操作,则尽量放到后台线程去创建,但可惜的是包含有 CALayer 的控件,都只能在主线程创建和操作。通过 Storyboard 创建视图对象时,其资源消耗会比直接通过代码创建对象要大非常多,在性能敏感的界面里,Storyboard 并不是一个好的技术选择。

Allocations

查看内存分配

All Heap Allocations: 真实内存
All Anonymous VM: 虚拟内存, 为程序分配的虚拟内存,当程序有需要的时候,能够及时为程序提供足够的内存空间,而不会现用现创建

在我的项目中进行选择相册照片的操作, 内存分配如图所示, 红框选中的就是虚拟内存项


虚拟内存.png

VM:CG raster data
关于这个问题我在google中找到了解释,这是SDWebImage的问题

  • Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
  • Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
//所以我们需要在Appdelegate中设置一下
[SDImageCache sharedImageCache].config.shouldDecompressImages = NO;

Time Profiler

检测应用CPU的使用情况

注意点:
(1)使用真机调试。
(2)最好使用release包测试(release是发布版本,苹果会在release包中做很多优化工作,因此用release包测试出来的性能才是最真实的)。

你可能感兴趣的:(性能优化小记)