性能优化之FPS实践报告。

环境:Xcode 9.3

iPhone 7p  11.3

依赖 : masonry + SDWebimage

本文章主要探讨以下几个对FPS的影响:

1.Color Blended layers (混合图层),Color Misaligned Images(image对齐), Color off-screen render(离屏渲染)

2.masonry,flexlib,AsyncDisplayKit,frame等性能对比(这个不在文中讨论见https://draveness.me/layout-performance),如果对

性能要求极为苛刻的需要定夺frame和auto layout之间的平衡点,每个都有利弊.


xcode 9.3 的instrument 中对 core animation的debug options进行了移除,这个在官网中也有了说明。

Deprecation and Removal Warnings

  • The Core Animation instrument and template have been deprecated in Instruments. The functionality previously under "Debug Options" has moved to Xcode, under "Debug > View Debugging > Rendering". (22971414)

  • The OpenGL ES Analyzer Instrument is no longer supported. It has been replaced by the GPU Frame Debugger in Xcode and will be removed in a future version of Instruments. (35104029)

    General


功能被移到了Xcode的 Debug->View debugging -> Rendering下了。以后调这几个不需要再打开CA 了,只有监控FPS时打开观察。

解决blended layer问题。


红色部分是因为UILabel透明背景,对于图片UIImageView的是因为UIImage本身是带了alpha通道。所以在渲染时显示红色。

对于label

///对lable处理blended layers

- (void)settingLabelCleanBlended

{

    self.lb_title.backgroundColor = [UIColor whiteColor];

    self.lb_title.layer.masksToBounds = YES;

}

对于image的,可以让UI设计的时候设计为不透明。(后面看源码,我通过源码的方式改变alpha通道设至)

经过处理

    ///clean blended layers

    [self settingLabelCleanBlended];

    [self settingAvatar];


经过处理后看到不透明的时候QQ头像显示为黑色边框。

解决Color Misaligned Images 这个一般都是图片大小和设定的imageview的宽高不一致所致,调到一致就OK.

如果用模拟器调试则需要开启光栅设置,(真机不用。)

///光栅

- (void)settingeRasterize

{

    CGFloat scale = [UIScreen mainScreen].scale;

    self.avatar.layer.shouldRasterize = YES;

    self.avatar.layer.rasterizationScale = scale;

    

    self.pic.layer.shouldRasterize = YES;

    self.pic.layer.rasterizationScale = scale;

    

    self.lb_title.layer.shouldRasterize = YES;

    self.lb_title.layer.rasterizationScale = scale;

}

处理后效果为


最后解决离屏渲染,其实就是前面的settingeRasterize中的 这几个设置。

先看源码,看完后,再继续分晰,前前后后的FPS执行的差距,看有多少提升。

cell.h

#import <UIKit/UIKit.h>

@interface testCell : UITableViewCell
@property (nonatomic , strong) UIImageView              *avatar;
@property (nonatomic , strong) UIImageView              *pic;
@property (nonatomic , strong) UILabel                  *lb_title;

- (void)loadDataSet:(id)dataset;
@end

cell.m

//
//  testCell.m
//  fengsh
//
//  Created by fengsh on 2017/4/8.
//  Copyright © 2017年 All rights reserved.
//

#import "testCell.h"

@interface testCell()
@property (nonatomic, strong) UIView            *alignview;
@end

@implementation testCell

- (void)awakeFromNib {
    [super awakeFromNib];
    // Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        [self createControls];
        [self layoutControls];
    }
    return self;
}

- (void)createControls
{
    self.alignview = [[UIView alloc]init];
    [self.contentView addSubview:self.alignview];
    
    self.avatar = [[UIImageView alloc]init];
    self.avatar.image = [UIImage imageNamed:@"share_QQ"];//132 * 132 ,3倍图 所以一倍时为44
    [self.alignview addSubview:self.avatar];
    
    self.pic    = [[UIImageView alloc]init];
    [self.alignview addSubview:self.pic];
    
    self.lb_title = [[UILabel alloc]init];
    self.lb_title.numberOfLines = 0;
    self.lb_title.font = [UIFont systemFontOfSize:14];
    self.lb_title.textColor = [UIColor blackColor];
    [self.alignview addSubview:self.lb_title];
    
    ///clean blended layers
    [self settingLabelCleanBlended];
    [self settingAvatar];
    ///使用光栅
//    [self settingeRasterize];
    
}

- (void)layoutControls
{
    [self.avatar mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.leading.equalTo(20);
        make.height.width.equalTo(44); //132 / 3
    }];
    
    
    [self.lb_title mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(20);
        make.leading.equalTo(self.avatar.mas_trailing).offset(10);
        make.trailing.equalTo(self.pic.mas_leading).offset(-10);
        make.height.greaterThanOrEqualTo(20).priorityHigh();
        make.bottom.equalTo(-20).priorityLow();
    }];
    
    [self.pic mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(20);
        make.trailing.equalTo(-20);
        make.width.equalTo(108);
        make.height.equalTo(72);
    }];
    
    [self.alignview mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.leading.trailing.equalTo(0);
        make.height.greaterThanOrEqualTo(132);
        make.bottom.equalTo(0);
    }];
}

///圆角
- (void)settingAvatarRadius
{
    self.avatar.layer.cornerRadius = 22;
    self.avatar.layer.masksToBounds = YES;
}

///光栅
- (void)settingeRasterize
{
    CGFloat scale = [UIScreen mainScreen].scale;
    self.avatar.layer.shouldRasterize = YES;
    self.avatar.layer.rasterizationScale = scale;
    
    self.pic.layer.shouldRasterize = YES;
    self.pic.layer.rasterizationScale = scale;
    
    self.lb_title.layer.shouldRasterize = YES;
    self.lb_title.layer.rasterizationScale = scale;
}

- (void)settingAvatar
{
     //share_QQ
    self.avatar.image = [self CGContextClip:[UIImage imageNamed:@"share_QQ"] cornerRadius:22 backgroundColor:[UIColor whiteColor]];
//    self.avatar.image = [self UIBezierPathClip:[UIImage imageNamed:@"share_QQ"] cornerRadius:22 backgroundColor:[UIColor whiteColor]];
}

///对lable处理blended layers
- (void)settingLabelCleanBlended
{
    self.lb_title.backgroundColor = [UIColor whiteColor];
    self.lb_title.layer.masksToBounds = YES;
}

- (void)loadDataSet:(id)dataset
{
    self.lb_title.text = @"好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字";
    [self.pic sd_setImageWithURL:[NSURL URLWithString:@"https://images.ihuoqiu.com/article/2018/04/07/huoqiuwang_201804072024469924.png"] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
        
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            
            UIImage *scaleimg = image;
            CFTimeInterval start = CFAbsoluteTimeGetCurrent();
            scaleimg = [self useWay1:image]; //方式一
//            scaleimg = [self useWay2:image]; //方式二
//            scaleimg = [self useWay3:image]; //方式三
            
            CFTimeInterval end = CFAbsoluteTimeGetCurrent();
            
            CFTimeInterval timeval = end - start;
            NSLog(@"毫时 %f ms",timeval * 1000);
            
            dispatch_async(dispatch_get_main_queue(), ^{
                self.pic.image = scaleimg;
            });
            
            [self lookImageInfo:scaleimg];
        });
    }];
}

- (UIImage *)useWay1:(UIImage *)srcimage
{
     return [self scaleImage:srcimage toSzie:CGSizeMake(108, 72)];
}

- (UIImage *)useWay2:(UIImage *)srcimage
{
    return [self scaleImageWithData:UIImageJPEGRepresentation(srcimage, 1.0) toSize:CGSizeMake(108, 72) scale:0 orientation:UIImageOrientationUp];
}

- (UIImage *)useWay3:(UIImage *)srcimage
{
    return [self createRGBAWithUIImage:srcimage toSize:CGSizeMake(108, 72) opaque:YES];
}

#pragma mark - 图片处理方法

/*
    如果包含 alpha ,那么每个颜色分量是否已经乘以 alpha 的值,这种做法可以加速图片的渲染时间,因为它避免了渲染时的额外乘法运算。
    比如,对于 RGB 颜色空间,用已经乘以 alpha 的数据来渲染图片,每个像素都可以避免 3 次乘法运算,红色乘以 alpha ,
    绿色乘以 alpha 和蓝色乘以 alpha
 
    带last  说明alpha 分量是在RGB后面即RGBA格式,
    带first 说明alpha 分量是在RGB前面即ARGB格式
 
     typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {
        kCGImageAlphaNone,                      //不带alpha,即不透明
        kCGImageAlphaPremultipliedLast,         //带alpha通道,图片解码压缩的时候,就将 alpha 通道的值分别乘到了颜色分量上,不需要再计算
        kCGImageAlphaPremultipliedFirst,
        kCGImageAlphaLast,                      //带alpha通道,但图片解码压缩时,并没有将alpha计算到分量,这样渲染里再计算,效率很低
        kCGImageAlphaFirst,
        kCGImageAlphaNoneSkipLast,              //带alpha通道,但被忽略,相当于透明度不起作用
        kCGImageAlphaNoneSkipFirst,
        kCGImageAlphaOnly                       //只有alpha值,没有RGB
    };
 */

- (NSString *)alphaToString:(CGImageAlphaInfo)alpha
{
    switch (alpha) {
        case kCGImageAlphaNone:
            return @"kCGImageAlphaNone";
            break;
        case kCGImageAlphaPremultipliedLast:
            return @"kCGImageAlphaPremultipliedLast";
            break;
        case kCGImageAlphaPremultipliedFirst:
            return @"kCGImageAlphaPremultipliedFirst";
            break;
        case kCGImageAlphaLast:
            return @"kCGImageAlphaLast";
            break;
        case kCGImageAlphaFirst:
            return @"kCGImageAlphaFirst";
            break;
        case kCGImageAlphaNoneSkipLast:
            return @"kCGImageAlphaNoneSkipLast";
            break;
        case kCGImageAlphaNoneSkipFirst:
            return @"kCGImageAlphaNoneSkipFirst";
            break;
        case kCGImageAlphaOnly:
            return @"kCGImageAlphaOnly";
            break;
        default:
            break;
    }
    return @"UNKnow";
}

- (void)lookImageInfo:(UIImage *)image
{
    CGImageRef imgref = image.CGImage;
    CGColorSpaceRef space = CGImageGetColorSpace(imgref);
    CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imgref);
    
    CGFloat cgImageBytesPerRow = CGImageGetBytesPerRow(imgref);
    CGFloat cgImageHeight = CGImageGetHeight(image.CGImage);
    NSUInteger memorysize  = cgImageHeight * cgImageBytesPerRow;
 
    //CFStringRef cs = CGColorSpaceCopyName(space);//CGColorSpaceGetName(space);
    NSLog(@"color space : %@, 是否alpha通道 : %@ val = %@ \n Size : %f * %f \n 内存大小 : %lu Byte \n",space,(alpha != kCGImageAlphaNone)?@"是":@"否",[self alphaToString:alpha],
          image.size.width,image.size.height,(unsigned long)memorysize);
}

/*
 *  缩放到指定大小(耗内存)
 *  
 */
- (UIImage *)scaleImage:(UIImage *)srcImage toSzie:(CGSize)newsize
{
    ///YES 不透明,NO透明  opaque的中文为"不透明"
    UIGraphicsBeginImageContextWithOptions(newsize, YES, 0);
    [srcImage drawInRect:CGRectMake(0, 0, newsize.width, newsize.height)];
    UIImage *scaleimg = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return scaleimg;
}

/*
    kCGImageSourceTypeIdentifierHint                    设置一个预期的图片文件格式,需要设置为字符串类型的值
    kCGImageSourceShouldCache                           图片解码的时候是否应该缓存,如果设置为true,在读取数据时就进行解码
                                                        如果为false 则在渲染时才进行解码
    kCGImageSourceShouldAllowFloat                      返回CGImage对象时是否允许使用浮点值 默认为kCFBooleanFalse
    kCGImageSourceCreateThumbnailFromImageIfAbsent      如果有缩略图则使用,无则使用原图产生缩略图
    kCGImageSourceCreateThumbnailFromImageAlways        用原图产生缩略图
    kCGImageSourceThumbnailMaxPixelSize                 缩略图高或宽最大尺寸(当设置的最大值比原图的MAX(宽,高)大时,取原图的)
                                                        最大取值:MIN(MAX(目标宽,目标高),MAX(原图宽,原图高))
                                                        eg:
                                                            原图(w=944,h=557) 目标图片大小(w=108,h=72)
                                                            理论图片比例:
                                                                原图      h:w = 577 /944 = 0.590042
                                                                目标图     h:w = 72 / 108 = 0.666667
                                                0  < MaxPixelSize <  MIN(MAX(944,557),MAX(108,,72)) = MIN(944,108) = 108;
                                                            缩放后是得不到 0.666667的比例的,会按0.59的比例来,也就是最后得到的宽高会是
                                                            w = 108 ,h = 108*0.59 = 63.72
 
    kCGImageSourceCreateThumbnailWithTransform          根据exif标记 自动旋转
 
 */
/*
    等比例缩放 (当原图的比例和目标的比例不同时会引起图片有模糊感)
    @param imgdata    原图的数据
    @param scale      缩放倍数 0,1 时没有任何缩放,大于1时则为缩小的倍数,推荐写0
                      这个值将会影响newsize输出的大小。如:w = 108,h = 72 (在原图和目标图1:1的情况下)
                      scale = 3 则最后的ImageSize = (108/3,72/3)
    @param imgorientation 图片方向
    @return 返回缩放图片大小,比例和原图比例一至,不受newsize的比例影响。因此想指定到预想的宽高,这个方法只有在比例一至的情况下才能达到,
            否则要么高是想要的,要么宽是想要的。
 */
- (UIImage *)scaleImageWithData:(NSData *)imgdata toSize:(CGSize)newsize scale:(CGFloat)scale orientation:(UIImageOrientation)imgorientation
{
    CGFloat maxPixelsize = MAX(newsize.width, newsize.height);
    CGImageSourceRef sourceref = CGImageSourceCreateWithData((__bridge CFDataRef)imgdata, nil);
    NSDictionary *options = @{(__bridge id)kCGImageSourceCreateThumbnailFromImageAlways:(__bridge id)kCFBooleanTrue,
                              (__bridge id)kCGImageSourceThumbnailMaxPixelSize:[NSNumber numberWithFloat:maxPixelsize],
                              (__bridge id)kCGImageSourceCreateThumbnailWithTransform:(__bridge id)kCFBooleanTrue,
                              (__bridge id)kCGImageSourceCreateThumbnailFromImageIfAbsent:(__bridge id)kCFBooleanTrue
                              };
    CGImageRef imgref = CGImageSourceCreateThumbnailAtIndex(sourceref, 0, (__bridge CFDictionaryRef)options);
    
    UIImage *retimg = [UIImage imageWithCGImage:imgref scale:scale orientation:imgorientation];
    CGImageRelease(imgref);
    CFRelease(sourceref);
    
    return retimg;
}

///指定大小
- (UIImage *)createRGBAWithUIImage:(UIImage *)srcimage toSize:(CGSize)newsize opaque:(BOOL)opaque
{
    int64_t bitmapBytesPerRow = newsize.width * 4;
    int64_t bitmapByteCount = bitmapBytesPerRow * newsize.height;
    
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    if (!colorspace) {
        NSLog(@"create color space rgb error.");
        return nil;
    }
    
    void *bitmap = (uint32_t*)malloc(bitmapByteCount);
    if (!bitmap) {
        NSLog(@"bitmap memory alloc error.");
        CGColorSpaceRelease(colorspace);
        return nil;
    }
    
    CGBitmapInfo bitmapinfo = opaque? kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big : kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
    
    CGContextRef context = CGBitmapContextCreate(bitmap,
                                                  newsize.width,
                                                  newsize.height,
                                                  8,
                                                  bitmapBytesPerRow,
                                                  colorspace,
                                                  bitmapinfo
                                                  );
    if (!context) {
        free(bitmap);
        NSLog(@"context create error.");
        CGColorSpaceRelease(colorspace);
        return nil;
    }
    
    CGRect rect = {{0,0},{newsize.width, newsize.height}};
    CGContextDrawImage(context, rect, srcimage.CGImage);
    
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    
    UIImage *newImage = [UIImage imageWithCGImage:imageRef];
    CGContextRelease(context);
    CGColorSpaceRelease(colorspace);
    return newImage;
}

#pragma mark - 载剪函数

- (UIImage *)CGContextClip:(UIImage *)img cornerRadius:(CGFloat)radius backgroundColor:(UIColor *)bgcolor
{
    int w = img.size.width;
    int h = img.size.height;
    
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(w, h), YES, 0);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    ///设置背景色
    CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextSetBlendMode(context, kCGBlendModeNormal);
    CGContextFillRect(context, CGRectMake(0, 0, w, h));
    
    CGContextSaveGState(context);
    CGContextMoveToPoint(context, 0, radius);
    CGContextAddArcToPoint(context, 0, 0, radius, 0, radius);
    CGContextAddLineToPoint(context, w - radius, 0);
    CGContextAddArcToPoint(context, w, 0, w, radius, radius);
    CGContextAddLineToPoint(context, w, h - radius);
    CGContextAddArcToPoint(context, w, h, w - radius, h, radius);
    CGContextAddLineToPoint(context, radius, h);
    CGContextAddArcToPoint(context, 0, h, 0, h - radius, radius);
    CGContextAddLineToPoint(context, 0, radius);
    CGContextClosePath(context);

    CGContextClip(context);

    [img drawInRect:CGRectMake(0, 0, w, h)];
    CGContextDrawPath(context, kCGPathFill);
    CGContextRestoreGState(context);
    
    UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return ret;
}

/*
    UIBezierPath 裁剪
    radius 相对于img的size 不要和uiimageview 的size搞混了
 */
- (UIImage *)UIBezierPathClip:(UIImage *)img cornerRadius:(CGFloat)radius backgroundColor:(UIColor *)bgcolor
{
    int w = img.size.width;
    int h = img.size.height;
    CGRect rect = CGRectMake(0, 0, w, h);
    
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(w, h), YES, 0);
    UIBezierPath *radiuspath =[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
    if (bgcolor) {
        UIBezierPath *backgroundPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, w, h)];
        [bgcolor setFill];
        [backgroundPath fill];
    }
    
    [radiuspath addClip];
    
    [img drawInRect:rect];
    UIImage *ret = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return ret;
}

@end

 最后是用于测试的viewcontroller

#import "testVC.h"
#import "testCell.h"

@interface testVC ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) UITableView                   *tabview;

@end

@implementation testVC

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];

    self.tabview = [[UITableView alloc]init];
    self.tabview.delegate = self;
    self.tabview.dataSource = self;
    self.tabview.rowHeight = UITableViewAutomaticDimension;
    self.tabview.estimatedRowHeight = 100;
    [self.tabview registerClass:[testCell class] forCellReuseIdentifier:@"testcell"];
    [self.view addSubview:self.tabview];
    
    [self.tabview mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(0);
    }];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 100;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    testCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testcell"];
    [cell loadDataSet:nil];
    return cell;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

下面打开instrument 的core animation,来看下来回滚动时的FPS如何

主要是针对

- (void)loadDataSet:(id)dataset

{

    self.lb_title.text = @"好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字";

    [self.pic sd_setImageWithURL:[NSURL URLWithString:@"https://images.ihuoqiu.com/article/2018/04/07/huoqiuwang_201804072024469924.png"] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {

        

        dispatch_async(dispatch_get_global_queue(0, 0), ^{

            

            UIImage *scaleimg = image;

            CFTimeInterval start = CFAbsoluteTimeGetCurrent();

            scaleimg = [self useWay1:image]; //方式一

//            scaleimg = [self useWay2:image]; //方式二

//            scaleimg = [self useWay3:image]; //方式三

            

            CFTimeInterval end = CFAbsoluteTimeGetCurrent();

            

            CFTimeInterval timeval = end - start;

            NSLog(@"毫时 %f ms",timeval * 1000);

            

            dispatch_async(dispatch_get_main_queue(), ^{

                self.pic.image = scaleimg;

            });

            

            [self lookImageInfo:scaleimg];

        });

    }];

}

这部分代码进行分晰,全程真机

情况一: 注释这个,即回到没有优化过的状态(存在blended layers,和misaligned images的问题)。只有一个lable和一个SD异步下载图片

    ///clean blended layers

//    [self settingLabelCleanBlended];

//    [self settingAvatar];

    ///使用光栅

//    [self settingeRasterize];


- (void)loadDataSet:(id)dataset

{

    self.lb_title.text = @"好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字";

    [self.pic sd_setImageWithURL:[NSURL URLWithString:@"https://images.ihuoqiu.com/article/2018/04/07/huoqiuwang_201804072024469924.png"] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {

        self.pic.image = image;

    }];

}


再来看下只是把圆角开启有多少影响

///圆角

- (void)settingAvatarRadius

{

    self.avatar.layer.cornerRadius = 22;

    self.avatar.layer.masksToBounds = YES;

}


经过多次试验,在少量的图片存在圆角时影响不是很大也就3 FPS 之间的差距左右(大家可以下代码亲自跑)


再来看下把这个优化后是不是有很大的性能提升?

 ///clean blended layers

    [self settingLabelCleanBlended];

    [self settingAvatar];

    //使用光栅

    [self settingeRasterize];

//    [self settingAvatarRadius];

- (void)loadDataSet:(id)dataset

{

    self.lb_title.text = @"好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字好多字";

    [self.pic sd_setImageWithURL:[NSURL URLWithString:@"https://images.ihuoqiu.com/article/2018/04/07/huoqiuwang_201804072024469924.png"] placeholderImage:nil completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {


        dispatch_async(dispatch_get_global_queue(0, 0), ^{


            UIImage *scaleimg = image;

            CFTimeInterval start = CFAbsoluteTimeGetCurrent();

            scaleimg = [self useWay1:image]; //方式一

//            scaleimg = [self useWay2:image]; //方式二

//            scaleimg = [self useWay3:image]; //方式三


            CFTimeInterval end = CFAbsoluteTimeGetCurrent();


            CFTimeInterval timeval = end - start;

            NSLog(@"毫时 %f ms",timeval * 1000);


            dispatch_async(dispatch_get_main_queue(), ^{

                self.pic.image = scaleimg;

            });


            [self lookImageInfo:scaleimg];

        });

    }];

}

这里用个异步,是因为这几个图片处理有计算对CPU开销,先不考虑内存,尽量模拟图片是后台传来合规格的。

通过观察,优化后60FPS的占比的确高了不少。

因此在解决卡顿时,根据页面的复杂度,优先处理耗时问题,可以用time profiler来进行检测,再来考虑优化blended layers,misaligned,off-screen render。


转载请注明出处。





猜你喜欢

转载自blog.csdn.net/fengsh998/article/details/79862113