最近读了一本关于移动web开发性能优化方面的书 《High Performance Mobile Web》,这本书系统全面的介绍了性能优化的知识点,对我来说至少以后再回答 “你是怎么做性能优化的?” 这个问题,不会再简单罗列诸如懒加载图片、缓存 js/css、按需加载这些了,而是会从不同的方面系统的给出优化点。接下来的系列会对这本书做个简单的总结。
首先谈谈移动设备和PC之间的不同,包括硬件、网络、操作系统、引擎、webview等方面。
1、硬件条件
现在市场上有很多种类型的移动设备,诸如平板(ipad…)、智能手机(iPhone, HTC…)、可穿戴设备(iwatch…),对于web开发来说,这些移动设备和PC存在着很大的差别如分辨率,最直观的感受就是屏幕大小不一样,从性能优化的角度来说,不同点在于:
- CPU:核心工厂,解析下载执行的地方
- 内存:存储DOM树、图片、数据等
- GPU:开启硬件加速渲染
- GPU 内存:存储GPU渲染的层、图片、数据等
- …
比如我自己的 Mac Pro 的内存是 8GB,iPhone 6s 的内存是 2GB
2、网络情况
上网的途径无非就是 WiFi 或者数据流量,WiFi 可以是稳定的如家庭、工作网络,也可以是不稳定的如热点,流量的话更不用说了,偏僻的地方手机都没有信号。
平时我们谈到流量都是说 2G、3G、4G,这些名字是什么意思呢?你可能会猜到 G 就是 Generation 就是 代 的意思,所谓 2G 就是第二代XXX,3G 就是第三代XXX。嗯,事实也就是这样,除了这些名字之外,还有其他名字表示:
- GPRS (2G)
- EDGE (2.5G, 3G)
- UMTS (3G)
- WCDMA (3G)
- LTE (4G)
- …
虽然身边的人大都是 4G 用户,但是移动网络是不稳定的,看到是 4G 信号也不表示用的是 4G,很可能降到了 3G,更何况我这种之前一直使用 3G 的用户,在地铁上就没打开过网页。。。
PS:The State of LTE (November 2016) 可以看到全球 4G 的使用率
网络有带宽、延迟的特性,在移动开发中,我们是否也需要关注这些呢?
带宽
带宽固然也大越好,但是相比较我们传输的文本文件的大小,似乎也没有很大的影响,除非你要求实时传输,做视频音频流这些对带宽具有高要求的需求
延时
计算机网络有一个概念:RTT(Round-Trip-Time),表示从发送端发送数据开始,到发送端收到来自接收端的确认,总共经历的时延。不管怎么样延迟是避免不了的,这是因为手机连到网络上需要经过发射塔、运营商网关、服务器,然后取得数据之后再反向走一遍。
PS:书中提到 2G 下有 1s 的延时,4G 下有 180ms 的延时
radio rate
手机使用无线电和发射塔通信,无线电的使用会消耗电量,所以操作系统会尽量减少它的使用,这意味着如果没有 App 使用网络,手机会把无线电状态从 active 切换为 idel,当有软件请求数据时,会重启无线电,这个过程也花费时间
PS:书中提到 3G 下这个时间可以达到 2.5s,4G 下通常少于 100ms
3、操作系统
市场上主流的手机操作系统有 iOS, Android, Windows,平时开发我们只会考虑前两者。此外还有一些其他操作系统,比如 BlackBerry, Firefox OS, Symbian...,一般不考虑这些。
PC 上的话,主流的有 Windows, MacOS, Linux, Ubuntu...。
PC:相比较移动设备,PC开发的时候一般不会去判断系统类型
4、引擎
引擎分为渲染引擎和 js 执行引擎。
4.1 渲染引擎
渲染引擎(布局引擎)是用来下载、解析、渲染 HTML、CSS的,包括相关的内容如SVG、图片。
目前主流的操作系统如 iOS、Android... 等都是使用 webkit 渲染引擎。除了 webkit,还有其他的渲染引擎可供选择如 Blink, Trident, Gecko, Presto:
webkit是Apple基于KHTML创建并使用在safari中的一个开源项目,引擎中和渲染布局相关的代码叫做WebCore。blink是Google基于webkit开发的,目前chrome, opera都在用blink引擎。Trident是IE专有的引擎,自从windows 10以后,微软又基于Trident重写了一个引擎EdgeGecko是Mozilla维护的开源引擎Presto是opera特有的引擎,自从opera 12后就切换为blink了
4.2 执行引擎
执行引擎是一个解释执行代码、管理内存的运行时环境。有些引擎会包含 Just-In-Time(JIT) 编译有些则不会,那他们有什么差异?
没有 JIT 编译的引擎会边执行 JS 代码边解释,而有 JIT 的会在执行之前编译为机器码,如果再次执行相同的代码无需再翻译直接执行机器码就好了。
javaScriptCore
JavaScriptCore 引擎是 WebKit 中默认的引擎,在早期阶段只有解释器来解释执行 JavaScript 代码,性能不是特别突出,后来经过优化产出了 Nitro,也正是 safari 浏览器所使用的
V8
Google 开发的开源js引擎,V8在执行之前会把 js 代码编译为机器码从而提高效率,更进一步使用了内联缓存等优化性能。
V8 是 Google Chrome 浏览器内置的JavaScript 脚本引擎 同时也是 Node.js 支持的引擎
其他主流的 JS 引擎:IE 的 Chakra,Mozilla 的 monkey 系列 JaegerMonkey, IonMonkey...
5、web 平台
web平台指的是我们编写的web应用在哪里被解析执行,换句话说就是指它的宿主环境。
平时开发最经常打交道的环境有两种:浏览器和app,一个是直接在浏览器地址栏打开能访问的到,一个是嵌套了app的外壳,即 webview 的方式
5.1 browser
浏览器是最熟悉不过了,从PC开始就已经和它打交道了,Chrome、Firefox、Safari、IE。。。然而在移动设备上浏览器会更加五花八门
现在的手机都会自带一个浏览器出厂,称为 stock browser/preinstalled browser,这个浏览器的问题在于如果我们不更新手机系统,它就不会更新。
iOS 系统上的浏览器会比较简单点,它的预装浏览器是 safari,如果不是开发人员的话,很少会再去装其他的浏览器。如果装其他浏览器的话如 chrome, firefox, uc...,其实和 safari 都是使用一样的引擎,这是因为 iOS 系统的封闭性,第三方浏览器只能优化功能、定制UI等,所以整体上 iOS 上的 bug 会比较简单一致
Android 就不一样了,它是一个开源的操作系统,4.3 之前使用的是 webkit 的 webview,4.4 之后就转为基于 chromium 的 webview 了,也就是使用 blink/v8 渲染了。
因为 Android 自带的浏览器性能并不好,就导致各个厂商、浏览器厂商开发自己的浏览器,有的会使用 webkit 有的又使用 chromium,这就导致渲染会存在差异,修改了一个手机的问题,另一个手机可能还存在问题。
5.2 webview
webview 是一个类似于按钮、输入框等的原生控件,它允许原生 App 包含并执行 web content,webview 可以使用整个屏幕或者一部分。webview 能做些什么?
- 执行 js 代码
- 显示富文本内容
- 创建完整的用户界面
- 创建一个 in-app browser
- 创建一个 pseudo-browser
- ….
in-app browservs pseudi browser
什么是 in-app browser ?有些原生App想展示一个页面,但是并不希望你离开App,就在 app 内部提供了一个渲染环境。比如在 evernote 内打开一个链接,并没有调用 safari 浏览器
pseudo-browser 是一个被认为是浏览器的原生应用,但是它没有自己的渲染、执行引擎,使用的是系统原生的 web view。从用户的角度来说它是个浏览器,从开发者角度来说,它就是一个具有特殊 UI 的 webview。iOS Chrome 就是这样一个 pseudo-browser
他俩的区别在于 in-app browser 场景下的 app 并不是一个浏览器,你不能说evernote是个浏览器,即便它在app内部打开了一个页面
iOS
iOS 8 之后,有两个 webview 可以用:UIWebView / WKWebView
Android
Android 使用的是基于 webkit 的 webview,Android 2.x 性能非常慢,虽然在 4.0 - 4.3 有所好转,但是在性能兼容性上并没有显著的提升。所以很多厂商都决定使用新版本的 webkit 或者 chromium 替换默认的 webview ,这就导致每个设备、操作系统对应的 webkit/chromium 的版本可能不一致
在 Android 4.4 之后,Google 决定使用 chromium。在 Android 5.0 之后,基于 chromium 39 版本的 webview 可以自动从 Google Play Store 更新,意味着用户不必手动更新系统就能体验最新webview的特性了
End.