前端优化系列 - 初始化的性能影响分析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介:

前言

数据表明,即使在资源有缓存的情况下,页面首次访问的耗时也是非首次访问的两倍。

为什么首次访问这么耗时呢,时间去哪里了?本文详细分析页面首次访问耗时的原因。

常见的初始化

我们先看看打开一个页面,需要经过那些流程。可能会包括,外壳初始化,内核初始化,创建WebView,创建Renderrer进程,初始化V8 JS引擎,初始化IPC,初始化CC,初始化网络库,初始化文件系统,初始化数据库,启动ServiceWorker线程,DNS解析,创建网络连接,页面服务器初始化,等等。这些流程前端一般是看不见的。

在讨论具体的耗时之前,我们先约定,下文所有的数据都是基于Nexus 5手机。不同的手机的性能数据差异极大,一些高端手机(比如,iPhone X),性能可能是中低端机的好几倍。

外壳初始化

我们先看看浏览器外壳的初始化,用户点击桌面图标启动浏览器,浏览器会进入一个状态机,按步骤初始化各个模块,很多模块的初始化会涉及网络,文件IO,JNI,等等操作,这些都会有一定的耗时。

当然,全新安装首次启动,外壳初始化的过程中,一般最耗时的是加载SO和JAR,其中使用DexClassLoader去加载JAR文件,在一些中低端机器,特别是Android 5.0以前的系统,耗时是以秒计算的,有些甚至可以达到10秒。非全新安装首次启动,加载SO和JAR的耗时会大幅下降,大概在500ms。

我们为什么需要关心浏览器启动的耗时呢?一些场景下,用户通过扫码或者点击桌面图标去访问页面,这个过程就会包含浏览器的启动流程,我们有必要了解这其中发生了什么。

对于内置浏览器内核的App,比如,支付宝,手淘,情况又是怎样的呢?我们这边暂时没有支付宝和手淘的启动性能数据,但模块初始化,加载SO和JAR,这些流程都会有,时间不会很小。

在外壳初始化耗时方面,有没有一些比较好的解决办法呢?

最好的办法就是进程保活,现在国内很多手机厂商都会给微信,支付宝,等超级App去进程保活,用户在任务列表杀掉了应用,其实进程还在。

如果是多进程的情况,可以提前创建进程,比如,微信和支付宝的小程序,用户访问时可以直接使用预创建的进程。

内核初始化

我们再来看看内核的初始化,与外壳的初始化类似,内核的初始化也需要加载SO和JAR,创建WebView和初始化各个功能模块。

在创建WebView方面,全新安装首次创建约1秒,非全新安装首次创建约300ms,第二次创建约15ms。

首次创建Renderrer进程,初始化IPC,初始化CC,这些耗时在百毫秒的级别;

V8 引擎相关的初始化耗时也在百毫秒的级别,其中首次NewContext要20ms。

总的来说,首次访问加载SO和JAR一般需要500ms,创建WebView和走完内核流程一般需要消耗500ms,也就是说,提前初始化内核和预创建WebView加载一个URL,跑一趟内核流程,可以带来约1秒的收益。

业务初始化

在页面加载的过程中,内核会有很多回调通知外壳,这些回调的处理上是否可能存在性能问题呢?

我们发现,在一些App上,一些接口很可能会出现性能问题,比如,onPageStarted,shouldOverrideUrlLoading,shouldInterceptRequest。

这些接口为什么会出现性能问题呢?一般很多应用会在首次onPageStarted回调时执行复杂的业务逻辑,比如,初始化一些统计模块,进行JS注入,等等。需要说明的是,onPageStarted并不是同步接口,为什么也会有影响呢?因为它是在UI线程执行的,长期占用UI线程,会对内核有较大的影响,内核很多操作需要抛转到UI线程去处理,比如,ServiceWorker线程启动就有抛转UI的过程,在UI执行完之前,它只能等待。

shouldOverrideUrlLoading 是客户端拦截请求的关键接口,内核会同步等待,很多应用会有比较复杂的拦截规则。

shouldInterceptRequest 是客户端离线包的关键接口,内核会同步等待,很多应用会在这个接口首次回调时去解压离线包和初始化离线模块。

在一些实际应用中,优化这些回调的处理,可以给全部H5页面带来 10% 以上的性能提升。

ServiceWorker初始化

ServiceWorker是PWA的关键技术,它具有非常强大的能力,Fetch,Cache,Push和Add to home screen,能让前端开发者非常灵活的操控页面缓存。

同时,它也是有比较大的初始化成本的,比如,ServiceWorker线程启动平均要200ms,而每次访问页面,一般ServiceWorker线程至少都需要启动一次。当然,Chrome也在不断优化这块的耗时,最终预计能优化到100ms以内。

网络初始化

在网络初始化方面,一般内核网络库的初始化并不太耗时,耗时的是DNS和Connection。

用户首次访问,一般都需要去进行DNS解析和创建连接,而在后续访问时,一般都可以用上缓存或者预连接。

DNS解析,一般耗时在200ms以上,创建HTTP连接,一般耗时也在200ms以上,而创建HTTPS连接则需要600ms以上。

也就是说,用户首次访问时,如果不能提前创建连接,从性能的角度来说,是非常危险的。

这个方面我们的建议是,使用HTTPDNS提前解析和缓存DNS,提前创建连接(比如,用户点击时)。

浏览器也有这方面的优化,比如,在加载主文档时,提前发起子资源的预连接,但在一些托管网络库的应用来说,这些策略可能不会生效。

服务器初始化

页面服务器和资源服务器,是否也需要初始化呢?一般也是需要的,比如,页面访问过之后,页面服务器也会有一些缓存,用户再次访问时可以直接使用缓存而无需走完整的流程,但这些缓存应该是大部分用户都能共享的,所以实际影响不好评估。资源服务器也一样,比如,图床,很多是按用户手机屏幕和网络类型来返回不同图片的,用户访问过就会放到CDN缓存中。

暂时未有数据表明服务器初始化对页面整体性能产生明显影响。但我们有另外一份数据,在一个业务中,预创建WebView提前加载一次模版页面,能让全网平均性能优化100ms。其中,模版页是304的,里面的资源都是可缓存的,也就是说,这100ms的收益并不来于缓存,而是来于某些模块的初始化。

JS初始化

这里提到的JS初始化,并不是前面说的JS引擎相关的初始化。JS初始化是指JS文件缓存到httpcache和解析编译生成V8 Cache文件。很多数据表明,JS解析编译占JS耗时的35%以上,一些有巨型JS的页面甚至可以达到80%。在U4 2.0中,一般JS执行一次之后,就可以生成V8 Cache,虽然V8 Cache可以重复使用,但也存在被自动清理的情况,所以提前执行一次还是有收益的。

一些业务中,提前执行一次JS,在用户真实访问时,耗时从500ms降到200ms。特别是在一些超级App中,基础JS基本都一样,提前执行一次可能会带来非常明显的收益。

结束语

上面介绍了一些常见的初始化对页面性能的影响,希望大家能了解到一些隐藏的信息,能开阔Web优化的思路。当然,这些点不一定会存在很大的性能问题,比如,一些业务模块处理的非常好的App,在业务初始化方面不一定会有性能问题,需要根据自己的实际场景,具体问题具体分析。

目录
相关文章
|
6天前
|
JavaScript 前端开发 开发者
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第27天】在前端开发领域,Vue.js和Angular是两个备受瞩目的框架。本文对比了两者的优劣,Vue.js以轻量级和易上手著称,适合快速开发小型到中型项目;Angular则由Google支持,功能全面,适合大型企业级应用。选择时需考虑项目需求、团队熟悉度和长期维护等因素。
14 1
|
13天前
|
JavaScript 前端开发 算法
前端优化之超大数组更新:深入分析Vue/React/Svelte的更新渲染策略
本文对比了 Vue、React 和 Svelte 在数组渲染方面的实现方式和优缺点,探讨了它们与直接操作 DOM 的差异及 Web Components 的实现方式。Vue 通过响应式系统自动管理数据变化,React 利用虚拟 DOM 和 `diffing` 算法优化更新,Svelte 通过编译时优化提升性能。文章还介绍了数组更新的优化策略,如使用 `key`、分片渲染、虚拟滚动等,帮助开发者在处理大型数组时提升性能。总结指出,选择合适的框架应根据项目复杂度和性能需求来决定。
|
7天前
|
JavaScript 前端开发 API
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第26天】前端技术的飞速发展让开发者在构建用户界面时有了更多选择。本文对比了Vue.js和Angular两大框架,介绍了它们的特点和优劣,并给出了在实际项目中如何选择的建议。Vue.js轻量级、易上手,适合小型项目;Angular结构化、功能强大,适合大型项目。
11 0
|
26天前
|
前端开发 JavaScript Java
导出excel的两个方式:前端vue+XLSX 导出excel,vue+后端POI 导出excel,并进行分析、比较
这篇文章介绍了使用前端Vue框架结合XLSX库和后端结合Apache POI库导出Excel文件的两种方法,并对比分析了它们的优缺点。
190 0
|
3月前
|
缓存 前端开发 JavaScript
超时空加速秘籍:揭秘JavaScript前端开发中的性能魔法,让您的Web应用瞬间穿越到未来!
【8月更文挑战第27天】本文介绍了一系列实用的JavaScript性能优化方法并提供了示例代码,包括减少DOM操作、使用事件委托、避免阻塞主线程、异步加载资源、利用浏览器缓存、代码分割以及使用Service Worker等技术,帮助开发者有效提升Web应用性能和用户体验。
49 2
|
3月前
|
缓存 编解码 前端开发
优化Web应用性能的前端技巧:从加载时间到用户体验
在现代Web开发中,提升前端性能不仅仅是为了缩短页面加载时间,更是为了提供更流畅的用户体验。本文将探讨几种有效的前端优化技术,包括懒加载、代码拆分、资源压缩以及浏览器缓存策略。通过具体实例和最佳实践,读者将能够掌握如何系统地提高Web应用的响应速度,减少资源消耗,并最终改善用户的整体体验。
|
3月前
|
前端开发 JavaScript API
一场前端框架的“武林大会”,三大主流框架之间的性能比较!!!
一场前端框架的“武林大会”,三大主流框架之间的性能比较!!!
|
3月前
|
前端开发 大数据 数据库
🔥大数据洪流下的决战:JSF 表格组件如何做到毫秒级响应?揭秘背后的性能魔法!💪
【8月更文挑战第31天】在 Web 应用中,表格组件常用于展示和操作数据,但在大数据量下性能会成瓶颈。本文介绍在 JavaServer Faces(JSF)中优化表格组件的方法,包括数据处理、分页及懒加载等技术。通过后端分页或懒加载按需加载数据,减少不必要的数据加载和优化数据库查询,并利用缓存机制减少数据库访问次数,从而提高表格组件的响应速度和整体性能。掌握这些最佳实践对开发高性能 JSF 应用至关重要。
65 0
|
3月前
|
前端开发 UED 开发者
React组件优化全攻略:深度解析让你的前端应用飞速运行的秘诀——从PureComponent到React.memo的彻底性能比较
【8月更文挑战第31天】在构建现代Web应用时,性能是提升用户体验的关键因素。React作为主流前端库,其组件优化尤为重要。本文深入探讨了React组件优化策略,包括使用`PureComponent`、`React.memo`及避免不必要的渲染等方法,帮助开发者显著提升应用性能。通过实践案例对比优化前后效果,不仅提高了页面渲染速度,还增强了用户体验。优化React组件是每个开发者必须关注的重点。
63 0
|
4月前
|
缓存 监控 前端开发
前端开发中的性能瓶颈分析与优化
【7月更文挑战第27天】前端开发中的性能优化是一个系统工程,需要从多个角度入手,综合运用多种策略。通过减少网络延迟、优化资源加载、优化DOM操作、优化JavaScript执行以及第三方服务优化等措施,可以显著提升前端应用的性能。同时,通过性能监控和调优工具的使用,可以持续监控和优化应用性能,确保用户获得流畅、高效的体验。