​X5内核轻量版本的诞生!你还不知道吗!

2021-05-14 11:40:31 浏览数 (1)

背景

Web的跨平台能力、动态运营能力、较强的特性支持以及低开发成本使其被广泛运用到众多的业务场景中。不过,最近几年Web载体WebView的使用场景相比之前有了很大的变化。各种超级App中的信息流或者类似小程序的场景越来越多。这些场景中一部分业务需求是由终端或者Hybrid实现,WebView用来承载一些运营需求高、终端或者Hybrid无法胜任的场景。

不同于传统的Web浏览场景,这里的页面都是由统一的模板生成,不需要很多的Web能力支持,层次简单,也不需要非常复杂的渲染管线支持。由于直接集成于超级App的各个业务场景中,对页面的打开速度、渲染响应速度有着极高的要求,以保证一致的用户体验。页面的各项能力,则通过JS API的方式扩展到App终端实现。

一款极简、扩展方便的Web引擎才是业务所需要的。X5Lite就是为此而生!

总体设计

一、现有浏览器内核的问题

现有的浏览器内核或者Web技术的发展的方向仍然是面向传统Web浏览场景的,以 Web for all为最终目标。不断添加越来越多的Web能力。现在的浏览器内核存在下面的一些问题:

 1.越来越大的size

目前的Chromium内核Android上编译后的大小已经超过50M,压缩后也会有20M~30M。这给需要集成浏览器内核的App造成沉重的负担。会导致获取新用户失败率提升,也会导致升级下载带宽成本上升。

 2.Chromium冗余的流程设计

Chromium内核需要支持所有的Web标准。所以其流程设计是必须要全面考虑所有可能情况,兼容所有的web标准和流程。举一个例子,在QQ浏览器首页信息流和微信公众号等WebView的应用场景,终端提前将页面内容下载和组装再调用WebView的loadData来加载页面html。这种常见loadData调用中,参数data是html字符串。但是Web标准中支持很多种data类型,有些是需要适用网络去拉取一些资源的。Chromium为了支持所有的情况,其loadData的流程如下图:

图1   Chromium的loadData流程

Chromium先会将data拿到网络线程去解析,确定其不需要使用网络再回到主线程,正式向内核发起loadData流程。在微信或QQ浏览器的这种场合下,主线程在这个时间点都是有大量业务逻辑需要处理的。同时主线程还担负系统渲染和事件等处理任务。所以主线程基本是不可能及时响应Net-thread的返回消息的。测试确定这里一般会导致50ms以上的延时。

也就是说这种比较通用的应用场合,Chromium需要兼容所有Web标准的流程导致了50ms以上的打开时间的损失。

 3.全而不精

包括Chromium在内的Web引擎,在众多Web标准的实现方面,虽然做了很多工作,但是还是存在功能难以满足实际业务需求情况,这些功能在超级App中被私有能力取代。很多新功能随着超级App的业务发展,也是领先Web标准的制定。所以内核应提供更方便的扩展能力满足超级App的需求,促进业务创新。

二、X5Lite的设计思想

要达到极简、扩展方便目标,我们设计X5Lite的思想是:

 1.一切以实际业务场景出发

X5Lite项目的针对新业务场景而设立的。所以一切设计都需要围绕业务场景开展。渲染流程和页面加载流程都按照实际业务场景尽可能做到最优。线程模型等也按照实际场景来设计。

 2.先破而后立

Chromium的代码给我们带来了完备的Web能力,也带来了承重的历史包袱。小修小改很难达到我们的要求。所以我们打算抛开一切历史包袱,完全抛弃Chromium的流程管线、线程模型、模块架构等等。按照我们自己的想法以及业务场景重新设计自己的架构。

 3.简到极致

冷门的、业务上用不到的能力一律不再支持。能够去掉的逻辑就去除。保证业务场景能力支持和性能的情况下将代码size减少到极限,将线程个数减少到极限,将流程简化到极限。并以流程管线简化来促进性能的提升。

来源

一、主体架构

 1. Chromium的主要模块

图2   Chromium 内核模块图

如上图所示,Chromium的主要模块包括:

●WebView:接口层,提供上层终端调用接口。

●Content:Chromium内核的骨架,连接其他各个模块。负责线程或进程框架的建立和运行;各线程/进程或各模块之间的通信和联系。

●Blink:负责页面解析、排版等。

●V8:javaScript执行引擎。

●Compositor:负责页面的合成渲染。

●Skia:图形库。

●Commandbuffer:提供一个可跨线程/进程调用的GPU沙箱。

●Media:媒体的编解码以及播放等。

●Components:提供Web上的功能支持的一系列小模块的集合。

●Net:网络模块。

●Base:提供一些基础的API或者能力支持。

●Mojo:提供基础的跨进程/线程函数调用API。

页面加载、解析、排版、渲染以及javascript执行等核心能力的模块如上图红色框中。这些模块是保证基本Web能力所必不可少,且无法替代的。

 2.  模块重组和裁剪

Content模块是连接其他各个模块,以及实现线程/进程架构的骨架模块。它也是基于主线Chromium的多进程架构来设计的。其大部分代码其实是用来维护整体架构和模块间通信等。对于X5Lite来说,显得非常冗余,与我们的设计思想是相冲突的。

要达到X5Lite的架构小巧、size最小化的设计目标。我们整体抛弃了Chromium 原有的content模块。也就是直接去掉了Chromium的整个骨架。去掉content后的Chromium其实就变成了一堆零件。我们用了两个迭代来完成模块的重组。第一个迭代达到可以跑通最简单页面的能力。第二的迭代中完成全能力支持。

我们重新实现了一个精简的X5Lite Content模块,按照X5Lite的需要来连接Chromium的其他模块。第一个迭代中我们只连通了blink、Compositor等几个核心的模块。

X5Lite Content模块是X5Lite的骨架,负责X5Lite线程架构的构建和维护。并且要保证web整体流程时序的正确执行。

完成X5Lite Content后,再在上层进行一个简单的Webview接口封装,形成一个X5Lite Webview层提供给终端的调用接口。

Chromium的commandbuffer模块提供了硬件渲染调用GPU的能力。其提供了跨线程/进程调用OpenGL的能力,以及沙箱和容错等能力。这其中只有跨线程能力是X5Lite所必须的。但因为X5Lite的线程通信方式不再使用原有Chromium复杂的mojo/IPC方式,所以我们也无法直接复用commandbuffer的跨线程代码。这样,Commandbuffer的代码对X5Lite就不太适用了。

我们重新开发了一个只支持跨线程调用OpenGL的X5Lite GPU模块来替换Chromium的commandbuffer模块。

Chromium原来的网络模块size比较大,并且与Chromium的content代码耦合较多。所以我们基于okhttp实现了一个精简的网络模块。

这样X5Lite已经具备了web所必须的主要模块,一个简单的X5Lite内核就完成了,同时第一个迭代也完成。初期的demo可以执行JS以及显示一些简单的web页面。

图3   X5Lite初期demo模块图

初期的demo仅仅能满足简单页面的显示要求,离满足业务需求的目标还有很多工作需要完成。

初期的X5Lite很多H5功能是缺失的。我们综合线上上报数据进行分析和梳理,确定了业务常用的H5能力的范围和列表,并且分别将需要支持的H5能力对应的Component对接回来。

OkHttp虽然具有size非常小,接入简单等特点。但是其性能与Chromium net相比还是存在较大差距的。网络性能是浏览器内核的核心性能指标。X5Lite仍然需要高效的Chromium net。

为了兼顾size和性能,我们将Chromium net进行了插件化。插件未下载完成时,X5Lite会临时适用okhttp作为网络库。当Chromium net 下载完成时,则会适用Chromium net作为网络库。

视频等媒体播放能力也是内核的必要能力。我们基于同层框架,重新实现了一个media插件用来支持web的媒体播放能力。

最终的X5Lite完成的模块构成如下图所示:

图4   X5Lite完整模块图

二、线程设计

ChromiumAndroid webview主要线程

Chromium Android Webview虽然是单进程多线程的。但是其是基于Chromium主线的多进程架构基础上演变过来的。其线程架构以及线程间的通信方式很多都继承于主线多进程代码。在X5Lite上其线程间通信方式以及有些线程就显得多余。

所以我们首先参考原有的线程架构,去掉一些冗余线程,完善一些不合理的逻辑,重新设计形成了下表中的X5Lite的线程模型。

X5Lite的线程

同时,在X5Lite上将不再使用Chromium基于mojo或IPC的复杂的线程/进程间通信方式。统一采用poskTask这种简单、直接、高效的通信方式。

三、扩展性设计

不同的业务或者不同的应用场景下,所需要的内核能力是不同的。另外,部分业务场景会需要更有针对性的特殊能力。因此我们打造了一套同层渲染框架机制,可以组件化来扩展内核的能力。也可以将内核原来的能力通过这套机制进行组件化。目前我们将Web中的Video和Canvas能力进行了组件化。

同层渲染框架将内核中标签的渲染和事件处理逻辑,转交到上层的组件实现,内核负责将组件的渲染结果与其他元素一起合成上屏显示。

图5   同层框架模块图

X5Lite的效果

一、启动速度

浏览器内核启动耗时主要是在load java的dex文件,以及loadC代码的so文件。

X5Lite无论是dex中打包的java源文件还是参与编译的C源文件都比原来的Chromium内核要减少一半以上。最终的so大小也从X5的26.73M大幅降低到12.02M。具体数字如下图:

图6   X5Lite与X5的size对比

X5Lite的so和dex的size都大幅降低了。最终X5Lite内核的线上统计的启动时间从X5原来的平均769ms降低到只要331ms。

图7   X5Lite的启动时间

二、打开速度

X5Lite在架构设计时就充分考虑了页面打开速度。在load阶段尽可能减少不必要的流程。并且充分考虑到在开始load页面的时候避开繁忙的系统主线程,避免因为线程抢占导致的消息延时影响页面打开速度。

图8   X5Lite的load流程

如上图所示,正常的页面打开流程是终端在系统主线程调用WebView的loadUrl接口打开新页面。然后会去单独的网络线程去下载页面主资源。主资源下载完成后会回到系统主线程去执行页面导航等逻辑后,再去内核线程去执行主资源的解析等。系统主线程需要执行终端的业务逻辑以及系统界面的事件、渲染等逻辑。主线程在打开页面这个阶段往往是比较繁忙的,非常容易导致消息延时执行。

X5Lite设计时就支持在任意线程发起页面load流程,也就是可以在任意线程调用loadUrl。并且整个页面打开流程是完全和系统主线程是解耦的。不会受主线程资源抢占等影响。

图9   X5Lite的渲染流程

Android WebView的正常渲染目标是普通的系统View,整个渲染上屏流程是嵌入到系统界面渲染的流程中的。如上图所示,在内核的合成线程完成第一级合成后,将数据发送到系统主线程,并等待系统的渲染回调。在系统主线程的OnDraw回调中向系统注入自己的上屏回调函数。系统完成主线程的渲染逻辑后会进行一次线程同步,将主线程中的数据同步到系统渲染线程。并开始按照View的位置和层级关系逐个渲染每一个View或调用View的上屏回调。在这个时候WebView才会真正地进行渲染上屏。

普通的WebView渲染上屏逻辑依赖系统的回调,而系统的回调在主线程繁忙的情况下延时问题也比较突出。WebView的渲染上屏流程是和系统UI界面刷新流程是绑定在一起的。也就是说页面更新上屏时,系统界面也会一起刷一次屏。这也会产生一些耗时。另外由于WebView上屏的线程和自己的GPU线程是两个线程,所以需要将GPU线程中的上屏所用资源纹理等跨线程传递,这里因为线程同步以及GPU锁等逻辑也会导致一些耗时。

在渲染方面,X5Lite采用了SurfaceView的渲染方式,整个流程是于系统界面刷新流程分开的。并且也不会有GPU资源跨线程传递导致的同步锁耗时。如上图所示,内核在合成线程完成初级合成后就直接进行上屏逻辑,最后到GPU线程完成指令调用和Swap就完成上屏流程了。整个流程更加精简且可控。

下图为X5Lite线上统计的首屏铺满时间于之前的对比数据:

图10   X5Lite首屏铺满时间

三、内存占用

图11   X5Lite内存占用对比图

X5Lite的小巧、轻快的特点在内存占用方面也能够充分体现。App的启动内存中加载so所耗内存跟so的大小正相关,加载java对象所用内存跟java代码的size有关。而X5Lite无论是so大小或者是java代码size都远小于基于Chromium的X5内核。所以X5Lite在启动内存方面要比X5低36M左右。

X5Lite架构简单,去除了很多冗余逻辑。并且X5Lite也简化页面加载和渲染的流程。在整个页面显示过程中通过各种方式来节省内存的占用。比如减少临时buffer的使用和创建、纹理资源用完及时回收、让数据传递路径更短减少内存消耗等等。所以用于加载单个页面的内存占用X5Lite也要比基于Chromium的X5内核更少。启动并打开单个页面后总内存占用X5Lite要比X5减少46M左右。

四、能力定制和扩展

X5Lite的插件化逻辑以及同层渲染机制可以方便地定制和扩展能力。比如上层可以使用自己的网络模块替换X5Lite默认的网络模块去实现一些定制化的网络能力。也可以使用自己的视频组件来达到特殊的页面视频效果等等。X5Lite非常方便的能力定制和扩展机制大大拓展了Web的应用边界。

五、节省大量拉新成本

X5Lite的so大小也从X5的26.73M大幅降低到12.02M。Java的dex的size也同样大幅减少。QQ浏览器Android 10.9.5版本开始用X5Lite替换原来静态集成的X5内核。浏览器App总的apk大小减少了8M左右。

apk大小的减少,意味着用户下载成功率的提升。在拉取新用户的场景中,用户下载成功率的提高可以节省拉新的成本。

未来展望

目前轻量化内核(X5Lite)已经在QQ浏览器首页信息流场景中被用来展示资讯正文。后续我们将继续打磨X5Lite,使其能够满足更多业务场景的应用。比如我们已经开始完善X5Lite在小程序场景的应用。

另一方面,现有的渲染合成大部分还是保留Chromium的逻辑,其设计更偏重渲染复杂页面。后续我们将对渲染管线进行大刀阔斧的改进,重新设计一套更适合层次简单页面的合成器,进一步提升X5Lite的渲染性能。始其更加契合业务场景需求。

你的每个赞和在看,我都喜欢!ღ

0 人点赞