前言
好记性不如烂笔头,于是决定把最近了解到的知识点整理,以供后面及时回顾。
总结本篇博客内容:
web首屏优化体验
相信现在大部分客户端都存在webview来支撑业务,而其中就会涉及首屏优化的体验,这是最简单的一种跨平台了,既省人力成本又快速,当然性能没有原生好,个人在去年也是写了大半年的vue,感觉前端对新人上手很快。
web端做的工作
- 域名尽量保持和APP一样,因为系统层面会缓存DNS解析后的ip
- 减少请求量
- 适当的使用缓存
- css和js优化,注意css和js的顺序
原生做的工作
- 1) webview第一次初始化耗时较长,可在APP启动时便进行初始化 2) webview池
- 离线包,包括资源缓存,提前加载到内存,减少静态资源的IO,包括图片和静态资源分开处理,包括可以更深的diff机制
- 预加载数据,抽出中间层由原生代理,在初始化
webview
的同时,并行发起比如用户信息的请求,这样当webview发起请求时,询问原生,如果原生请求完,则返回,如果不成功则等待。 - 客户端提供web端接口,如网络请求,sqlite,客户端可提供DNS与解析/IP直连/长连接等。
移动端网络优化
正常的网络请求是
- DNS解析,请求DNS服务器,获取域名对应的IP地址
- 与服务端建立连接,包括 tcp 三次握手,安全协议同步流程。
- 发送和接收数据,解码数据。
速度
- DNS所遇到的问题:不及时,不可控,缓存,第三方劫持,每次只能解析一个域名
HTTPDNS 自己控制和处理 - 连接 HTTP 2.0 多路复用和 Keep-Alive
- 数据压缩 Protobuf,解码速度快体积小
弱网
如何确定弱网
httprtt(http Round-Trip Time)又名TTFB(Time to first byte),指从客户端请求的第一个字节开始发送到接收到http header的第一个字节的时间差。httprtt的时间如果过长,一方面是客户端本身接入网络质量的问题,另一方面是服务的延时比较大。
这里还是推荐看看百度APP分享的博客。还有一篇集合。
- 提高连接成功率,梯式并发连接,其中一个连接都关闭。提高弱网下的链接成功率,又不会增加服务器的资源消耗
- 制定合适的超时时间,及时定位,减少等待时间,加快对超时的判断,尽早重试
- 调优TCP参数,适合移动端的业务特性和网络环境,混合慢启动等。
安全
- HTTPS
- 网络传输过程中数据加解密
- 。。。
崩溃问题分析
一般而言有两种崩溃信息,一种是可以通过信号监听收到的,一种是不能通过信号监听收到的。对于前者一般有数组越界,子线程操作UI,kvo,野指针等。
对于后者多存在于,后台被杀,主线程卡顿超时,触发watchdog机制,oom。
在这里我们分析后者信号捕获不到的情况。mach异常到BSD转换成信号,所以可以监听信号
常见的几种信号,访问未知地址,比如没有权限,重复释放同一个内存,非法指令,非法地址等。
后台被杀
我们可以自己起一个后台任务,当然这个后台任务不宜处理大数据或大量读写操作,时间阈值是3min,所以我们可以起个定时器,快到这个时间的时候,如果APP没有挂开始记录当前线程信息或调用栈,作为最接近崩溃的环境。
主线程卡顿
我们这里借助runloop,runloop更为友好的线程调度,runloop主要接受两种不同类型的输入源:1)从另一个线程或另一个应用传来的消息 2)定时器重复间隔的事件。
方案自己启个子线程进行监控,主要是监控两个地方,即将进入休眠之前和唤醒之后,如果这两个点超过了我们设置的3s,而这3s是可以根据watchdog机制来设置。原则上10s也不为过,但是更好的监控到用户感知最明显的卡顿为佳。当触发这个事件后,通过plcrashreporter进行收集堆栈信息,因为直接获取系统的不完整。
(Runloop 的目的,当有事情要处理就保持线程工作,如果没有就让线程休眠,更好的提高用户体验。)
oom定位
可以通过腾讯开源sdk,或者灰度测试内存阈值,然后dump出所有内存信息,对象名称,对象个数,个对象的内存等。
电量优化问题整理
这里不得不吐槽下,某宝真的很费电🙄
背景
假如测试某天说某个页面的耗电严重,之前几个版本却好好的,并且这几个版本也没有改变
基本问题分析
- 首先最简单最快捷的就是用排除法,注释掉相应代码进行检测
- 如果还有问题,可能就是某个第三方或者其他线程引起的,此时可以获取每个线程的CPU使用率,通过task_threads函数可以获得所有线程信息,thread_basic_info里有记录CPU使用率的字段cpu_usage,此时检测所有线程的使用率,如果如果超过90%的话,就证明有问题,并且dump堆栈信息进行记录。
- 尽量避免CPU做大量数据的复杂计算,尽量让服务端去处理,如果必须APP内处理,可通过GCD,专有的QOS模式,NSQualityOfServiceUtility 系统做了专门的电量优化,包括大量的网络请求
- 再有就是I/O,模仿SDWebImage使用原生NSCache,减少I/O操作,降低能耗。如果有监听file变动的话使用原生的dispatch_source,而不是轮询去检测。
其他情况
- iOS9之后,iPhone增加了低电量模式,APP可监听此通知,减少一些非必须的请求或timer等情况
- 优化定位和动作(Motion) 如果你的app只是需要快速确定一下用户的位置,最好用CLLocationManager的requestLocation (iOS9引入)方法。定位完成之后会自动让硬件断电。包括定位精度,及时停止定位等情况。用户摇晃,移动都会触发加速计、陀螺仪等硬件检测,所以不需要时及时取消
- 蓝牙在不必要时不要扫描外设,不要轮询检测。
流量监控
一个请求主要包含请求行,请求头,请求体,响应行,响应头,响应体。所以就需要整体监测,看了一些开源的第三方大部分只监控body,和记录body,所以我们还需要记录line 和 header
这里主要是借助众所周知的
NSURLProtocol
,主要记录实体的几个字段是,host/path type(请求还是响应) line-length header-lenth body-length 和 总length。
整体监控是一个套路,所以没啥好说的,主要有以下几个注意点。
- 需要注意的是请求中cookie,臃肿的cookie也是消耗流量的一部分。
- 还有gzip,我们客户端拿到的数据实际上是解压过后的数据,所以直接计算是不准确的,需要模拟gzip压缩再计算大小。