《百度开源小程序框架架构演进和性能优化实践》
作者:百度架构师
的主题是《百度开源小程序框架架构演进和性能优化实践》。本部分由两部分组成。第一部分是百度智能小程序的总体框架及开发。主要讲了百度小程序的整个开发流程概述、百度智能小程序的框架以及百度小程序多主机运行的保障;第二部分是百度小程序的总体框架和开发。小程序框架的性能优化主要讲整个小程序的启动过程以及从开发者的角度有哪些重要的优化点。
1。百度智能程序总体框架及开发
整个移动互联网一直在寻找NA和H5之间的平衡。 NA性能好,能力强; H5具有更高的灵活性。我认为渲染分为两个流派,一个是NA渲染流派,另一个叫H5渲染流派。
NA渲染流派,比较有代表性的有RN、Flutter;网页渲染学派,比如百度的轻量级应用,以及后来创建的小程序。
1。整个开发流程概览

百度曾经出过的网页渲染学派的三大代表产品是轻量级应用、直账、小程序。
- 轻松应用,H5+端功能。是一个标准的H5,增加了一些NA API,比如定位等。
- 直号在技术上和轻app是一样的。
- 小程序本质上是有限的H5+大量丰富的API+UI组件。现在我们为小程序提供了300多个API和30多个组件。组件具有接口。例如视频和地图。
小程序应该受到限制有两个主要原因:
- 保持体验的一致性。 H5太灵活了,JS可以随时改变界面。
- 安全考虑。因为我们提供了大量的API和组件,而这些都是非常底层的功能,比如电话号码和账户,它们不能轻易地向所有人开放。
受到限制主要有两个原因:
- 编写语言不再是直接编写HTML,而是使用自定义语言swan来编写。
- 运行时层有两个栈,一个是渲染栈,一个是JS执行栈。这两个堆栈物理隔离以确保安全。
2。智能小程序框架
(一)完整的开发和运营流程
首先我们简单介绍一下整个百度智能小程序的开发流程。
- 首先,开发者使用swan来编写布局;
- 然后通过开发者工具打包,上传到我们的小程序B端服务器;
- 接下来是小程序审核流程,有机审核和人工审核;
- 最后,当用户点击小部件时,客户端向C端服务器请求小部件,C端服务器从B端服务器检索小部件包。整个过程都是加密传输,保证了代码的安全。
(2)百度智能小程序框架-SWAN
上图是一个百度智能小程序的框架,我们内部称之为SWAN。
层次结构如下:
- 最顶层是开发者的基础库,称为swan-js。开发人员直接处理这一层。 swan-js 负责两件事:将 swan 代码转换为 HTML,并将其转变成可执行的 WebView 应用程序;封装并公开客户端功能。
- 下一个级别是天鹅原生的。这里的核心是API和组件的NA实现。双栈管理也在这一层。另外,红色标记的扩展是供开发者扩展主机自身能力的。例如,如果贴吧主机想要添加邮件功能,就可以使用这种机制。
- 下面的层称为移植层。该层是百度小程序为了实现开源代码而添加的接口层。最底层是宿主的基础能力层。如果主机不具备这些能力,可以参考百度的开源参考实现,可以直接集成到主机中使用。
3。核心结构
(一)前端视角
我们从前端视角来看一下双栈结构。一个主机客户端可以运行多个小程序并在一段时间内保持活动状态。每个小程序都有一个主执行框架JS和小程序开发者JS。一个master对应多个slave(slave代表一个用户可见的接口)。
(2)客户端角度
从客户端角度看双栈结构,如上图所示,master负责执行JS。可以有两种实现方式,WebView或者JS引擎(V8/jscore),JS引擎效率更高;从站通过 WebView 显示。为了加快WebView的创建速度,设置了缓存;主站和从站之间的通信是通过消息总线进行的。
master 不支持 BOM、DOM 和 WEB-API。 Applet 只能调用外部开放的函数。
(3)小程序NA组件与界面的关系
从体验角度来看,小程序体验优于H5。其中之一是小程序将把一些 NA 功能和用户界面集成到小程序中。小程序的主要渲染仍然基于H5技术。接下来我们来说一下NA元素是如何融入到UI界面中的。
NA元素和H5之间有两种类型的关系,补丁关系和共层关系。
补丁条件:NA元素与H5不在同一层,NA漂浮在H5之上,并且H5的元素不能放置在NA元素之上。因为不在第一层,所以必须处理滚动链接。当检测到 WebView 滚动 n 个像素时,NA 元素也必须滚动 n 个像素。
同层关系:NA元件在H5层上,H5原来的元件可以放在NA元件上面。
更新且同层的界面层次结构树如上。
让我们举一个同一层视频组件的例子。视频组件更复杂,有 4 层。第一层是视频层,是原始视频的图像。第二层是阻挡层。第三层是视频控制的控制层(例如开始和暂停按钮)。第四层是Slot层,漂浮在视频上。 H5 元素将放置在该层上。
同层处理机制,先在H5上打上特殊标记(开发者写的天鹅会转为H5)先占空间,属性内联;滚动核心,取出该区域的表面,并将其交给NA层;然后小部件框架会将这个区域呈现给玩家,允许玩家直接在表面上绘制以到达同一层。上面的障碍、控件和轨道都是swanjs层的H5实现。轨道层可以被认为是一个容器。例如,如果您编写视频,所有子元素都会放置在轨道中。
NA的组件在同一级别上有不同的技术方案,Android和iOS之间存在一些差异。就像在iOS上,如果某个组件被设置为溢出,它自然会支持这套东西,但Android需要浏览器核心支持它。
4。小程序多主机运行保障

百度智能小程序是开放系统,可以在多主机上运行。那么如何保证小程序在多台主机上运行体验的一致性呢?
每个主机集成我们的widget框架后,首先要运行CTS测试。通过测试后才能获取小程序列表进行分发。
对于可选功能部分,不需要实现每台主机的所有功能。比如一些AI功能、推送功能。
小程序使用了可选功能怎么办?
两种方法,一种是widget和host之间的双向选择机制。小程序可以选择我要部署到哪些平台,主机也有权利选择我要部署到哪些主机。二是小程序兼容。
延伸机构

如上图所示,延伸机构以红色标记。当主机有一些自定义需求时可以使用此机制。作为主持人,您需要做两件事。首先需要在JS层写一套接口;其次,需要在移植层接口实现层实现一组功能。如果主办方认为这种可能性具有普遍性,可以就该提案提供反馈。审核通过后,百度小程序团队会将提案合并到开源框架中。
5。章节摘要

2。百度智能小程序框架性能优化实践
首先从用户的角度来看一个小程序的加载过程。
1。百度智能小程序加载步骤流程

以微博为例,如上图所示。
- 首先,小程序启动后,有一个加载过程。出现上面的标题和下面的选项卡(框架 NA 实现)
- 。我们将第二张图像定义为 FP(First Paint)场景。
- 第三张图下面有一个搜索框。这其实就是小程序包的内容。它通过 initdate 接口进行初始化和渲染。我们将此阶段定义为FCP(First Contentfull Paint)阶段。
- 第四张图是从互联网上拉取实时内容然后更新到界面的小程序。我们将其定义为 FMP(首次有意义的绘制)阶段。
- 在最后一张图中,所有元素都被拉下来并显示出来。用户可以对任意位置进行操作。我们将其定义为TTI阶段(Time to Interactive)。
2。百度智能小程序
(1)性能基线
百度小程序于2019年底建立了FMP指标,开发者平台上显示的名称为“屏幕时间”。
我们计算了线上的第80个百分位点,花了1.9秒。第 80 个百分位数是多少?比如有100个请求进来,然后我们对耗时的请求进行排序。我们认为第 80 个请求的耗时为第 80 个百分位。
(2)性能历史曲线
如上图所示,2019年百度小程序性能优化的历史曲线。FP框架层从近3s优化到约3s现在1.1秒。百度小程序的目标是让小程序无线化接近NA体验。
3。启动流程

接下来,从开发者的角度来看,还有哪些可以优化的地方?
我们先看一下启动过程。所有启动逻辑只是简单地串联列出(实际上有些步骤是并行的)。
4。性能优化
开发人员可以进行性能优化的两个主要部分。一是小软件包的大小,二是业务数据。
然后我用三点来解释开发者可以做什么。
(1) 优化报文大小
建议报文大小保持在1M以内。为什么?
因为我们统计过,如果我们打开的时候需要下载包,那么这个时候的启动时间就会占到我们整个时间的60%。对于1M的包,以80%的速度下载需要1s+。所以你需要检查一下你的包的尺寸。我们现在只关注第 80 个百分位。当我们达到第 90 个和第 99 个百分位数时,这是一条非常陡峭的曲线,并且恶化非常严重。
包优化机制
有两种技术:一是分包商技术和独立分包商技术,二是资源压缩。
- 分包技术和独立分包技术 分包技术

一个小程序的页面很多,但并不是所有页面都是高PV页面。许多页面很少被用户点击。您可以将这些页面放在我们的子包中,并将我们的高PV页面放在主包中。
分包不能独立运行。例如,当从搜索源部署时,我们的主包在运行时需要下载,但由于概率较低,它不会影响大多数情况。简而言之,它使用分包商技术来删除非关键页面。
使用分包技术去除非关键页面后,小程序包体积仍然较大,怎么办?
- 独立分包技术
所谓独立就是下载完包后就可以运行,不需要下载主包。此时主包和独立子包的区别在于,小程序总是有一个输入,我们将这个输入的独立子包称为主包。
利用这两种技术来减小我们的数据包大小,使其保持在1M以内。
- 资源压缩

我们分析了一些小程序,发现有些包中含有PC镜像,这无疑增加了包的大小。建议如下:
- 将镜像放在服务器上,而不是放在包中。
- 压缩图片尺寸,例如将png格式改为jpeg格式,这样尺寸可以缩小90%(不考虑透明度)。
- 消除无用的资源。
App-js必须通过分包商解决。我们最终想要达到什么目的?
- 单个包裹1M以内检查。
- 文件数量控制在200个以内。
(2)数据提取
数据提取的目的是快速向界面添加内容,减少用户白屏时间。即使用户与互联网断开连接,也会为他离线缓存一些数据。
如上图提到了业务骨架屏和框架骨架屏。今天很多小程序都会参考H5的实现,在我们的小程序中使用H5的渐进式加载骨架屏。使用该技术后,会降低真实内容的显示速度。据我们统计,大约需要300ms。延迟。
为了解决骨架屏带来的内容显示延迟,我们创建了帧级骨架屏机制。如果按照我们的机制实现骨架屏,对性能的影响将会大大降低。策略是让slave加载骨架屏,并在master运行appjs时并行运行。
我写的业务骨架屏,什么时候出现?
如上图所示,当你通知app、page和waitNotify到渲染线程时,你创建的业务骨架截图只有在到达ReadyfirstRender时才会渲染。这个过程当然是非常缓慢的。即使使用了骨架屏,骨架屏与用户点击之间仍然存在大量的白屏时间。有了骨架屏,白屏时间问题就迎刃而解了。使用骨架屏会花费或多或少的时间。虽然是并行的,但是还是占用了手机的资源。
所以总体来说,从客户端或者框架的角度来看,我们不推荐使用它,但我们也不反对它的使用。如果要用的话就用骨架屏,影响最小。我想把
请求的优化总结为两个要点。第一个是早做,第二个是少做。
- “早”可以分为两部分。一是早发送,二是不阻塞。
第一件事就是早点寄。如果请求太晚,显示会明显变慢。建议在启动时设置网络请求。这是我们第一次为小程序开放的活动。很多小程序都会放在pageload中,速度比较慢。这两次在线时间都在80分位,相差200ms到300ms左右。另一种是非阻塞的。我们经常会看到一些小程序。它们启动后,必须等待用户的授权和定位。通常定位涉及到XY坐标,但是当定位涉及到海拔高度时,必须开启GPS,这会导致性能下降2秒到3秒。如果你不需要高度,就不要设置它,否则它会运行得很慢。有些小程序在使用时需要用户授权。如果他们不授权,则不会显示任何内容,并且会被阻止。如果可以的话,建议什么时候需要授权就询问用户,这样用户不反感,也能加快启动速度。
- “一点”主要分为两点。一种是推迟非关键请求,另一种是仅提取一屏数据。
一个小程序执行完毕后,可能会出现几十甚至上百个网络请求。小程序除了自己的业务之外,还会打理自己的业务,这会极大的影响我们的网络速度。因为一般主机会在底层网络库中设置一个线程池,如果请求太多就会排队。小程序框架不知道请求是核心请求还是非核心请求,只能将其排队。如果一切从一开始就靠管理,生意就会受阻。简而言之,首先请求需要在整个页面上显示的数据,然后延迟非关键请求。另一种方法是只拉取一屏数据并分段加载。
(3)渲染
setData操作的开销比较大,所以尽量减少数据量和次数。
如上图所示,setData是一个非常核心的API。当网络数据返回时,内容经过setData驱动并渲染后才能显示在界面上。
上图是优化前后的对比。我们可以看到,即使是1K数据也需要大约20ms。如果js是用WebView来运行的,首先一个JS字符串到达浏览器的Renderer线程和浏览器线程时会变成C层字符串,然后再到我们的NA通过Java接口变成Java字符串。所以到达slave后还得再反转一次,所以不能很快完成。虽然我们做了一些优化,通过核心做了内存指针优化开关,但是还是很贵。
我在使用一些小程序时发现setData的使用方法有很多不恰当的地方。以下是使用设定数据时应注意的一些事项。
- 减少调用 setData 的次数。 Goodcase:将多个 setData 调用合并为一个 setData 调用。
- 减少setData数据量。 Badcase:在调用setData之前,新的页面数据被添加到之前的页面数据中。
- 变量更改仅更新变量,而不更新对象。
5。性能自检

性能自检主要分为三个阶段,即开发阶段、测试阶段和上线后。
- 在这部分开发阶段,我们有三种方式进行性能自查,分别是工具的经验值、性能面板(客户端的性能面板可以显示整个性能启动所花费的时间)和管理体系。
- 在测试阶段我们有两种方式,一种是屏幕录制,一种是高速摄像。这两种方法能够真实反映用户体验。
- 上线后会有开发者平台。
如何获得官方技术支持?建议去开发者文档和社区寻求技术支持。

6。章节章节
- 开发者可以从包量、数据请求、渲染三个方面优化性能。
- 包含范围:1M以内。外包技术、压缩图像并消除无用资源。
- 骨架屏:如果要使用,建议使用框架骨架屏。
- setData:减少数据的频率和数量。
总体评价如下。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。