美文网首页
性能优化小记

性能优化小记

作者: hiseason | 来源:发表于2018-02-25 11:45 被阅读26次

    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包测试出来的性能才是最真实的)。

    相关文章

      网友评论

          本文标题:性能优化小记

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