前段时间,依据bugly数据,并借助苹果instruments,针对国内iOS客户端,完成了性能优化的部分工作,用时大概3个月,虽然时间慢长,但是效果显著,仅从bugly数据来看,卡顿指标下降明显,同时客户端的流畅度的提升在某些页面或是业务场景下也是可感知的。卡顿产生的原因有很多,各种理论理念,网上资料都很全面,优化方案也是百花齐放,这里我不写了,我主要写一下iOS客户端这次优化工作的相关内容。
具体优化内容
-
更换底层Json<->Model转换工具,由原来的MJExtension更换为YYModel。YYModel的转换效率是MJExtension的倍数级,提升巨大,尤其是对于列表类数据,提升明显。
-
优化调整代码中for循环业务逻辑,减少当大量数据时for循环次数,甚至消除某些for循环逻辑。
-
客户端网络请求,数据处理逻辑,全部移到异步子线程,充分利用设备多核优势,减轻主线程工作量,减少主线程阻塞。网络请求中的参数签名逻辑,也全部迁入异步线程。
-
缓存数据的存取以及课程文件的解压工作优化,存储逻辑全部迁入异步子线程,读取逻辑根据相关场景以及业务逻辑逐步调整,迁入异步线程,或异步主线程延后处理。课程包以及相关文件的解压或者解码工作全部迁移至异步子线程。
-
UI中涉及到多次耗时计算的逻辑,比如帖子cell高度,评论cell高度,甚至多处label高度计算的逻辑,均根据相关场景进行针对性逻辑调整,核心就是在页面展示内容未改变的情况下,做到无论如何刷新UI,相关耗时计算只执行一次。其中有些是将计算过程提前至网络请求数据处理阶段,有些是异步子线程计算完毕后切换主线程进行局部刷新。
-
将客户端底部5个tab主页的初始化工作,提前至APP启动阶段,异步子线程负责初始化,然后切换至主线程刷新UI,在提升页面加载速度的同时,进一步减轻了主线程的压力。
-
对于频繁刷新或者全量刷新UI的相关逻辑,进行逐步优化。一是优化部分逻辑,尽量减少UI刷新次数,尤其是在UI内容为改变的情况下。二是对UI刷新逻辑做diff处理,只刷新需要刷新的部分UI,减少不必要的全量刷新。
-
在线视频播放,视频相关参数获取时机由原来的进入页面时主动阻塞式计算延后至视频缓冲至可播放时异步获取,即消除了阻塞主线程的问题,同时也满足现有需求。
-
对于UI渲染部分,尤其是离屏渲染这种既会带来性能损耗又会带来内存损耗的部分,做了针对性的调整,调整并优化代码逻辑,抑或调整UI处理方式,以达到最优。
-
针对有大量逻辑或者UI需要集中在主线程中处理或是渲染的部分业务场景,进行切片、分步、延时处理,在拆分这部分时需要,具体业务具体分析。代码示例如下:
//TODO: 优先级最高任务 dispatch_async(dispatch_get_main_queue(), ^{ //TODO: 优先级次之任务 dispatch_async(dispatch_get_main_queue(), ^{ //TODO: 优先级再次之任务 }); });
-
对于需要消耗大量内存的操作或者大量操作CPU的工作,比如解压文件,图片解码渲染,或者缓存的读取,长列表操作,除了线程的调整外,同时优化了相关逻辑,尽量减少计算的次数,读取的次数,解码渲染的次数,减轻CPU压力。不需要的变量特别是长列表类型,尽量做到及时释放,及时释放内存。
-
对于客户端中凡是涉及到列表数据,然后刷新UI的场景。创建串行队列,进行数据处理,然后切回主线程操作DataSource和UI。
-
第三方SDK,发现问题,及时反馈,督促并跟踪第三方解决问题的进度,主要体现在ShareSDK和环信SDK,耗时虽然很长,但是最终都得以解决。
大部分工作都是围绕上面13个点去完成的,当然还有很多细节的点并没有提到。这次调整优化,从底层框架,到网络层,到数据缓存,再到数据解析与处理,再到上层UI,都有涉及,在这里就不一一列举了。可概括如下:
- 优化业务流程
- 合理的线程分配
- 预处理以及延时加载
- 增量或者差量UI刷新
- 缓存使用与优化
- 使用正确的API
优化成果
数据依据主要来源于bugly统计,优化前后效果对比明显,优化后卡顿维持在0.3%左右。部分被优化后的页面,比如帖子列表相关页面,聊天页面等流畅度的提示是可感知的。
总结
优化工作是一个繁琐而复杂的过程,尤其到后期更是如此,它涉及到代码的重构,逻辑的重写,甚至一些原有设计方案的推到重来,甚至涉及到底层架构,牵一发而动全身,它还要求开发人员必须熟悉现有相关逻辑,了解原有的产品需求等等,这些缺一不可,不然在优化的过程中总会带来不可预料的后果,甚至引来更可怕的crash。这次优化过程中就带来了如下两大问题:
- 代码逻辑调整不彻底,出现了多线程读写的问题,导致了部分crash。
- 异步线程的加入,影响了相关变量或者对象的生命周期,主要集中在block这部分,导致数据丢失。
不过,幸运的是这些问题都及时得到调整和修复。
对于APP来讲,性能问题普遍存在,无可避免。由于前期的对这部分工作的忽视,导致客户端APP被毒害至深,后期修复以及优化不仅体量大范围广,而且难度增加,不可控性和风险性也随之增加。所以说,与其花费大量时间,查找线上版本的性能问题,不如提高整体团队成员性能优化意识,借助性能查找工具,将性能问题尽早暴露在开发阶段,达到预防为主的效果。接下来,在以后的版本迭代与开发过程中,性能问题,Crash问题,将会是国内iOS开发团队的日常工作内容。
- 持续跟踪bugly数据,及时优化以及修复线上暴露的问题。
- 新需求开发,代码设计阶段,将充分考虑性能问题。
- 提高代码的规范性,健壮性,稳定性。
- 新需求开发过程中,及时跟踪bugly上开发版本的数据反馈,当前开发版本引发的新问题,尽量保证新版上线时都得到及时修复与优化。
- 新需求开发,尤其涉及到复杂设计或是需大量计算的业务场景,功能开发完毕后可通过instrumens工具或其他性能工具,针对新功能新需求进行查找、测试。
推荐文章
关于iOS 性能优化梳理: 基本工具、业务优化、内存优化、卡顿优化、布局优化、电量优化、 安装包瘦身、启动优化、网络优化等
可加群一起交流共同学习:801216530。
网友评论