微信读书解读

来源:互联网 发布:vb的http的get请求 编辑:程序博客网 时间:2024/04/28 14:57

微信读书 iOS 性能优化总结
发表于 2016-05-03 | hypo | 2 Comments
微信读书作为一款阅读类的新产品,目前还处于快速迭代,不断尝试的过程中,性能问题也在业务的不断累积中逐渐体现出来。最近的 1.3.0 版本发布后,关于性能问题的用户反馈逐渐增多,为此,团队开始做一些针对性的性能问题优化。本文将从发现问题、解决问题和预防问题三个方面进行总结。

如何发现性能问题
不同于一般的 bug,性能问题因为并没有统一的标准,而且与用户的机器环境相关性较大,所以往往是在产品上线后才被发现,也导致解决问题的周期很长。微信读书 1.3.0 版本之前,性能问题基本都来自于用户反馈(包括测试人员),受限于测试时间和用户反馈的积极性,性能问题往往到了比较严重的程度,开发人员才真正发现问题。

但是,移动应用要保证良好的用户体验,产品在性能方面的表现极其重要。为了尽可能早、尽可能全面地收集产品的性能问题,就避免不了对产品做性能监控。我们主要从两个维度进行了监控:

业务性能监控,是指在App本地,业务的开始和结束处打点上报,然后后台统计达到监控目的;

卡顿监控。卡顿监控的实现一般有两种方案:

(1)主线程卡顿监控。通过子线程监测主线程的 runLoop,判断两个状态区域之间的耗时是否达到一定阈值。具体原理和实现,这篇文章介绍得比较详细。

(2)FPS监控。要保持流畅的UI交互,App 刷新率应该当努力保持在 60fps。监控实现原理比较简单,通过记录两次刷新时间间隔,就可以计算出当前的 FPS。

但是,在实际应用过程我们发现,无论是主线程监控,还是 FPS 监控,抖动都比较大。因此,微信团队提出了一套综合的判断方法,结合了主线程监控、FPS监控,以及CPU使用率等指标,作为判断卡顿的标准。

微信卡顿监控

微信读书接入了RDM(bugly)的卡顿监控(也是基于微信团队的卡顿标准),通过下发配置,对现网用户进行抽样检测,并上报卡顿的堆栈信息。这对于我们掌握现网用户的卡顿状况起到了非常大的帮助。

性能问题的解决方法
产生性能问题的原因多种多样,因此解决的办法也不尽相同,比较常用的大概有以下几种:

1.优化业务流程

性能优化看似高深,真正落到实处才会发现,最大的坑往往都隐藏在于业务不断累积和频繁变更之处。优化业务流程就是在满足需求的同时,提出更加高效优雅的解决方案,从根本上解决问题。从实践来看,这种方法解决问题是最彻底的,但通常也是难度最大的。微信读书在优化阅读中各种操作(如,书签、划想、想法等)性能时,就是从业务流程的角度来进行优化。如下图:

阅读划线优化

2.合理的线程分配

由于 GCD 实在太方便了,如果不加控制,大部分需要抛到子线程操作都会被直接加到 global 队列,这样会导致两个问题,1.开的子线程越来越多,线程的开销逐渐明显,因为开启线程需要占用一定的内存空间(默认的情况下,主线程占1M,子线程占用512KB)。2.多线程情况下,网络回调的时序问题,导致数据处理错乱,而且不容易发现。为此,我们项目定了一些基本原则。

UI 操作和 DataSource 的操作一定在主线程。
DB 操作、日志记录、网络回调都在各自的固定线程。
不同业务,可以通过创建队列保证数据一致性。例如,想法列表的数据加载、书籍章节下载、书架加载等。
合理的线程分配,最终目的就是保证主线程尽量少的处理非UI操作,同时控制整个App的子线程数量在合理的范围内。

3.预处理和延时加载

预处理,是将初次显示需要耗费大量线程时间的操作,提前放到后台线程进行计算,再将结果数据拿来显示。

延时加载,是指首先加载当前必须的可视内容,在稍后一段时间内或特定事件时,再触发其他内容的加载。这种方式可以很有效的提升界面绘制速度,使体验更加流畅。(UITableView 就是最典型的例子)

这两种方法都是在资源比较紧张的情况下,优先处理马上要用到的数据,同时尽可能提前加载即将要用到的数据。在微信读书中阅读的排版是优先级最高的,所在在阅读过程中会预处理下一页、下一章的排版,同时可能会延时加载阅读相关的其它数据(如想法、划线、书签等)。

4.缓存

cache可能是所有性能优化中最常用的手段,但也是我们极不推荐的手段。cache建立的成本低,见效快,但是带来维护的成本却很高。如果一定要用,也请谨慎使用,并注意以下几点:

并发访问 cache 时,数据一致性问题。
cache 线程安全问题,防止一边修改一边遍历的 crash。
cache 查找时性能问题。
cache 的释放与重建,避免占用空间无限扩大,同时释放的粒度也要依实际需求而定。
5.使用正确的API

使用正确的 API,是指在满足业务的同时,能够选择性能更优的API。

选择合适的容器;
了解 imageNamed: 与 imageWithContentsOfFile:的差异(imageNamed: 适用于会重复加载的小图片,因为系统会自动缓存加载的图片,imageWithContentsOfFile: 仅加载图片)
缓存 NSDateFormatter 的结果。
寻找 (NSDate *)dateFromString:(NSString )string 的替换品。
//#include

0 0
原创粉丝点击