百度智能小程序框架性能優化實踐

移動互聯網中 Native App(NA) 和 H5 一直處在博弈狀態,在性能體驗和靈活性上艱難尋找着平衡,單從技術上來講,小程序就是 NA 和 H5 的又一次碰撞。小程序的靈活性已被證明,在性能方面,百度智能小程序從框架啓動、小程序包下載、小程序包加載以及渲染等 4 個方面進行了啓動速度優化。前端

在 GMTC 全球大前端技術大會(深圳站)2019 上,百度技術經理付嘉興結合百度側和小程序開發者側闡釋了提高自身小程序性能可採用的手段,並介紹了做爲宿主如何將小程序框架與自身技術整合。本文即根據付嘉興的演講整理而成。小程序

如下爲正文:瀏覽器

今天給你們講的題目是《百度開源小程序框架架構演進和性能優化實踐》。本次分享包含兩部分,第一部分是百度智能小程序總體的框架及演進,主要講百度小程序開發全流程概況、百度智能小程序框架,以及百度小程序多宿主運行保障;第二部分是百度小程序框架的性能優化,主要講整個小程序的啓動過程,以及從開發者角度,有哪些重要的優化點。緩存

百度智能小程序總體框架及演進安全

整個移動互聯網一直是在 NA 和 H5 之間尋找權衡,NA 的性能好、能力強;H5 靈活性更高。我認爲渲染分爲兩派,一派就是 NA 渲染派,一派叫作 H5 渲染派。性能優化

NA 渲染派,比較有表明性的如 RN 、 Flutter ;Web 渲染派,好比百度的輕應用,以及以後作的小程序。服務器

1. 開發全流程概覽網絡

打開百度APP,查看更多高清圖片架構

百度曾經作過的 Web 渲染派的三個表明產品,分別是輕應用、直達號和小程序。app

輕應用,是 H5 + 端能力。它是一個標準的 H5,增長了一些 NA 的 API,好比定位等。直達號,在技術層面跟輕應用是同樣的。小程序,本質上是一個受限的 H5 + 大量豐富的 API + UI 組件。如今咱們給小程序提供的 API 有 300 多個,組件有 30 多個,組件是有界面的。好比,視頻、地圖 。爲何小程序要受限,主要有兩個緣由:

保持體驗的一致性。H5 太過靈活,JS 隨時能夠去改變界面。安全考慮。由於咱們提供了大量 API 和組件,且這些都是很底層的一些能力,好比電話號碼、帳號,確定不能輕易開放給你們。怎麼受限,主要有兩點:

編寫語言,再也不是直接寫 HTML ,而是用自定義語言 swan 來編寫 。runtime 層有兩個棧,一個是渲染棧,一個是 JS 執行棧,這兩個棧從物理上隔離,以保障安全性。2. 智能小程序框架

(1)開發運行全流程

先簡單介紹一下整個百度智能小程序的開發流程

首先開發者用 swan 寫佈局;接着經過開發者工具打包,上傳到咱們的小程序 B 端服務器;而後是小程序的審覈流程,有機審、人審;最後是用戶點擊小程序時,客戶端請求小程序 C 端服務器,C 端服務器再從 B 端服務器獲取小程序包。整個過程都是加密傳輸,能夠保證代碼的安全。(2)百度智能小程序框架 -SWAN

上圖是一個百度智能小程序的框架,咱們內部命名爲SWAN

分層結構以下:

最上層是開發者基礎庫,命名爲 swan-js ,開發者直接和這層打交道。swan-js 負責兩件事情:即 swan 代碼轉爲 HTML,變成 WebView 可運行程序;客戶端端能力的封裝暴露。再下一層是 swan-native。這裏面最核心的是API 和組件的 NA 實現。其中雙棧管理也在這一層,另外標紅的 Extension 用於開發者宿主自身能力擴展使用,好比,貼吧宿主指望增長個發帖能力,就能夠經過此機制。再下面這層叫 Porting Layer。這層是百度小程序爲了實現開源,增長的一層與宿主的接口層。最下面這一層是宿主基礎能力層。若是宿主沒有這些能力,能夠參考百度開源的參考實現,可直接集成到宿主使用。3. 核心結構

(1)前端角度

咱們從前端的視角來看看雙棧結構。一個宿主客戶端能夠運行多個小程序,而且在一段時間內保持存活狀態,每一個小程序都有一個 master 執行框架 JS 和小程序開發者的 JS,一個 master 對應多個 slave(slave 表明一個用戶可見的界面)。

(2)客戶端角度

從客戶端角度來看雙棧結構,如上圖所示,master 負責執行 JS,能夠有兩種實現方式,WebView 或 JS 引擎(V8/jscore),JS 引擎的效率更高;slave 的展示有 WebView,爲了加快 WebView 的建立速度,設置 cache;master 和 slave 的通訊經過消息總線。

master 不支持 BOM、DOM 和 WEB-API,小程序只能調用對外開放的能力。

(3)小程序 NA 組件與界面關係

從體驗上看,小程序的體驗要好於 H5,其中有一點就是小程序會把一些 NA 的能力和 UI 融合到小程序裏面去。小程序的主體渲染仍是基於 H5 技術,接下來咱們講一下 NA 元素如何融入 UI 界面。

NA 元素與 H5 的關係有兩種,貼片關係、同層關係。

貼片關係:NA 元素在 H5 不在同一層,NA 浮在 H5 之上,H5 全部元素都不能夠放到 NA 元素之上。由於不在一層,就須要處理滾動聯動,當檢測到 WebView 滾動 n 個像素, NA 元素也須要滾動 n 個像素。

同層關係:NA 元素在 H5 這一層,H5 的原生能夠壓在 NA 元素之上。

貼片、同層的界面層級樹如上。

咱們舉一個視頻組件同層的例子。視頻組件比較複雜,有 4 層。第 1 層是視頻層,即原始視頻的圖像,第 2 層是彈幕層,第 3 層是用於視頻控制的控件層(好比,開始、暫停按鍵),第 4 層 Slot 層,視頻上面漂的 H5 元素將被放到這層。

同層處理機制,先在 H5(開發者寫的 swan 會被轉爲 H5) 上打一個特殊的標記先佔位,屬性 inline;瀏覽內核把這個區域的 surface 拿出來給到 NA 層;而後,小程序框架會把這個區域 surface 塞給播放器,讓播放器直接在 surface 上面繪製,達到同層。上面的彈幕、控件、 Slot ,都是 swanjs 層 H5 實現 ,Slot 層能夠認爲是一個容器,例如寫一個 video,其全部的子元素都會放在 Slot。

NA 的組件同層的技術方案還不太同樣,安卓和 iOS 也是有些區別的。像在 iOS 上,若是有些組件設置 over-flow ,它會自然支持這一套東西,可是安卓就須要瀏覽器內核來支持。

4. 小程序多宿主運行保障

百度智能小程序是開放系統,能夠運行在多宿主之上,那如何在多宿主上保證小程序運行體驗的一致性呢?

各個宿主集成了咱們的小程序框架後,首先要跑 CTS 測試,經過以後才能夠拿到小程序列表進行分發。

對於可選能力部分,各個宿主不是全部的能力都須要實現。好比,一些 AI 能力、push 能力。

若是一個小程序用到了可選能力怎麼辦?

兩個辦法,一是小程序和宿主之間的雙向選擇機制,小程序能夠選擇我要分發到哪些平臺,宿主也有權利選擇要分發到哪些宿主。二是,小程序作兼容

Estension 機制

上圖所示,標紅的是Extension 機制,當宿主有一些定製化的要求時,可使用此機制。做爲宿主,須要作兩件事情,一是在 JS 層須要寫一套接口;二是在 Porting Layer 接口實現層實現一套能力。若是宿主以爲這個能力是通用的,能夠反饋提案,審覈經過後,百度小程序團隊會將提案合併到開源框架裏。

5. 章節小結

百度智能小程序框架性能優化實踐

首先從用戶視角看看一個小程序的加載過程。

1. 百度智能小程序加載分階段過程

拿微博舉例,如上圖所示。

首先小程序被啓動後,先是一個 Loading 的過程,上面的 title 和下面的 tab(框架 NA 實現)顯示出來。第二張圖片咱們定義爲 FP(First Paint )階段。第三張圖下面有搜索框了,這實際上是小程序包裏面的內容。它是經過 initdate 接口初始化渲染出來的,此階段咱們定義爲 FCP( First Contentfull Paint )階段。第四張圖,是小程序從網上拉到了實時的內容,而後更新到界面,咱們將其定義爲 FMP(First Meaningful Paint) 階段。最後一張圖,全部的元素都已經拉下來並展現了,用戶能夠操做任何一個位置,咱們將其定義爲 TTI (Time to Interative) 階段。2. 百度智能小程序

(1)性能基線

百度小程序在 2019 年末創建了 FMP 指標,它在開發者平臺展現的名字爲「上屏時間」。

咱們統計了線上的一個 80 分位點,耗時是 1.9s。什麼是 80 分位點?好比,有 100 個請求過來了,而後咱們把請求的耗時排序,第 80 個請求的耗時,咱們就認爲是 80 分位點。

(2)性能歷史曲線

如上圖所示, 2019 年百度小程序性能優化的歷史曲線。

FP 框架層從接近 3s 一直優化了如今的 1.1s 左右。

百度小程序的目標是讓小程序無線接近 NA 體驗

3. 啓動流程

接下來,咱們從開發者角度看,還能優化什麼?

咱們先看一下啓動流程,全部的啓動邏輯簡單串行羅列(實際是有一些步奏是並行的)。

4. 性能優化

開發者可以作的性能優化主要有兩部分。一是小程序包的體積,二是業務數據。

接下來,我用三點來講明開發者能夠作什麼。

(1)包體積優化

建議包體積保持在 1M 之內,爲何呢?

由於咱們統計了一下,若是打開當次須要下載包,則此次的啓動時長會佔到咱們整個時長的 60%。1M 的包,80 分位速度須要 1s+ 才能下載完成。因此要控制本身的包的體積。並且咱們如今還只是看 80 分位,當咱們拉到 90 分位,99 分位,這個是一個很是陡的曲線,惡化很嚴重。

包體優化機制

有兩個技術:一是分包技術獨立分包技術,二是資源壓縮

分包技術 & 獨立分包技術分包技術

一個小程序有不少頁面,但不是全部的頁面都是高 PV 頁面。不少頁面是用戶不多點到的,能夠把這些頁面放到咱們的分包去,主包放咱們高 PV 的頁面。

分包不可以獨立運行,好比,從搜索 feed 分發過去,它運行時須要把咱們主包下載下來,可是由於它的機率低,不會影響絕大多數狀況。簡而言之,就是用分包技術把非關鍵的頁面剝離出去

用分包技術把非關鍵的頁面剝離出去以後小程序包的體積仍是大的話怎麼辦?

獨立分包技術

所謂獨立,就是說下載完這個包以後就能夠運行,無需下載主包。此時的主包和獨立分包的區別就是,小程序總要有一個入口,這個入口的獨立分包,咱們就命名爲主包。

經過這兩項技術來減少咱們的包體大小,將其保持在在 1M 之內。

資源壓縮

咱們分析過一些小程序,發現有的包體裏包含 PC 圖片,這無疑增長了包的體積。建議以下:

把圖片放到服務器,不要放在包裏面。壓縮圖片體積,好比,把 png 改成 jpeg 格式這樣體積能夠減小 90%(不考慮透明度狀況)。剔除無用資源。App-js 須要經過分包來解決,最終咱們要達到什麼目標?

單個包控制在 1M 之內。文件數控制在 200 個之內。(2) 數據拉取

數據拉取的目的是快速讓界面有內容,減小用戶的白屏時間。即便用戶是斷網的,也給他離線緩存一些數據。

如上圖所示,這裏面提到了業務骨架屏框架骨架屏。如今不少小程序都會參考 H5 的實現,把 H5 的漸進式加載骨架屏用到咱們的小程序裏面,用了這種技術以後,反而會讓真實的內容展現的速度變慢,咱們統計大概有 300ms 延遲。

爲了解決骨架屏致使的內容展現延遲,咱們作了一套框架層的骨架屏機制。按照咱們這個機制來實現骨架屏,對性能的影響就會大大減小。策略上就是在 master 作 appjs 執行時,就讓 slave 加載框架骨架屏,並行執行

本身寫的業務骨架屏,它何時才展現?

如上圖所示,當你把 App 、page、waitNotify 通知到渲染線程,到了 Ready firstRender 的時候纔會渲染本身作的業務骨架屏,這個過程固然很慢。雖然你用了骨架屏,可是骨架屏和用戶點擊的這段時間還有大量的白屏時間。用框架骨架屏,白屏時間問題就會解決。用框架骨架屏,或多或少都會耗一點時間,雖然是並行的,可是依然在搶佔手機的資源。

因此總體來看,站在客戶端或者站在框架的角度,咱們是不建議用,可是也不反對用。若是要用就用框架骨架屏,影響最小。

request 的優化,我總結主要是兩點,第一要早,第二要少。

「早」又能夠分兩部分來講,一是提前發,二是不阻塞。第一是提前發,請求得太晚,展現固然比較慢了。建議把網絡請求放在 onlaunch 裏面,這是咱們給小程序開放的第一個事件,不少小程序會放到 page unload 裏面,這個就比較慢了。這兩個時間在線上 80 分位,大概差 200ms~300ms。第二個是不阻塞,常常看到一些小程序,一塊兒來之後,它要等用戶的受權、定位。一般定位涉及 XY 座標,可是定位一旦涉及高度,就須要打開 GPS,這樣性能又會慢 2s~3s。若是不須要高度就不要去設置,不然很是慢。還有的小程序在使用的時候會讓用戶受權,若是不受權下面什麼也不展現,阻塞了。若是能夠的話,建議在須要受權的時候再提示用戶,這樣用戶也不反感,也能加快啓動的速度。

「少」,主要分爲兩點,一是非關鍵請求延後,二是隻拉取一屏數據。一個小程序運行後,可能有幾十甚至上百個網絡請求,小程序除了本身的業務還要打點,這會很大程度上影響咱們的網絡速度。由於通常的宿主在底層的網絡庫都會設置線程池,請求多了就要排隊。小程序框架根本不知道某個請求是核心請求仍是非核心請求,只能排隊。要是一上來全是一些打點的,業務就阻塞了。總之,整個頁面須要顯示的數據先請求,非關鍵請求延後。二是隻拉一屏數據,分段加載。

(3)渲染

setData 操做是較爲昂貴的,儘可能減小數據量和次數

如上圖所示,setData 是一個很是核心的 API, 當網絡數據回來,只有通過 setData 驅動渲染,內容才能顯示到界面上。

上圖是一個優化前和優化後的對比。咱們能夠看到,即便是 1K 的數據,也須要 20ms 左右的時間。若是 js 是用 WebView 來執行,首先一個 JS string,到了瀏覽器有 Renderer 線程、Browser 線程,變爲 C 層的 string,而後再到咱們 NA ,經過 Java interface,變成一個 Java string。而後到了 slave 之後還要再反過來,因此快不了。雖然咱們作了一些優化,經過內核讓它變成一個內存指針優化切換,可是仍是很昂貴。

發現有些小程序在使用的過程當中, setData 使用有不少不當之處,如下是使用 setdata 要注意的幾點 。

減小調用 setData 次數。goodcase:將屢次 setData 合併成一次 setData 調用。減小 setData 數據量。badcase:新一頁數據添加上以前頁面數據後再調用 setData。變量變化只更新變量不更新對象。5. 性能自查

性能自查主要有三個階段,即開發階段、測試階段和上線後。

在開發階段這部分,咱們有三個手段去性能自查,分別是工具體驗評分、性能面板(在客戶端上性能面板能夠提示整個性能啓動的耗時)以及打點系統。在測試階段咱們有兩個手段,一是錄屏,二是高速攝像頭,這兩個手段能夠真實地反應用戶的體驗。上線以後,有開發者平臺。如何獲取技術的官方支持途徑?建議去開發者文檔和社羣去獲取技術支持。

6. 章節小節

開發者可從包體積、數據請求、渲染三方面去優化性能。包體:1M 內。分包技術、壓縮圖片、無用資源剔除。骨架屏:若是要使用,建議採用框架骨架屏。setData:減小頻度、減小數據量。總體回顧以下圖。

相關文章
相關標籤/搜索