1987WEB视界-分享互联网热门产品和行业

您现在的位置是:首页 > 网络工具 > 正文

网络工具

浏览器内核创新技术演进及实践-U45.0

1987web2023-12-20网络工具215

诚邀您加入我们,一起创造未来!

前言

在移动互联网前期,Web 技术让开发者可以快速在移动平台支持网页浏览等功能,让大家快速进入了移动互联网的便捷时代。这种跨平台、动态性强、开发效率高、容易传播的开放 Web 技术,为移动互联网的迅速发展提供了重要的支持。但是,在那个移动互联网快速发展的时期,手机硬件性能不好、运营商网络速度慢、大部分页面由 PC 硬搬过来缺乏优化,Web 页面性能体验差给大家留下了非常深刻的印象,这种印象可谓刻骨铭心,让那一代互联网人不堪回首,往后每次聊到 Web 技术都会打上性能体验差的烙印。

在 2023 年的今天,手机设备性能和网络性能大幅提升,渲染引擎和 JS 引擎技术突飞猛进,Web 技术早已今非昔比。现在在 App 内我们已经非常难判别哪些是 Web 页面了,Web 页面无论是性能体验,还是外观样式,都和 Native App 页面几乎一致。在图文展示类的信息流场景,Web 技术已占据了压倒性优势,业界普遍使用 Web 技术,打造出了很多类似 UC 信息流的极致体验,在复杂的富媒体页面场景 Web 技术也毫不逊色。但是,大家依然会漠视 Web 技术的发展,在各种场合继续乐于用性能体验差给 Web 技术打标签,所以我们很有必要从技术角度去纠正这种错误的观念。

本文是第 18 届 D2 主题分享内容的整理,期望从渲染引擎、JS 引擎等内核底层技术角度给大家阐明 Web 应用为何能具备 App 级的优秀性能体验。

以下为分享的主体内容:浏览器内核创新技术演进及实践 - U4 5.0

一 内核技术产品

U4 5.0 是 UC 内核团队研发的最新一代 Web 引擎。U4 内核的应用非常广泛,阿里巴巴集团大部分 App 底层的渲染引擎都是 U4 内核,比如 UC、Quark、淘宝、钉钉等等。我们还以授权接入的方式提供给第三方使用,体量也非常大。除了 U4 内核,我们其它的技术产品 JSI 独立 JS 引擎、Apollo 播放器、CrashSDK 也被大量产品接入使用。本文给大家介绍的主要是 U4 5.0 内核,下面会从渲染引擎、JS 引擎、多媒体技术、基础技术等方面,给大家详细介绍内核引擎技术的演进思路和应用实践。

二 渲染引擎优化

渲染引擎是内核最重要的模块之一。我们为什么需要做渲染的优化呢?现在 Web 页面越来越复杂,已经发展为文本、图片、动画&游戏、音视频&直播等元素混排的复杂富媒体展示形态。在这样复杂的页面形态下,既要有很好的首屏性能,又要有优秀的操作体验和流畅的动画,这就要求我们必须深度优化渲染引擎,增强渲染能力和提升渲染性能。我们一般可以从渲染流水线、渲染调度、渲染高可用、渲染增强等方向去优化渲染引擎,下面介绍其中非常重要的渲染流水线的优化。

我们先看看原生的渲染流水线,内核在加载、解析、排版、绘制之后会产生 MainFrame。MainFrame 里包含了 PaintRecords 等绘制信息,这些信息会提交给 Layer Compositor。Layer Compositor 是图层合成器,图层合成器负责网页的合成,Layer Compositor 的 Draw 会产生 Compositor Frames。Compositor Frames 里包含了 RenderPass、DrawQuads 等信息,Compositor Frames 会提交给 Display Compositor。Display Compositor 是显示合成器,显示合成器会进一步与自绘 UI 做二次合成。Display Compositor 产生的绘制指令会提交给 GPU,GPU 调用图形库接口去绘制和上屏。

另一方面,Chromium 在网页渲染过程中会进行 Layer 分层,Layer 还会拆分为多个分块,光栅化事实上是针对分块进行光栅化,分块的渲染是异步的,我们叫做异步分块光栅化。异步分块光栅化,它的优点是不阻塞合成,分块缓存能够复用,在惯性滚动、合成器动画、缩放等场景不容易出现卡顿。它的缺点也比较明显,分块是需要分配额外的内存的,这样就明显增加了内存负担,异步的设计也增加了线程抛转等待的耗时,降低了光栅化的整体效率,在快速滚动等场景可能会因为光栅化来不及完成而出现闪白的现象。为了解决异步分块光栅化存在的问题,我们在 U4 5.0 内核支持了直接光栅化,不再使用分块,直接以同步方式进行光栅化,提升了光栅化的整体效率。

现在手机设备性能很好,大部分场景使用直接光栅化也能在一帧内很好地完成渲染流程,在这些场景里,直接光栅化既节省了内存,又提升了渲染效率。但是,部分页面的图层非常复杂,直接光栅化不能在短时间内完成,这样就可能会出现卡顿掉帧,这些场景里异步分块光栅化是更好的选择。在 U4 5.0 内核我们会根据图层复杂度动态选择光栅化策略,简单图层使用直接光栅化,复杂图层使用异步分块光栅化,在同一个页面,也可以部分图层使用直接光栅化,部分图层使用异步分块光栅化,我们把这种叫做混合光栅化,这在实践中有更好的效果。

我们再继续看看原生的渲染流水线,可以很明显看到它有 Layer Compositor 和 Display Compositor 两层合成器。Layer Compositor 负责网页合成,Display Compositor 负责与自绘 UI 做二次合成。在 Chrome 浏览器场景,它有很多自绘 UI 控件,这些 UI 控件需要与网页内容一起合成展示,所以它需要 Display Compositor 来做二次合成。但是,在 U4 WebView 普通网页浏览的场景,我们仅仅只需要合成网页,并不需要 Display Compositor,这种两层的合成器架构明显是偏重的,所以我们期望能简化合成器的架构。

在 U4 5.0 内核我们将 Layer Compositor + Display Compositor 的两层合成器架构进行了优化改造,简化为只有 Layer Compositor 一层的直接合成架构,这样就简化了渲染流水线,有效地提升了合成的性能。

前面介绍的是光栅化和合成的流程,我们再看看 GPU 绘制上屏的过程。GPU 有 Client 端和 Server 端,在 Client 端会把绘制指令序列化为 Command Buffer 命令,Command Buffer 命令会通过 IPC 传输到 Server 端,Server 端会反序列化 Command Buffer 命令为绘制指令,并执行相关调用完成绘制和上屏。CommandBuffer 可以用于支持进程间的渲染指令传输,在页面比较复杂的时候,页面的绘制指令就会非常多,CommandBuffer 带来的开销就比较大。那么我们是否能优化 CommandBuffer 的开销呢?基于这种想法我们在 U4 5.0 内核实现了 InRenderer GPU 渲染架构。

在 InRenderer GPU 渲染架构里,我们把 GPU 进程变成 Renderer 进程的一个子线程,合成器产生的 DisplayList 可以直接交给图形库处理,整个过程不需要产生 CommandBuffer,从而减少了中间 Buffer 带来的开销。这样,我们就更进一步优化了渲染流水线,既节省了内存,又提升了整体的渲染性能。

InRenderer GPU 是 U4 5.0 内核支持的最新渲染架构,还在不断演进中。从测试跑分来看,MotionMark 跑分能提升3倍,Canvas Images 帧率能提升 30%。CSS,JS,SVG 动画性能都有不同幅度的提升,整体效果比较好。其中 Motion Mark 是动态复杂度测试,绘制复杂度的增长和耗时的增长并不完全是线性关系,得分主要说明在同样耗时下能承载的绘制复杂度,即得分越高能承载的页面复杂度越高。

三 JS 引擎优化

JS 引擎也是内核最重要的模块之一。我们为什么需要优化 JS 引擎呢?现在Web 技术在往 Web App 方向快速发展,用户对 Web 性能体验的期望也越来越高,期望 Web 页面能具备 App 级的性能体验。Web 页面一般有 CSR 和 SSR 两种模式,CSR 页面的核心逻辑一般是由 JS 来完成,大型 JS 也可能会影响 SSR 页面的首屏渲染,所以 JS 对 Web 页面的性能体验是非常重要的。下面我们看看如何优化 JS 引擎,让 JS 语言的性能逐步接近 Native 语言的性能。

我们先看看 V8 执行 JS 的流水线。V8 在运行 JS 的时候,会先把 JS 源码解析成抽象语法树,接着会将抽象语法树编译为字节码,字节码解释执行。在满足一定条件的时候可以继续编译生成未优化版本或优化版本的机器码,机器码直接执行。

Chromium V8 团队是怎么优化 JS 引擎的呢?V8 逐步引入了 Crankshaft 优化编译器、TurboFan 优化编译器、Ignition 解析器和 Sparkplug 非优化编译器,而且还在持续演进中。那么 V8 为什么要引入这么多的解析器和编译器呢?它其实是在权衡编译耗时和执行耗时,期望找到一个最优解。JS 一般有解析、编译和执行等流程,这些流程的总耗时最小才是最优的。优化机器码的执行效率比较高,但编译时间比较长,总耗时并不小。字节码和非优化机器码,它们编译效率比较高,虽然执行效率稍差一些,但是总耗时反而是更小的。V8 会优先把 JS 快速编译成字节码或者非优化机器码,在满足一定条件时再编译成执行效率更高的优化机器码,这样就能很好地平衡解析耗时和执行耗时,从而能达到更好的性能效果。

下面我们看看 UC 内核团队是如何去优化 JS 引擎的。第一个思路是在原生 V8 JS 引擎的基础上进行深度优化。从前面我们了解到字节码有比较好的效果,那么我们是否能继续优化字节码呢?为了加快字节码的解释执行速度,我们将 V8 本地编译生成的字节码处理程序 Builtins 的优化编译器 TurboFan 换成了 UC LLVM Compiler。使用 UC LLVM Compiler,可以让 V8 的 Builtins 大小减少 12.5%,性能提升 5-10%。同时我们针对整个 Code Cache 链路做了进一步优化,在保存时机、保存策略、代码质量和覆盖场景等方面都做了较多优化,整体性能比原生 Code Cache 能提升 10-15%。

在前面我们已经把 Code Cache 性能优化得很好了。但是 Code Cache 有个特点,它需要在访问页面时生成,至少要在第二次访问时才能生效,原生的生效时间甚至要更晚,在 72 小时内访问两次才会生成,第三次访问才能使用。但是很多页面的首次访问性能也是非常重要的,比如活动页、推送页、唤端页等等,那么有没有办法让第一次访问也能用上 Code Cache 呢?这就是我们的第二个优化思路 AOT,提前编译生成 Code Cache。我们的 JS AOT 技术支持在线生成和离线生成两种模式,在线模式是客户端 Worker 线程在空闲的时候生成,离线模式是在服务端生成下发到客户端,在生成 AOT 文件之后,用户首次访问页面时就能用上 Code Cache,页面首次访问性能能提升 30% 以上,效果很好。

前面我们讨论的是 Code Cache 链路的优化,那么 JS 运行链路是否还能继续优化呢?基于这样的设想,我们在 U4 5.0 内核研究实现了 U4 Snapshot 技术。U4 Snapshot 技术,通过我们的 JS 离线编译器将 React 等框架 JS 的运行结果镜像化为 Snapshot 文件,页面在执行相应 JS 的时候就可以直接使用 Snapshot 中存储的信息,而不需要再走 JS 解析、编译、执行等流程,这样相对于 AOT 还能再进一步提升 JS 性能。生成 Snapshot 的过程是比较耗时的,所以我们一般会离线生成 Snapshot 文件再通过 Pars 离线包机制提前下发到客户端。V8 Snapshot 技术是 U4 5.0 内核支持的最新 JS 引擎技术,我们已经应用到夸克上的部分业务,有比较好的效果。

从前面介绍的渲染引擎和 JS 引擎技术我们可以看到,通过直接光栅化、直接合成、InRenderer GPU 等技术,我们也可以把 Web 的渲染流水线做得非常简洁和高效;通过 Code Cache、JS AOT、U4 Snapshot 等技术,我们可以把 JS 编译成字节码或机器码(注:机器码是汇编代码,非常高效),甚至还可以把 JS 运行结果镜像化为 Snapshot 文件,把 JS 语言的性能提升到了新的高度,逐步接近 Native 语言的性能。正是有了这些强悍的 Web 引擎能力的支持,我们从而能够轻松打造出大量性能体验优秀的 Web 应用。

四 多媒体优化

接下来我们聊聊多媒体技术的话题。多媒体技术对用户体验也非常关键。多媒体技术,我们先看看视频播放部分。原生的视频播放存在较多问题,功能单一,基本上只有播放和全屏功能,性能和体验也不好,还有较多的稳定性和兼容性问题。

相比原生 WebView,我们在视频体验方面做了很多优化。一方面是视频播放增强,我们通过混合渲染技术接入了自研的 Apollo 播放器,Apollo 播放器能支持更多的视频格式,有更好的解码性能,还支持边下边播、秒播、音视频双轨等特色能力。另一方面,我们支持在独立进程运行播放器,这样就有更好的稳定性和更高的安全性。在性能体验方面,我们也做了多视频内存优化、全屏体验优化、预加载视频内容等一系列优化,从而能有比较好的视频体验。

多媒体技术,我们再看一下当前非常热门的 WebRTC 技术。WebRTC 提供了一套标准 API,使Web应用在不需要借助任何插件的情况下可以直接提供实时音视频通信功能。U4 5.0 内核支持了 WebRTC H.265 技术,原生 Chromium 内核还不支持该技术。支持 WebRTC H.265,在技术流程上与 H.264 是比较相似的,都需要处理编解码和 RTCP 流等流程。我们为什么要支持 H.265 技术呢?业务在使用 WebRTC 的过程中,反馈服务器成本压力比较大,所以我们研究支持了 H.265 技术。与 H.264 相比,H.265 有更高的压缩比和更好的视频质量,能大幅节省服务器存储成本和带宽成本,大概能节省 30-50%,有非常大的业务价值。

五 基础技术优化

U4 5.0 内核其实做了非常多的基础能力增强,比如 Lottie 增强、截图增强、字体渲染增强、自定义网络库、自定义播放器、内存优化、稳定性&兼容性优化等等。下面给大家介绍其中的安全技术和大小核技术。

Web 安全技术,我们先看看 Web 安全有哪些问题,一个是 Web 的动态性非常高,页面很容易通过 JS 执行攻击,一个是内核依赖比较多的三方库,这些三方库可能会存在安全漏洞,比如最近爆出的 WebP 安全漏洞,还有就是 Chromium 内核是开源的,开源项目如果存在漏洞会更容易被发现和利用。针对安全漏洞,一方面,我们会快速修复漏洞问题;另一方面,我们期望能有一套统一的安全机制来保障安全。

Isolated 沙箱进程就是一个非常有效的安全技术。前面提到页面很容易通过 JS 执行攻击。比较好的想法就是把执行 JS 的 Renderer 进程限制在一个安全沙箱里,这个沙箱里文件系统、网络、系统调用等权限都会受到限制,这样就能让风险最高的模块处于一个相对安全的环境,从而能达到较好的安全效果。但是,Isolated 模式也有缺点,兼容性不是很好,部分系统会启用失败。所以我们会让 Renderer 进程优先启用 Isolated 模式,启用失败就降级到 Seccomp 模式。其中 Seccomp 模式是通过限制部分系统调用来保障一定程度的安全性。

下面介绍大小核技术。我们先聊聊内核的集成方式,内核集成一般有两种方式,动态下载和内置集成,动态下载由于依赖网络下载,会存在用户覆盖率问题,下载成功前可能部分业务场景会存在不可用的问题,一些重要的端很难接受这种不可用的问题,所以一般会做内置集成。内置集成,一般需要集成一个相对较小的内核,需要多小呢?Chrome 原生 64 位内核大约是 45 M,我们优化后的 U4 64 位小核是 14 M,在嵌入式 WebView 场景下,基本上也能算是业界最小了。U4 小核能够满足阿里巴巴集团内绝大部分业务场景的能力诉求。在 Size 优化技术实现上,我们更多是依赖内核底层技术优化来做内核小型化,当然我们也裁剪了一部分 Web 特性能力,但主要是一些老旧废弃或较少使用的功能。而对于一些有特殊能力诉求的业务场景,需要用到更加完整的内核功能,又期望能覆盖全部用户,我们也提供了大小核技术来满足此类场景的能力诉求。

大小核技术就是内置集成小核,动态更新合并出大核。整体流程有两部分,一部分是公共的独立库,比如 zlib、icu 等,独立库一般会有较大的难度,它除了要把库独立成单独的产物,一般还需要做兜底或降级方案,一些兜底或降级方案是比较复杂的。独立库一般只需要一次性下载,更新频率比较低,下载后可以给小核和大核使用。第二部分是生成大核,客户端请求更新大核,服务端会先与小核比较产生一份 Diff 文件,返回 Diff 文件给到客户端,客户端将 Diff 文件与小核合并成大核,这种 Diff 更新合并出大核的方案能很好地节省流量成本。

六 总结与展望

前面介绍了 U4 内核引擎技术的演进,下面做一下总结和聊聊 Web 技术未来的发展。

我们在前面介绍了很多渲染引擎技术和 JS 引擎技术。这些技术并不是孤立的,它们是在一个完整的体系里。在页面整个生命周期里的每个环节,我们都有各种技术能进行增强,这些技术之间是紧密相连的。为了能离线编译出 AOT 或 Snapshot 文件,我们支持了 JS 离线编译器;为了让离线编译的文件能下发到客户端,我们支持了 Pars 离线包技术;为了让渲染性能体验更好,我们支持了最高效的 InRenderer GPU 渲染流水线;为了让页面外观与 Native 一样,我们支持了 App 样式和沉浸式体验;为了让页面间操作更加顺滑,我们支持了 Swiper 多页容器;等等。这一系列技术保证了 Web 页面生命周期的每个阶段都能得到充分的优化。

展望未来,Web 技术正在往 Web App 方向高速发展,全方位对标 App 级体验。目前行业里已经有一些出色的解决方案,例如:PWA 与小程序。而目前我们面向的场景更多是在 App 端内,在端内 Web 作为嵌入式技术与 Native 等其它技术混合使用。我们期望 Web 在更加符合 W3C 开放标准的情况下,也能有媲美 Native 的性能体验。我们基于这些诉求,也提供了一套基于标准 Web 技术的端内嵌入式 Web App 解决方案,并在快速演进。端内更需要的是一种融合的技术栈,它既要有内核,又要有容器,还要有其它关联组件,我们以一个内部命名为 Web Compass 的容器为载体,把内核底层基础技术和 Native App 能力更好的透出给前端使用,让 Web 应用在遵循 W3C 标准的情况下还能更自由地使用各种底层能力作进一步的增强。我们期望通过 Web 引擎、Web 容器和 Web 开发框架的协同发展,形成一体化的 Web App 解决方案,让 Web 应用都能具备 App 级的优秀体验。