性能优化

193 阅读4分钟

卡顿优化

屏幕成像原理

image.png

视图布局排版、属性(文字大小、颜色)、图片的编码解码等都是CPU去计算的,CPU计算好的数据提交给GPU。 CPU计算的数据是无法直接显示在屏幕上的,屏幕显示的数据有固定的数据格式,数据由GPU渲染后转成屏幕能显示的数据,才能显示。渲染后数据直接放在缓存区,叫着帧缓存。然后将帧缓存里的数据读取到视频控制器这个部件里,然后才能显示。

iOS是双缓冲机制,这个帧缓存满了,还可以放在另一个。或者这一个在"忙",另一个处理。

要显示数据首先要发送一个垂直同步信号,VSync。一旦发送垂直同步信号,就表示要显示一帧(一页)的数据。然后发送一行行的水平同步信号,直到填充整个屏幕为止。

image.png

image.png

image.png

卡顿产生的原因

image.png

首先CPU计算的数据交给GPU,然后发送垂直同步信号,然后GPU渲染到帧缓存里的数据显示在屏幕上,完成这一帧的显示,并且马上开始下一帧的操作,开始CPU的计算......

image.png

有时候GPU会早早的把数据渲染到帧缓存,然后等待垂直同步信号的到来。

image.png

有时候垂直同步信号到来的时候,GPU的渲染还未完成,那么这一帧会显示上一次的数据(上图第三帧会显示第二次的数据),这就造成掉帧。那么第三次的数据是否会丢弃呢,不是,会等待下一个垂直同步信号(上图第四个)的到来,显示在下一帧里。就造成了卡顿。

image.png

卡顿优化 CPU

image.png

  • 文本处理
    // 文字计算
    [@"text" boundingRectWithSize:CGSizeMake(100, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:**nil** context:**nil**];

    // 文字绘制
    [@"text" drawWithRect:CGRectMake(0, 0, 100, 100) options:NSStringDrawingUsesLineFragmentOrigin attributes:**nil** context:**nil**];

文本尺寸计算和文本绘制放在子线程。

  • 图片处理
    UIImageView *imageView = [[UIImageView alloc] init];
    imageView.frame = CGRectMake(100, 100, 100, 56);
    imageView.image = [UIImage imageNamed:@"test"];
    [self.view addSubview:imageView];
    self.imageView = imageView;

[UIImage imageNamed:@"test"]得到的是压缩过的图片二进制数据,当图片即将要显示屏幕上,才经过解码操作,解码默认在主线程上操作的,这样如果图片比较多比较大的话,也会产生卡顿。所以要提前放在子线程解码。网络上很多图片第三方库都有异步解码操作。如下面代码:

- (void)image
{
    UIImageView *imageView = [[UIImageView alloc] init];
    imageView.frame = CGRectMake(100, 100, 100, 56);
    [self.view addSubview:imageView];
    self.imageView = imageView;

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // 获取CGImage. 这里是本地。实际情况从网络或本地获取
        CGImageRef cgImage = [UIImage imageNamed:@"timg"].CGImage;

        // alphaInfo  位图信息
        CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(cgImage) & kCGBitmapAlphaInfoMask;
        BOOL hasAlpha = NO;
        if (alphaInfo == kCGImageAlphaPremultipliedLast ||
            alphaInfo == kCGImageAlphaPremultipliedFirst ||
            alphaInfo == kCGImageAlphaLast ||
            alphaInfo == kCGImageAlphaFirst) {
            hasAlpha = YES;
        }

        // bitmapInfo
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
        bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;

        // size
        size_t width = CGImageGetWidth(cgImage);
        size_t height = CGImageGetHeight(cgImage);

        // context 创建一个位图上下文
        CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, CGColorSpaceCreateDeviceRGB(), bitmapInfo);

        // draw 将图片数据画到上下文上去,这样就完成了解吗操作
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage);

        // get CGImage 从上下文获取解码的图片
        cgImage = CGBitmapContextCreateImage(context);

        // into UIImage CGImage包装成UIImage
        UIImage *newImage = [UIImage imageWithCGImage:cgImage];

        // release
        CGContextRelease(context);
        CGImageRelease(cgImage);

        // back to the main thread 回到主线程
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = newImage;
        });
    });
}

卡顿优化 GPU

image.png

  • 有透明的视图要经过重新计算。比如两个透明的颜色重叠会变成另一种新的颜色。

离屏渲染

image.png

新开辟的缓存区不是在当前屏幕,就是这个缓冲区数据不是用来直接显示在屏幕上的。为什么会产生离屏渲染,是因为当前操作比较耗性能,即使是双缓冲机制也不够用。所以要新开辟缓冲区。

卡顿检测

image.png

image.png

主线程大部分操作基本在source0和source1,比如点击UI处理,View绘制、计算等等。所有我们要监听结束睡眠到source0这中间所耗的时间。

下面的第三方会监制到造成卡顿的方法,并打印方法调用栈: LXDAppFluecyMonitor

耗电优化

耗电的主要来源

  • CPU处理,Processing
  • 网络,Networking
  • 定位,Location
  • 图像,Graphics

耗电优化

image.png

image.png

  • 减少,压缩网络数据:用protobuf(protocol buffer)
  • 如果多次请求的结果是相同的,尽量使用缓存 NSMutableURLRequest的NSCache缓存

App启动

image.png

image.png

  • dyld

image.png

为什么递归,因为这个动态库有可能依赖另外一个动态库,需要递归一层层查找。

  • runtime

image.png

map_iamges 在runtime源码

  • 总结

image.png

  • 启动优化

image.png

安装包瘦身

image.png

去除无用的资源:github.com/tinymind/LS… Appcode: www.jetbrains.com/objc/

  • LinkMap

image.png

image.png

Write Link Map File 是否把可执行文件信息写入LinkMap Path to Link Map File 是LinkMap文件的路径,这里放在桌面。

可借助第三方工具解析。