Cube 技術解讀 | Cube 小程式技術詳解

語言: CN / TW / HK

 本文為 Cube 技術解讀》系列第三篇文章,之前上線的 《支付寶新一代動態化技術架構與選型綜述》 《Cube卡片技術棧解讀》歡迎大家回顧。

小程式作為動態化或者跨端開發的一種技術棧,在業界成為事實標準。Cube 作為一種輕量級小程式技術棧,具有體積小、啟動快、記憶體佔用低等特點,也比較適合“即用即走”的小程式場景。以下將重點介紹 Cube 小程式技術棧與技術演進實踐(若無特殊說明,所有的資料和圖表都是針對小程式)。

Cube 渲染小程式

模組組成

小程式視角,Cube 渲染引擎主要由以下模組組成:

  • Components:主要是小程式規範裡的元件;

  • Layout:支援 Inline,Block,Flex,Inline-Block,Inline-Flex 等多種佈局方式,還包括文字分詞,斷行等計算;

  • Style:支援樣式解析,樣式匹配,樣式繼承,偽類和偽元素等多種選擇器;

  • Rendering:管理渲染相關 Render Tree,圖片資源請求排程等;

  • Animation:JS 和 CSS 動畫實現;

  • JS Bridge:和 JS 引擎橋接;

  • JS Engine:目前支援 V8,JSC,QuickJS;其中 Android 下支援 V8,QuickJS;

  • Compositor:用於動畫和圖層的合成器(開發中)。

執行緒模型

Cube 小程式技術棧內部有這麼幾個執行緒:Bridge,Layout,Render,Paint,UI 等。

  • Bridge執行緒:執行 JS;與 AppX 橋接的類 DOM 的 JSAPI;處理 JS 相關事件;

  • Layout執行緒:佈局計算;樣式計算與匹配;維護 Layout Tree;

  • Render執行緒:維護 Render Tree;繫結資料;分層;

  • Paint執行緒:生成繪製命令;

  • UI執行緒:平臺事件分發;UI 佈局。

小結:

  • 並行佈局,非同步繪製:這裡的並行是指 JS 執行,Layout 佈局 以及  Render 三者完全並行處理。由於 Layout 和 Render,Paint 等不在一個執行緒,因此是非同步繪製;

  • 多個執行緒協同工作,有點像 CPU 的 5 級流水線。

值得注意得是 Web 渲染引擎有個特點就是和 Node 相關的 DOM 操作必須和 JS 在一個執行緒。這就導致解析 HTML,佈局,樣式計算,DOM,JS (包括垃圾回收)都在一個執行緒裡。帶來的後果就是隻有解析完文件才能看到 UI 效果,這也是 Web 渲染小程式白屏時間較長的一個原因。

Cube小程式技術棧,將“DOM操作” 和 JS 執行解耦。因此 JS 的 GC 不會影響 UI 呈現。這種實現對於加快小程式啟動非常有幫助。由於佈局計算和 JS 執行也解開耦合,因此一般不會由於 JS 執行阻塞 UI 互動。

Cube 小程式技術棧的特點

  • 體積小,啟動快:主 so 只有 2.8 MB(如果包括 Ariver,AppX,InsideSDK,整體小程式技術棧最小是 5.7MB)。另外可以享受到 OS 的紅利(包括 UI 的初始化和快取);

  • 高效能:接近於原生體驗;

  • 記憶體佔用小:小程式技術棧初始化後(包括 Inside SDK,Cube,AppX),大約只需要 7.5 MB;

  • 支援 Android,iOS 雙端。

與 Web 引擎對比

下面僅僅針對小程式場景與 Web 引擎對比:

Web

Cube

DSL

AXML

:white_check_mark:

:white_check_mark:

CSS

:white_check_mark:

部分支援

DOM

:white_check_mark:

不支援(有部分替代的介面)

Component2

:white_check_mark:

:white_check_mark:

外掛

:white_check_mark:

不支援(規劃中)

元件

:white_check_mark:

部分支援

開發工具

釋出打包

IDE/CLI

CLI

JS 除錯

:white_check_mark:

:white_check_mark:

預覽 DOM

:white_check_mark:

:white_check_mark:

編輯樣式

:white_check_mark:

:white_check_mark:

特性

JS 上下文

每個業務一個 Worker

所有業務共享一個 Worker

佈局

CSS 裡各種佈局

CSS 裡常用佈局

樣式

CSS 全集

CSS 子集

JS 引擎

V8/JSC/JSI

V8/JSI/JSC/QuickJS

特點

效能上

啟動較慢,記憶體佔用較大

啟動快,體積小,記憶體佔用低

技術演進

讓小程式業務低成本適配 Cube 渲染小程式,需要做三方面的工作:

  • 擁抱 Web 技術,補齊前端開發常用的能力:包括 CSS,小程式元件等;

  • 完善相關工具:包括開發,除錯,Profile,釋出,打包等;

  • 針對 Cube 的架構特點,深入優化,並拉開和 Web 渲染的差異。提供更好的使用者體驗。

新的流式佈局(Flow Layout)

最初 Cube 小程式使用只支援 Flex 佈局 Yoga 用於佈局計算。後面升級成支援 Block,Flex,Inline-Block等多種佈局方式的 Flow Layout。從而解決開發者只能使用 Flex 佈局的困擾。目前兩個佈局引擎 Cube 內部都支援。其中 Flow Layout 主要用在小程式,Yoga 用在卡片。兩者能力差異如下:

Yoga

Flow Layout

display: none

:white_check_mark:

:white_check_mark:

display: flex

:white_check_mark:

:white_check_mark:

display: inline

:x:

:white_check_mark:

display: block

:x:

:white_check_mark:

display: inline-block

:x:

:white_check_mark:

display: inline-flex

:x:

:white_check_mark:

display: -webkit-box

:x:

:white_check_mark:

display: grid

:x:

可以擴充套件支援

支援 CSS 樣式表

老版本的 Cube 只支援內聯樣式和簡單的 CSS 選擇器;然而小程式並沒有約束 CSS,因此 Cube 擴充支援 CSS 樣式表,樣式繼承,多種選擇器等。從而使得 Web 渲染切換到 Cube 渲染,適配成本大大降低。甚至部分小程式可以做到在小程式 IDE 裡基於 Web 渲染開發,然後打包成 Cube 渲染產物在真機上預覽。前端同學無需進行過多的修改和適配。

新老 Cube 版本,選擇器支援上的差異如下:

老版本 Cube [1]

新版本 Cube

內聯樣式

:white_check_mark:

:white_check_mark:

id 選擇器

:white_check_mark:

:white_check_mark:

類選擇器

:white_check_mark:

:white_check_mark:

元素選擇器

:white_check_mark:

:white_check_mark:

樣式繼承

:x:

:white_check_mark:

偽類、偽元素

:x:

:white_check_mark:

屬性選擇器

:x:

:white_check_mark:

選擇器分組

:x:

:white_check_mark:

分組選擇器

:x:

:white_check_mark:

組合器

:x:

:white_check_mark:

@keyframes

:white_check_mark:

@fontface

:x:

:white_check_mark:

@media

:x:

可擴充套件支援

注:

  • [1] 老版本 Cube 是指:錢包 10.2.0 以前版本;

  • 新樣式能力基本上對標 Web 引擎的樣式能力;

  • 新樣式能力支援像這種複雜選擇器。

    div > div.jartto p span.yellow a#t1 {}
    .pixel-ratio-2 .web1px::before {}
    div:nth-child(2n+1) {}
    input[type="button"] {}
    #blue,div > div.jartto p span.yellow a#t1 {}

支援自動分詞,斷行(Inline Text)

最初 Cube 用的是 Android 和 iOS 提供的文字計算和繪製能力。這種技術方案(以下稱為平臺層 Text)存在3個問題:

  1. 效能問題:特別是 Android 下,利用 Android 平臺層的介面實現文字佈局計算,導致在文字較多的情況下,佈局耗時在渲染整體耗時裡佔比較高;

  2. 富文字特性:富文字以及許多文字特性支援較麻煩;

  3. 各平臺上實現文字效果存在細節差異或者相容性問題。

針對上述問題,在 Flow Layout 基礎上增強支援 Inline Text 佈局計算文字。基於 Inline Text 可以較輕鬆實現以下富文字,圖文混排,分詞,自動換行等。

1.富文字

2.自動換行和分詞

Inline Text 實現前後的文字樣式對比如下:

平臺層 Text

Inline Text

width: fit-content

:x:

:white_check_mark:

overflow-wrap: break-word 或 anywhere

:x:

:white_check_mark:

word-wrap: break-word 或 anywhere

:x:

:white_check_mark:

text-align: jusify

:x:

待支援

text-align-last

text-align-start

:x:

待支援

text-emphasis

:x:

待支援

text-decoration: overline

:x:

待支援

text-decoration-color

:x:

待支援

line-break

:x:

待支援

word-break

:white_check_mark:

white-space

:white_check_mark:

vertical-align

:white_check_mark:

font-family

:white_check_mark:

font-face

:white_check_mark:

font-weight

:white_check_mark:

float

:white_check_mark:

clear

:white_check_mark:

line-height

:white_check_mark:

注:

  • 假設原有 Cube 採用平臺層介面實現的文字特性稱為: 平臺層 Text

  • 表示實現細節上不完善或者不完全支援;

  • 在 Inline Text 基礎上可以實現功能豐富的富文字元件;

  • 值得一提的是:該實現非常精巧,對於 Cube 包體積只增加了 170KB。具體細節後續文章詳細探討。

文字佈局計算耗時對比(文字節點較多場景):

Yoga

平臺層 Text

Flow Layout

平臺層 Text

Flow Layout

Inline Text

佈局耗時

單位(ms)

456

763

170

採用 QuickJS 替代 V8

V8 雖然是效能最高的 JS 引擎,但是存在記憶體佔用大,初始化較慢等不足。在 IoT 或者低端裝置上這些不足會被放大。因此在這些裝置上,Cube 採用 QuickJS 取代 V8。一方面降低記憶體佔用,另外一方面提升初始化效能。

Cube 內部目前適配了多個 JS 引擎,具體如下:

  • 在 Android 移動端上使用 V8 和 JSI

  • iOS 上使用 JSC

  • IoT 等低端裝置上使用 QuickJS

另外我們在開源 QuickJS 基礎上做了些優化工作。優化的結果大致如下(後續文章將詳細介紹):

V8 Bench

開源 QuickJS

優化後 QuickJS

效果

DeltaBlue

627

731

+16.5%

Crypto

893

933

+4.5%

Ray Trace

459

1194

+160%

Earley Boyer

973

1906

+95.9%

RegExp

178

265

+48.9%

Splay

756

1783

+135.8%

Navier Stokes

1644

1643

0%

分數(越高越好)

672

991

+47%

支援動畫和多媒體元件

除了上述基礎元件和能力之外,動畫和多媒體也是部分小程式不可缺少的。因此我們擴充套件支援了 VideoCanvasLottieLive Player 等元件支援。並應用於 TV 大屏小程式、小遊戲以及直播場景上。

在低端裝置上,如何提高動畫幀率並且降低記憶體佔用也做了深度的優化。以下是 Video 和 Canvas 元件在小程式中的效果圖:

Cavas 元件

Video 元件

支援多種模式的小程式產物

目前 Cube 支援多種模式的小程式產物: NativeCubeShared

  • Native模式:對應的是舊的 Cube 渲染小程式模式,不支援 CSS 樣式表,只能支援內聯樣式和有限的幾種 CSS 選擇器。效能最高,相容性較低;

  • Cube模式:在 Native 模式進化而來,支援 CSS 樣式表和多種 CSS 選擇器。效能良好,支援常用的 CSS 樣式和特性(包括樣式繼承,多種 CSS 選擇器);

  • Shared模式:為了降低 Web 渲染的小程式遷移或者過渡到 Cube 渲染而開發。在同一個小程式產物裡既支援 Web 渲染一部分頁面又支援 Cube 渲染一部分頁面。而且 Cube 渲染的頁面支援樣式表。這樣在效能和相容性平衡。小程式產物相對於 Web 渲染的小程式,產物體積增加不會超過 10%。

Native 模式

Cube 模式

Shared 模式

小程式產物體積

較小

稍大

小程式效能

稍低

小程式相容性

一般

稍高

新樣式

不支援

支援

支援

新佈局

支援

支援

支援

注:如果需要 Web 產物兜底,則 Native 模式Cube 模式 的小程式產物,比 Shared 模式 大。

當前工作

Cube 小程式在 TV 和 POS 機上和相關團隊,一起打磨小程式技術棧(包括渲染引擎,JS 引擎,AppX,Ariver 容器)等。

在 TV 上面臨的問題:

  • 記憶體少:有的裝置只有 512MB 記憶體,長列表滾動容易卡;

  • 需要支援焦點切換;

  • CPU 主頻較低:有的只有 1GHz。

短中期目標是用小程式技術棧替代 WeeX 單頁。當前進展如下:

  • 小程式啟動效能上超過 WeeX 單頁(低端裝置上優勢更明顯);

  • 記憶體佔用上,小程式初始化後記憶體佔用小於 10MB,典型小程式整體記憶體佔用在 32MB 左右。

具體細節後續文章詳細總結。

在 POS 機上面臨的問題:

在 POS 機上跑點餐小程式,主要有面臨以下問題:

  • 記憶體少:部分裝置只有 512MB 記憶體,容易出現卡死和 OOM;

  • CPU 核心少:部分 CPU 只有雙核(硬體效能大約是主流手機的 1/5);

  • 長列表滾動卡。

短中期目標是用小程式技術棧替代 Flutter 開發的 App。當前進展如下:

  • 小程式首屏啟動效能提升了 30%+;

  • 小程式重點的互動場景的頁面,比如:購物車,商品詳情頁等,都已接近 Flutter App;

  • 首頁滾動幀率達到 50 ,使用者已經難以感知和 Flutter 的差異(Flutter 幀率是 60);

  • 小程式記憶體佔用下降了 30%(本地測試已無卡死和 OOM)。

該場景主要是文字節點較多的長列表。採用了非常多的優化方法,後續文章詳細總結介紹。

總結

為了適配小程式,Cube 渲染引擎在佈局計算、樣式能力、元件支援,還有開發工具等在小夥伴一起努力下取得了較大的進展。同時在低端裝置(比如:IoT 裝置)或者效能敏感場景,Cube 小程式效能優化,降低記憶體佔用也取得了不錯的效果。而未來面對多種多樣的 IoT 裝置,還需要加速技術演進以支援更多的場景。歡迎大家一起來交流討論。

關注我們,每週 3 篇移動乾貨&實踐給你思考!