背景

前不久我做了一个富文本编辑工具,编辑器遇到了一个性能问题是添加多张图片,当滚动编辑区域,遇到图片切换的时候会有明显的卡顿现象。这篇文章基于这个卡顿的性能问题进行性能瓶颈的分析以及做对应的优化。

可以打开这个链接 iOS使用UITableView实现的富文本编辑器 查看我的文章,这篇文章所用的项目也是基于这个项目的。

结果

最终的分析优化的结果把时间从90ms的数量级降低到了2ms的数量级,达到了一个比较流畅的效果。具体的分析优化步骤请往下看。

问题分析

既然问题是发生在图片切换的时候,图片是放在单独的一个Cell中的,那么就尝试在Cell的渲染方法 cellForRowAtIndexPath 添加两个Log,查看方法执行所用的时间。

对应的结果:

  1. 2017-08-11 06:12:48.744 RichTextEditDemo[6867:1064632] ======begin render cell
  2. 2017-08-11 06:12:48.749 RichTextEditDemo[6867:1064632] ======end render cell
  3. 2017-08-11 06:12:49.261 RichTextEditDemo[6867:1064632] ======begin render cell
  4. 2017-08-11 06:12:49.266 RichTextEditDemo[6867:1064632] ======end render cell

从日志打印的时间上看,大概每渲染一个Cell只要发几毫秒的时间,貌似问题不会出现在这个位置,然而这并不是真相,很明显的,其他地方不会影响到,所以得用更高级的分析工具去分析查看。

发现问题

Instrument是一个很好的性能分析工具,可以分析内存分配、内存泄漏、网络情况、CPU占用等和性能有关的问题,当前的性能问题是耗时的问题,可以使用 Instrument 的 Time Profiler 进行分析

让这个列表滚动,并且有进行图片Cell的切换

可以看到Time Profiler 有下面的记录,红色框中就是Cell切换所耗费的时间值,这个时间的增长很明显的高于其他值了,所以这个就是我们要定位到的地方了。

Tips

  • alt + 鼠标滚轮 -> 缩放时间轴
  • shift + 鼠标滚轮 -> 移动时间轴
  • 按住鼠标框选 -> 选择和定位时间轴

第一步要在时间轴上框选一个范围,标识选择这个范围进行分析,才能准确定位到这个问题,如图(1)位置所示;第二步要选在堆栈中的某一个函数,一般的选择到OC函数调用,更底层的函数调用就到了CF层是C语言实现的就不好分析了,所以这里选择的是 [UIImage drawInRect:blendMode:alpha] 这个函数分析,可以看到这个函数调用说花费的时间是 92ms,这是一个比较长的时间了,所以应该就是这里导致的卡顿了。

这个函数花费的时间和image图片的大小有关系的,选择另一个时间峰值范围,这个时间峰值范围是发生在小图之间的切换的

这个地方耗费的时间就比较小一点,不过也是达到了25ms,对于性能也是有一定的影响的。

解决问题

以上的分析可以得出结论:[UIImage drawInRect:blendMode:alpha] 函数的调用是会导致性能问题的,因为UITextView内部处理图片的方式是通过调用 [UIImage drawInRect:blendMode:alpha] 函数绘制图片实现的。

既然是UITextView内部的处理方式,所以这个函数调用行为是应用层改变不了的,不过UIImage对象是我们可以控制的,或者可以改变图片的显示方式来达到优化的目的,所以就有了以下的两种方案。

方案1

第一种方案就是对预览的图片进行压缩,然后再设置到NSTextAttachmen中,放到UITextView中显示

  1. textAttachment.image = self.image;
  2. // ===> 修改为
  3. // scaletoSize用于压缩原始的图片,textAttachment中的image对象是压缩过后的
  4. textAttachment.image = [self.image scaletoSize:showImageWidth];

这样修改之后大图的滚到加载时间减少到了40ms左右

虽然减少了一半的时间,不过,40ms的时间还是比较长的,下面会继续进行优化。

方案2

上面的方案进行了图片的压缩,时间的耗费还是因为 [UIImage drawInRect:blendMode:alpha] 函数的调用,所以有没有一种更好的方案呢?答案是肯定的,可以把传给UITextView的image压缩成一个很小的,(这一步也可以不必,传递一个空的UIImageView对象即可,这里设置图片的主要原因是图片区域需要一个编辑的光标),然后在 UITextView 所对应的图片区域添加一个UIImageView,在UIImageView中设置原始的图片即可,这种方案会比方案1的效果好很多。

方案二几个修改点:

1.设置NSTextAttachment的image为空的UIImage对象

  1. //....
  2. NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
  3. CGRect rect = CGRectZero;
  4. rect.size.width = showImageWidth;
  5. rect.size.height = showImageHeight;
  6. textAttachment.bounds = rect;
  7. textAttachment.image = [UIImage new];
  8. NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:textAttachment];
  9. //....

2.Cell添加ImageView显示Image

  1. [self.imageContentView mas_remakeConstraints:^(MASConstraintMaker *make) {
  2. make.left.equalTo(self).offset(_imageModel.imageFrame.origin.x);
  3. make.top.equalTo(self).offset(_imageModel.imageFrame.origin.y);
  4. make.height.equalTo(@(_imageModel.imageFrame.size.height));
  5. make.width.equalTo(@(_imageModel.imageFrame.size.width));
  6. }];

下面是使用方案2优化之后的分析图

图中可以看到 cellForRowAtIndexPath 方法总共占用了2ms的时间,从分析的堆栈中可以看到 UITextView setAttributedText: 方法才占用了1ms的时间,所以这个提升是很明显的,因为传递了一个空的UIImageView对象,不用执行 [UIImage drawInRect:blendMode:alpha] 方法,使用了UIImageView直接设置Image的方式几乎不会占用时间,所以堆栈中看不到 [UIImageView setImage:] 方法调用的时间。

总结

Instrument是一个很好工具,你用它可以很方便的帮我们定位到性能问题,问题找到了,那么也就很容易找到解决方案了。

作者:aron1992
来源:51CTO

IOS使用Instrument-Time Profiler工具分析和优化性能问题相关推荐

  1. 使用Chrome的timeline工具分析web应用性能

    Development tool的timeLine功能,可以用来做前端的性能分析. 例如我们想分析frontend Opportunity点了Note tab的性能: 因为我们用的是UI5 frame ...

  2. 前端如何进行网站性能分析及优化性能

    目录 1.分析网站性能常用的方式 1.1 chrome dev Tools 1.2  Lighthouse 1.3 第三方收费方案 2.介绍一个常用的性能分析工具 LightHouse 2.1 特点: ...

  3. webuploader 怎么在react中_React 项目性能分析及优化

    点击上方"前端技术砖家"关注 性能优化不是一个简单的事情,但在 95% 以上的 React 项目中,是不需要考虑的,按自己的想法奔放的使用就可以了. 我认为性能优化最好的时候是项目 ...

  4. React 项目性能分析及优化

    我们看下 Frames(帧) 这一栏,能看到红框中在一次输入中,776.9 ms 内都是 1 fps 的.这代表什么意思?我们知道正常网页刷新频率一般是 60 帧,也就是 16.67ms(1s/60) ...

  5. android profiler 简书,使用AndroidStudio提供的Android Profiler工具和mat进行内存泄漏分析...

    废话不多说直接说流程 给项目中集成LeakCanary工具进行内存泄漏检测.发现有内存泄漏后该工具会进行提示 有内存泄露后我们需要使用as的profiler工具进行分析并获取到.hprof文件,步骤如 ...

  6. 【Android CPU 优化】Android CPU 调优 ( Trace 文件分析 | Android Profiler 工具 | CPU Profiler 工具 )

    文章目录 一.Android CPU 优化 二.CPU Profiler 工具 三.相关资源 一.Android CPU 优化 在 Android 中 , 出现 动画掉帧 , 页面切换白屏 , 卡顿 ...

  7. 京东怎么做《IOS系统APP耗电量检测分析和优化》?

    耗电量不仅是衡量应用性能表现的一个重要指标,同时也是用户体验的重要组成部分.要做好⼀款APP,不仅仅是实现功能那么简单,我们需要考虑很多性能指标,让用户用的更爽.在开发过程中,要充分考虑到各项性能指标 ...

  8. ios性能分析和优化

    http://game.ceeger.com/Manual/iphone-InternalProfiler.html http://game.ceeger.com/Manual/Profiler.ht ...

  9. SQL Server Profiler工具

    SQL Server Profiler工具 原文:SQL Server Profiler工具 一.SQL Profiler工具简介 SQL Profiler是一个图形界面和一组系统存储过程,其作用如下 ...

最新文章

  1. pytorch之卷积模块、池化、激活函数(可视化)
  2. Py之docx:Python库之docx简介、安装、使用方法详细攻略
  3. html中的特殊符号
  4. 鼠标划过图片进行缩放效果
  5. easyui中的datetimebox 只显示年月日_云计算自动化运维之linux-工作中常用命令总结(中)...
  6. qml: 自定义滚动条;
  7. 什么是deployment 声明式升级应用
  8. 学计算机的学数学分析吗,学计算机专业是不是对数学的要求很高?
  9. android 仿饿了么地图,微信小程序仿饿了么地址定位、筛选与回传
  10. Noip 模拟练习9
  11. 人工智能谓词逻辑——猴子摘香蕉问题
  12. 关于Flash闪存的扇区、块、页
  13. vue项目中使用高德地图实现添加点标记和获取点击位置信息
  14. 黑苹果安装 hackintosh Lenovo Y50-70 TransMac 破解版安装
  15. 电脑突然没有网络,发现电脑无法打开WiFi列表,打开设备管理器,发现intel(R)wireless-ac 9462感叹号
  16. layui table动态选中_ODME与动态交通分配——DTALite使用测评
  17. JAVA spring hessian_Springboot写的Hessian例子
  18. adobe Adobe Acrobat DC资源下载
  19. 《思考,快与慢》学习总结
  20. STM32学习——TFTLCD原理

热门文章

  1. String indexOf 算法
  2. 一键安装lamp系统
  3. 修改MySql默认存储引擎为InnoDB,启动报错
  4. linux中的pppoe拨号上网
  5. 虚拟机 硬盘容量不够 增大的方法
  6. ubuntu 12.04/11.10 PPA 安装 Nvidia 295.59
  7. objective-C NSNotificationCenter (通知)的使用方法
  8. CentOS 6.0安装VNC Server
  9. [20180408]那些函数索引适合字段的查询.txt
  10. python3 urllib