本文來自QCon全球軟件開發大會王勁鵬的技術分享,下文進行了排版優化和修訂。
1、引言
性能和體驗在 iOS / Android 雙端場景下已經是一個較為成熟的話題,但隨著鴻蒙 OS 的發展,端側開發者需要更多的關注多端場景的差異性。
本次分享的主題是小紅書在鴻蒙平臺上的工程實踐,主要聚焦于性能優化和探索。(* PPT講稿原文下載:《小紅書鴻蒙OS下的性能優化探索與實踐(PPT)[附件下載]》)
先介紹一下自己的背景。之前一直從事大前端領域的工作,主要專注于跨端和容器化方案。也曾手寫過一個跨端框架,名為 Doric,它可以對標 React Native、Vue Native 和 Flutter 等。Doric 框架在落地時表現良好,還支持了一些自研的 3D 引擎方案。除此之外,我還有播放器內核研發經驗,以及大前端常規體系建設和 CI/CD 流水線的工程經驗。未來,我將持續關注大前端的演進,尤其是鴻蒙這樣的多端和跨端平臺。
從 2023 年開始,鴻蒙的優勢愈發明顯,已經成為可與 iOS、安卓媲美的第三大移動操作系統。從一些抖音視頻中也可以看出,鴻蒙在流暢性方面甚至在某些層面上超過了 iOS。
今天的分享內容分為四個部分:
- 1)介紹整個歷程和背景;
- 2)介紹鴻蒙 OS 的相關能力和小紅書在該平臺上的優化實踐;
- 3)通過鴻蒙 OS 提供的性能驗證工具,展示小紅書在鴻蒙平臺上的性能優化驗證方法、優化后的性能提升以及具體的收益和結果;
- 4)總結和展望。
2、內容分享和整理
分享者:王勁鵬,內容審校和編輯:Kitty。

王勁鵬:小紅書鴻蒙工程師。目前主要負責小紅書鴻蒙版的研發和工程建設,曾從事過大前端架構設計、研發效能等方向的工作,在終端架構演進、性能優化以及跨端容器和動態化等方面具備長期實踐及深厚經驗,持續關注大前端技術體系,鴻蒙以及多端的演進。
3、版本歷程和開發背景
3.1 小紅書迭代歷程
從 2023 年年中開始,鴻蒙的“千帆計劃”正式啟動,并很快升級為“鴻飛計劃”。小紅書作為 7 家頭部合作商之一,率先支持了鴻蒙,并于 2023 年 11 月中旬上線了一個基礎版的 beta 版本 APP。這個版本主要包含筆記瀏覽和視頻筆記瀏覽兩大功能,以及一些簡單的個人設置。當時,小紅書的動作非常迅速,可以說是頭部應用廠商中對華為支持最為積極的品牌之一。
在整個鴻飛計劃中,我們規劃了三個核心里程碑:除了 2023 年 11 月的 beta 版本外,還包括 2024 年 6 月的 HDC 版本和 2024 年 9 月的商用版本。HDC 版本主要是針對華為正式宣發鴻蒙 3(HarmonyOS Next)開發者測試的情況。在 HDC 版本中,我們上線了許多小紅書特有的存量功能,包括視頻拍攝、圖文拍攝以及多設備協同等創新特性。而到了 2024 年 9 月的商用版本交付時,小紅書的核心功能已經基本與主端對齊。考慮到鴻蒙的開發周期僅有一年,小紅書的鴻蒙 APP 在這一年中要對齊開發了十年甚至十幾年的安卓和 iOS 版本,難度和壓力都非常巨大。
到 2024 年 9 月,除了對齊雙端的所有功能外,我們還開發了許多其他功能,包括華為支持的創新特性,例如智能拖拽——用戶可以將圖片拖拽到中轉站或小藝等場景。此外,商用版本還支持了用戶呼聲較高的 HDR 或 Moonlight Photo 拍攝能力。
3.2 純血鴻蒙與安卓的區別
我從幾個維度來對比一下純血鴻蒙和安卓 OS 的主要區別。
內核架構純血鴻蒙的本質是微內核,而安卓是基于 Linux 宏內核。微內核只提供基礎的內存和文件管理能力,驅動和其他系統能力都在 OS 之外。這樣做的好處是系統穩定性極高,即使應用崩潰,也不會導致整個系統崩潰(system crash)。而在 Linux 宏內核中,應用的不當行為可能會直接導致系統崩潰。
多設備適配鴻蒙目前支持多種設備類型:包括 Mate 60 Pro 這樣的直板手機、Mate X5 或非凡大師 XT 這樣的雙折疊和三折疊手機、平板電腦、車機,甚至華為正在研發的鴻蒙 PC。鴻蒙真正實現了類似 iOS 的多端整合能力,通過一套代碼實現多端部署。其工程體系和架構支持單 HAP(Harmony Ability Package)多 HSP(Harmony Service Package)模塊,指令集適配了 ARM64 等多種架構,開發者只需根據設備尺寸適配 UI 展示即可。例如,在 2024 年 9 月 的華為全場景設備發布會上,余承東展示了小紅書在從直板機到雙折疊、三折疊設備上的適配能力,完全實現了響應式編程,不同設備形態下有不同的瀏覽體驗。
開發工具和編程模型鴻蒙的開發工具和編程模型與安卓差異較大。鴻蒙更類似于 Flutter 的嵌套型容器布局,而不是安卓那種面向對象的開發方式。在語言層面,鴻蒙完全封裝了底層邏輯,采用類似前端 Flux 單向數據流模式,通過數據變更驅動 UI 刷新。這種模式類似于前端 Redux 或 MobX 框架中的 state 管理 。
從 2024 年 10 月 8 日公測開始,鴻蒙的應用生態正在逐漸繁榮。不過,目前像微信這樣的應用還處于搶先體驗階段。相比之下,安卓的生態已經相對成熟。鴻蒙的最終目標是打造全場景智能設備生態,涵蓋所有終端設備,以及基于 OpenHarmony 內核開發的物聯網終端。它還支持多種芯片體系,例如瑞芯微 RK3568 等。
3.3 小紅書鴻蒙應用架構層級
小紅書經過一年的迭代,其整體應用架構已經基本成熟。目前,整體代碼量接近 200 萬行,達到了一個較高的復雜度。在一般成熟的 APP 架構中,通常會包含一些基礎底層能力,例如網絡、磁盤存儲、埋點體系、APM(應用性能管理)系統,以及一些通用組件和能力。對于鴻蒙平臺,小紅書還具備一些特殊的公共通用能力。
我們開發了一個“一多框架”,這是一個支持一套代碼多端部署的具體框架體系。通過這個框架,我們實現了多設備的斷點控制功能。用戶可以根據設備的尺寸和類型進行適配,因為華為設備支持多端投屏。例如,用戶可以在手機上瀏覽小紅書,然后將內容投屏到車機上。比如用戶購買了一輛問界汽車,可以在車內通過車機繼續瀏覽手機上的小紅書內容,這種場景在駕駛時尤其有用。
除了底層框架,對于上層業務,小紅書還有一套自研的組件庫方案,這套組件庫承載了上層業務的多種功能,包括圖文筆記、視頻筆記瀏覽,以及一些 Hybrid 容器能力。小紅書本質上在跨端開發中仍然使用了 React Native(RN)和類 Web 技術。RN 引擎由華為內部合作提供,采用了自研的 ohos 方案,用于解決 React Native 的 bundle 和 JS 加載以及渲染問題。此外,還包括產品定制層,這里涵蓋了所有相關的設備適配內容。

3.4 性能優化與實踐
目前,安卓和 iOS 在性能優化方面已經相當成熟,包括如何分析性能熱點問題、有哪些工具以及最佳實踐等。然而,對于鴻蒙來說,它是一個全新的系統。直到 2024 年年中,鴻蒙的穩定性和流暢性都還存在一些問題。這里重點講述小紅書在 2024 年與華為一起進行了哪些實踐,以提升應用的性能和用戶體驗。
我們定義了一個性能指標場景。這個指標體系是小紅書與華為共同探討的結果,因為華為有一個性能工廠,它對每個應用的評級都有一個 S 標標準。小紅書與華為一起確定了針對小紅書場景需要觀測的具體指標。性能優化的核心是慢函數指標,它主要包含兩部分:過程時長和應用體驗的流暢性。
過程時長主要包含以下三點:
- 1)冷啟動時長:這是用戶最關心的指標之一,即從點擊應用圖標到應用完成動畫并展示第一幀的時間。對于多數應用,首頁通常有緩存機制。例如,小紅書會緩存用戶上次刷新的筆記,淘寶會緩存用戶上次瀏覽的商品內容;
- 2)場景完成時長:指完成某個特定場景所需的時間;
- 3)應用響應時長:指用戶操作界面后,界面真正發生變化的時間,即響應時延。
流暢性方面,最基礎的觀測指標是平均 FPS(幀率),包括丟幀數、最大連續丟幀數、丟幀卡頓次數以及卡頓率。卡頓率可以通過量化計算得出:當一個場景中出現丟幀時,丟幀的時長與場景總時長的比值即為卡頓率,它是一個小于 1 的百分比數值。
3.5 OS 能力 & 優化實踐
首先,針對 IO 場景,我們進行了相應的優化。
鴻蒙 OS 的系統能力主要分為以下三個方面:
- 1)并行化能力鴻蒙 OS 提供了兩種并行化能力:Worker 和 TaskPool。Worker 類似于傳統的線程模型,每個 Worker 都有自己的內存空間和執行單元,支持通過消息(message)進行通信。TaskPool 則類似于協程或線程池,能夠動態管理線程數量,支持標記為 @concurrent 的函數直接在任務池中調度和運行。這兩種機制都支持線程間隔離,內存不共享;
- 2)多線程通信和數據傳輸在多線程通信方面,鴻蒙 OS 支持序列化數據傳輸和基于消息(message)的通信機制。此外,還引入了事件發射器(Emitter)用于系統事件的發布和訂閱。這種機制允許線程間通過消息傳遞來實現復雜的交互邏輯;
- 3)同步轉異步機制鴻蒙 OS 支持基于 Promise 的異步編程模型,包括 async 和 await 語法,以及 then 和 catch 方法。這種機制能夠有效提升應用的響應性和用戶體驗。
4、并行化能力
在并行化能力方面,鴻蒙 OS 提供了兩套基礎實現方式。開發者可以通過 RTS(運行時系統)實現并行化,也可以通過底層庫(如 C++ 標準庫中的)實現。不過,如果完全依賴底層庫,可能會導致開發效率下降。為了滿足業務需求,鴻蒙 OS 在年初引入了 Worker 和 TaskPool 能力。Worker 類似于傳統的線程模型,每個 Worker 都有獨立的內存空間和執行單元,支持通過消息進行通信。消息可以包含可序列化的數據,也可以通過指針直接遷移數據。TaskPool 則類似于線程池,能夠動態管理線程數量,支持標記為 @concurrent 的函數直接在任務池中調度和運行。與安卓平臺的線程池不同,鴻蒙 OS 的 TaskPool 會根據硬件條件和任務負載動態調整線程數量。這種機制避免了安卓平臺中因線程池數量過多而導致的系統資源消耗問題。
接下來我們對比鴻蒙 OS 的 Worker 并行化能力和安卓端的相關特性。從多個維度來看,Worker 本質上不推薦手動創建,而是通過系統配置 build-provider.json 綁定 ETS 文件來實現創建。這一點與安卓端并無明顯差異,安卓端可以通過 THREAD 等方式啟動線程。
在鴻蒙 OS 5.0 以下版本(如 4.2 版本)中,主要運行的仍然是安卓系統。這種情況下,安卓線程數量存在上限,這對應用開發者來說是一個挑戰。如果 SDK 集成過多,線程數可能超標,進而導致應用被系統強制終止,或出現業務場景異常崩潰等穩定性問題。
數據傳輸方面:鴻蒙 OS 為了優化 Worker 的性能和負載,對 Worker 的數量和單個 Worker 的傳輸上限進行了限制。鴻蒙 Worker 的單個傳輸上限類似于安卓中的 Binder 機制,也存在類似的傳輸限制。不過,安卓線程通常沒有嚴格限制,因為線程本質上是一個內存拷貝過程,除非開發者通過指針等方式自定義線程間數據傳輸。
在傳輸格式上:鴻蒙 OS 支持通過 Sendable 接口進行數據傳輸。Sendable 是一種注解方式定義的數據結構,具有傳染性,即如果一個類被標記為 Sendable,其關聯屬性也必須是 Sendable 類型。鴻蒙 OS 支持基礎數據類型(如 number、string)和集合類型作為 Sendable 傳輸的內容。對于跨模塊調用,鴻蒙 OS 不允許 Worker 跨 HAP 或跨 HSP 調用。相比之下,安卓應用通常運行在一個或多個 Dex 文件中,允許跨 Dex 或跨模塊的線程間調用。
TaskPool 類似于雙端的協程概念,是一種輕量級線程,僅存儲函數。不過,TaskPool 與協程有所不同,它獨立于任務維度,且任務執行時長有限制(超過 3 分鐘會被系統自動回收)。安卓平臺可以通過 ASM 插樁技術對線程的創建和執行進行監控和優化,但輕量級線程或協程的實現通常依賴于線程池或協程機制。
TaskPool 中的任務默認支持數據轉移(transfer),不支持拷貝。此外,TaskGroup 不支持 SDK 初始化包的加載。某些同學習慣在異步線程中觸發 SDK 的行為,在鴻蒙 OS 上可能會因 TaskPool 生命周期結束而導致變量被釋放。
關于并行化數據傳輸的 Sendable 概念:Sendable 通過系統提供的 SharedHeap(共享堆)實現傳輸。共享堆與本地堆(local Heap)的區別在于,共享堆支持 Sendable 化數據的傳輸,而本地堆則需要序列化。共享堆的管理和控制耗費了華為專家大量時間和精力,其中還涉及復雜的異步鎖(async lock)機制。在 RTS 并發實例期間(包括 Worker、TaskPool 等),數據可以通過 Sendable 傳遞,但 Worker 需要使用單獨的 API。TaskPool 則完全支持 Sendable 的直接傳輸。這種異步鎖機制允許在 TaskPool 或 Worker 中鎖定其他任務中的某些函數,實現線程間的同步,類似于安卓中的 synchronized 或其他鎖機制。
5、小紅書典型并行化場景
小紅書在一些典型化場景中已經實現了并行化處理。例如,網絡請求是一個典型的耗時操作,因為請求過程中涉及驗簽和安全能力的處理,這些操作如果在主線程中同步完成,可能會導致應用掉幀。當用戶滑動時,掉幀現象會非常明顯,這通常是由于大量計算引起的。為了解決這一問題,我們采用了 Worker 化的方式,將這些操作移到 Worker 線程中,從而避免主線程的卡頓。
在進行埋點時,可能會涉及數據庫的 IO 操作,這些操作也不建議在主線程中執行。通過將這些操作放到 Worker 線程中,可以有效避免對主線程的影響。
針對雙列布局中的圖片和資源預加載,我們采用華為自研的 RCP 網絡解決方案(類似于 HTTP),通過 Worker 線程在遠端進行下載,并在完成后將結果返回到主線程。此外,TaskPool 的應用場景也非常廣泛,例如文件上傳、多媒體操作以及啟動任務的編排等。TaskPool 的優勢在于輕量化,避免了線程上下文切換帶來的不必要耗時。
關于冷啟動和首刷場景的優化。這部分主要包括兩個方面:模塊的懶加載和動態組件的復用池。懶加載是應用開發中常見的優化手段,類似于安卓端的 class order 機制。當應用不需要某個類時,可以延遲加載該類,直到真正需要使用時才加載。這種方式可以顯著提高冷啟動階段的代碼加載效率,從而大幅降低冷啟動時長。
動態組件和組件復用池則是為了解決 UI 組件重復創建的問題。在應用中,可能會有多種相同類型的 UI 組件(例如小紅書中的筆記組件)。為了避免重復創建帶來的開銷,我們希望在運行時盡量復用已有的組件,而不是頻繁地創建和銷毀。
6、類前端視角下的模塊懶加載
我們通過特定的分析工具對懶加載進行了深入分析。如圖所示,我們能夠識別出啟動過程中加載的各種模塊,包括 RNOH(React Native on Harmony)、Web engine(網頁引擎)、Red Player(播放器)等組件。這些模塊的加載過程涉及到多個.so 文件,即共享對象文件。

通過自上而下的分析方法,我們可以清晰地看到每個模塊加載的具體耗時。進一步分析這些.so 文件與 RTS(運行時系統)的關聯,以及它們所引入的 Napi 的 TS 文件。我們進行了懶加載潛在對象的分析,發現許多 RTS 實際上并不需要的類文件已經被加載。這是因為開發者在編寫代碼時,可能并未充分考慮到導入一個類或方法對應用啟動延遲的影響。
為了優化這一過程,我們的目標是減少字節碼中需要加載的類文件數量,從而加快應用的冷啟動速度。華為提供的編譯器能夠將 RTS 編譯成 Ark bytecode(方舟字節碼),這是一種高效的字節碼格式。通過減少需要加載的類文件數量,我們可以顯著提高應用的啟動速度。
華為還提供了一種懶加載的導入方式,只有在真正需要使用某個類時,它才會被加載。這種懶加載機制有助于減少應用啟動時的資源消耗。這引發了一個問題:為什么華為不默認采用全懶加載方式,即只有在使用時才加載類文件呢?我已經將這個問題反饋給華為,并且系統側可能會考慮在未來的版本中默認采用懶加載方式,同時仍然允許用戶手動選擇非懶加載的方式進行類文件的加載。
7、動態組件
在小紅書的首頁場景中,筆記卡組件在多個場景中被復用。為了避免重復創建 UI 導致的性能消耗,我們采用了動態組件的概念。動態組件的核心原理是利用占位符來延遲組件的創建,這與 Android 開發中使用 Stub 模式的概念相似。在這種模式下,可以使用一個代理對象(stub)來代表尚未初始化的組件,從而延遲組件的創建過程。當真正需要渲染組件時,再將渲染內容填充進去,從而避免每次調用構建函數(如 build)時的耗時。
占位邏輯通過系統的 API 實現,涉及到 NodeContainer 和 NodeController 的綁定關系。Container 和 Controller 一一映射,由 NodeCore 進行管理。Container 僅管理當前展現的內存部分,使用完畢后需要將其放回池中進行回收和再利用。以冷啟動首刷為例,在啟動階段可以先獲取磁盤上的筆記內容,然后在 BuilderNode 中預先創建多個 Image 組件。這樣,在等待網絡或推薦接口響應時,Image 組件已經創建完畢,從而在首頁刷新時可以立即使用這些組件,這對于提高首刷非常有益。

對于組件復用池,當動態組件不再使用時,需要將其返回到組件池中。對于自定義組件,通過 NoteContainer 占位方式,由 NodeController 進行管理。在需要創建子組件時,先在 NodePool 中查找,如果找不到,則創建新組件;如果找到,則嘗試復用。流程圖展示了從 Container 裝載 NodeItem 開始,通過 NodePool 查找,如果找到則進行條件判斷和復用。
組件的新建和復用過程中,如果找到對應的 NodeItem,則調用 build 方法并更新自定義組件的狀態,完成復用。如果有對應的 NodeItem,可以直接通過 update 函數更新內部狀態并刷新 UI。但要注意,update 方法可能會因狀態變量過于復雜而導致更新延遲,出現圖像殘影。因此,需要拆分 state,使其足夠小,以確保狀態變更到通知 UI 的時間縮短,消除殘影。
我們的策略是優先在 NodePool(節點池)中查找可用的 NodeItem(節點項)。如果 NodePool 中存在可用的 NodeItem,我們就直接使用它,并通過 getNode 方法進行 item 綁定,隨后更新其狀態以實現復用。如果 NodePool 中沒有找到對應的 NodeItem,那么我們將通過 makeNode 方法調用 build 函數來創建新的節點項。
完成組件的復用后,我們需要將這些組件返回到緩存池中,以便在未來可以再次使用。這個過程涉及到 NodeContainer(節點容器)和 NodeController(節點控制器)的銷毀,并將 NodeItem 重新放回 NodePool 中。為了更有效地管理緩存,業務層可以利用 LRU(最近最少使用)算法,或者鴻蒙系統提供的 LRUCache 和 LiUHashMap 等數據結構,來自定義緩存的大小,從而優化組件的復用和緩存策略。
8、滑動類場景
在小紅書應用中,滑動類場景非常普遍,包括推薦頁的子頻道、個人頁中的收藏點贊以及用戶自己發布的筆記,還有搜索結果頁中的搜索結果和用戶商品等,這些都是雙列滑動場景。這些雙列滑動場景占據了小紅書用戶體驗的 90% 到 95%,因此,滑動體驗的流暢性對于用戶的整體體驗至關重要。
為了提升滑動場景的流暢性,小紅書采用了 RCP 框架來優化網絡資源的獲取。RCP 是華為提供的一個系統組件能力,主要解決網絡資源獲取效率問題。通過 RCP,開發者可以在需要時發起網絡請求,并自定義資源的寫入地址,如文件或 ArrayBuffer。RCP 負責高效地將資源寫入指定位置,而在不需要時,可以取消 RCP 請求,從而優化資源管理。

RCP 的核心能力在于能夠取消請求,并對弱網場景進行了優化,其建聯過程優于 HTTP 1.1 或 2.0?;?RCP,小紅書還應用了華為俄研所提供的 Prefetch 方案。Prefetch 方案在瀑布流組件的可見區變更時,通過 worker 線程(如 prefetched worker)啟動資源獲取,當不可見時關閉,從而優化快速滑動場景,減少不必要的帶寬消耗。
在快速滑動過程中,有些 item 可能短暫消失,對于雙端場景,網絡請求可能已經發出且在途,無法取消,導致帶寬浪費。Prefetch 和 RCP 結合的方式可以優化這種快滑場景,防止真正想要看的內容出現白塊。Prefetched worker 線程管理多個 RCP 請求,每個請求都有完整的生命周期。當通過 RCP 請求獲取到所需資源時,會通知主線程,主線程根據地址加載資源到 Image 組件或占位符 RQI 組件中。
在小紅書的開發過程中,我們遇到了一些性能熱點問題,這些問題大多是通過 Code Linter(代碼檢查工具)檢測出來的。由于開發節奏快,開發者在編寫代碼時可能難以關注到性能問題,因此需要 CI(持續集成)檢查工具來輔助檢查。
常見的性能熱點包括:
1)在列表場景中頻繁使用的 LadyForEach 組件,需要指定 key 以實現列表復用。如果開發者忘記指定 key,Code Linter 會報錯提示;
2)在 onClick 或 onVisible 等函數中編寫空 callback(回調函數)。當這些空 callback 積累到一定數量(如幾百個或上千個)時,可能會嚴重拖慢應用性能。Code Linter 可以掃描出這類問題;
3)未使用 TaskPool 處理網絡資源。例如,Image Bitmap 直接傳遞 URL 進行同步加載,當網絡阻塞時會導致 UI 線程卡頓;
4)復雜的 ETS 組件在列表場景下未實現重用。未設置重用的 ETS 組件在列表滾動時需要重新構建,非常耗時。組件嵌套層級過深也會導致性能問題。在安卓端,布局檢查器建議容器嵌套不超過四層;
5)使用 JSON.stringify 進行對象序列化。JSON.stringify 有一定耗時,尤其在處理 100KB 左右的數據時,可能需要 10 毫秒左右。Code Linter 會提示這部分性能問題,但是否需要轉異步線程需要開發者自行判斷;
6)調用 Image 的 syncLoad(同步加載)。在某些場景下,如轉場動畫,需要同步加載 image 以保證連貫性。但如果 image 是非磁盤資源(如網絡資源),會導致卡幀。Code Linter 可以掃描出這類問題;
7)關于編譯器的優化。ETS 組件應避免嵌套過深。如果嵌套過深,可以將每層函數通過系統的 builder param 或 builder 函數轉換。使用 @builder 注解標識的函數會在編譯期間與 ETS 代碼整合,從而提高編譯器優化效果。
Code Linter 支持全量掃描和基于 Git DIFF 的增量掃描,但目前華為的 Code Linter 還不能與 Git Prehook 關聯,導致無法在流水線上自動檢查。雖然 CI 檢查階段已有 Code Linter,但本地代碼提交階段仍需手動運行腳本,無法實現自動檢查。我們正在催促華為解決這一問題。
9、UI 重載場景分幀方案
在處理 UI 重載場景時,我們采用了一種稱為分幀方案的方法。分幀這個術語的含義是,當應用在一幀內無法完成所有繪制工作,或者在多幀內都無法完成時,會導致屏幕卡頓現象。盡管用戶可以看到畫面,但卻無法進行滑動或操作。在這種情況下,分幀方案就顯得尤為合適。雖然分幀方案可能看起來不是最優雅的解決辦法,但它確實能夠有效地解決性能問題,使應用性能達到預期標準。分幀方案雖然看似是一種應急措施,但它能夠幫助應用性能達標。
分幀方案的流程大致如下:假設我們有數據 a、b、c 需要渲染,未采用分幀方案前,數據 a、b、c 會同時到達并觸發狀態變更,進而驅動整個 UI 進行刷新。這會導致在一幀內需要繪制大量 UI 組件,從而影響應用性能。為了解決這個問題,我們采用分幀方案,將數據 a、b、c 拆分開,分別在不同的幀中進行渲染。例如,數據 a 在第一幀中渲染完成后,通過調用宏觀指令讓其進入下一階段,然后在下一幀中更新數據 b,依此類推。
在小紅書的圖文筆記場景中,分幀方案得到了應用。當用戶在首頁的雙列場景中點擊一篇筆記進入筆記詳情頁時,這個過程涉及到許多組件的加載。我們可以將這些組件拆分成不同的幀,例如幀 a、幀 b 和幀 c。對于用戶而言,他們通常希望在第一時間看到整個大屏的畫面,因此我們會優先在幀 a 中展示大圖。而在幀 b 和幀 c 中,我們再處理頂部導航欄或底部交互區等內容。通過這種分幀策略,我們能夠確保用戶在第一時間看到最關鍵的內容,同時避免了因為一次性加載過多組件而導致的性能問題。
10、鴻蒙NEXT調優工具
傳統的主觀工具對于鴻蒙 OS 的性能分析仍然適用。例如,抖音和小紅書都通過競品分析來進行主觀測評。這種能力主要是通過錄屏來展示整個流程的耗時和時長,特別適合評估冷啟動完成時延和轉場過程的性能。通過錄屏,我們可以逐幀查看用戶從點擊開始到結束的幀數和真實時長,以此來衡量整個過程的持續時間。
10.1 鴻蒙性能分析工具:IDE Profiler
除了主觀工具,我們還可以使用 IDE 提供的性能分析工具,如 Profiler,來分析慢函數。由于 ArkTS 編程語言框架主要通過 RTS 和 NAPI(原生應用接口)進行關聯,因此需要能夠查看 ArkTS 和 NAPI 的整個堆棧層級。這與安卓有所不同,因為當 Java 通過 Java Native API 與原生代碼交互時,堆棧并不那么容易查看。
在小紅書的性能分析中,我們展示了一個整體線程分析的例子。在左側,可以看到小紅書的主線程(如 com 點開頭的線程)、Daemon 線程、Worker 線程以及 FFRT 線程。FFRT 是一種運行函數流的線程,可以執行 TaskPool 上的函數。在下圖右側,我們可以看到在 RTS 環境下的分析結果,其中頂部顯示了 NAPI 調用,底部則是一些 C++ 函數。整個調用棧和它們的執行時長是通過一種自上而下的視圖來展示的。利用這種視圖,我們可以精確地識別出哪些慢函數是造成界面卡頓的原因。

10.2 性能場景測試工具:DevEco Testing
DevEco Testing 是一個性能測試工具,它的功能非常全面,性能測試只是其中的一部分。除了性能測試,它還支持多種測試場景,包括 debug testing。在 debug testing 場景中,用戶可以自定義業務場景,監測 CPU 的耗時和負載、GPU 的耗時和負載、設備發熱情況以及功耗等問題。

使用 DevEco Testing 進行性能測試的過程如下:首先定義測試場景,然后捕獲主幀數據。一旦開始捕獲,就可以觀測到 FPS(幀率)、GPU 負載以及整體功耗等數據。完成性能數據捕獲后,工具會生成一份報告,為用戶提供了一個完整的場景分析。不過,目前場景定義還缺乏腳本化能力,需要人工操作輔助。未來,我們期望能夠實現場景定義的腳本化配置,類似于自動化測試。這樣,就可以通過自動化工具,實現更高效的測試流程。
11、小結與展望
在對性能場景進行優化后,我們可以看到顯著的收益。在實驗室環境下的測試顯示,冷啟動時間可以降低 50%,響應時延可以低于 100 毫秒,完成時延則保持與雙端持平或更優。在流暢性方面,在多場景和重載場景下均實現了 0 丟幀的成果。需要注意的是,這里的測試是在非重載模式下進行的,即沒有同時運行多個資源密集型應用,如《王者榮耀》或《和平精英》等。在這種條件下,我們的核心場景,如冷啟動、搜索和個人頁等,都能夠與雙端完全對齊。

展望未來,有幾個方向:
1)首先:我們希望能夠在全場景下實現組件復用,以最大程度地實現 UI 復用。這樣可以在多個業務之間的轉場或 UI 創建過程中,將不必要的 UI 創建和消耗降到最低。
2)其次:我們正在考慮代碼延遲加載的 lazy 機制。華為內部可能將其作為通用的解決方案,但在實施過程中我們發現了許多問題,例如全 lazy 加載可能會影響第三方 SDK,如支付寶等,因為它們可能進行了額外的二進制優化,導致加載失敗或無法響應。因此,我們期望通過代碼延遲加載來實現持續治理,但目前它可能還不適合全場景的 lazy import。
3)最后:我們關注防劣化問題,即在每個版本發布時,我們不希望性能指標出現劣化。我們希望能夠在開發階段就定義劣化指標和具體數據,以防止應用劣化。這部分可能需要借助 DevEco Testing 和主觀測評的方式來實現。包括我們關注的指標,例如冷啟動和流暢性等,未來可能會納入防劣化場景。目前,我們的 CI 環節或 RC 環節,包括流水線的性能管控和代碼 CR 機制,都能夠規避這類問題。
12、相關資料
[1] 鴻蒙NEXT官方開發指南
[2] 一年擼完百萬行代碼,企業微信的全新鴻蒙NEXT客戶端架構演進之路
[3] 鴻蒙NEXT如何保證應用安全:詳解鴻蒙NEXT數字簽名和證書機制
[4] 開源IM聊天程序HarmonyChat:基于鴻蒙NEXT的WebSocket協議
[5] 微信純血鴻蒙版正式發布,295天走完微信14年技術之路!
[6] 即時通訊框架MobileIMSDK的鴻蒙NEXT端詳細介紹
[7] 即時通訊框架MobileIMSDK的鴻蒙NEXT端開發者手冊
[8] 擁抱國產化:轉轉APP的鴻蒙NEXT端開發嘗鮮之旅
[9] 微信Windows端IM消息數據庫的優化實踐:查詢慢、體積大、文件損壞等
[10] 微信技術分享:揭秘微信后臺安全特征數據倉庫的架構設計
[11] IM跨平臺技術學習(九):全面解密新QQ桌面版的Electron內存優化實踐
[12] 企業微信針對百萬級組織架構的客戶端性能優化實踐
[13] 揭秘企業微信是如何支持超大規模IM組織架構的——技術解讀四維關系鏈
[14] 微信團隊分享:詳解iOS版微信視頻號直播中因幀率異常導致的功耗問題
[15] 微信團隊分享:微信后端海量數據查詢從1000ms降到100ms的技術實踐
[16] 大型IM工程重構實踐:企業微信Android端的重構之路
[17] IM技術干貨:假如你來設計微信的群聊,你該怎么設計?
[18] 微信團隊分享:來看看微信十年前的IM消息收發架構,你做到了嗎
[19] 總是被低估,從未被超越,揭秘QQ極致絲滑背后的硬核IM技術優化
[20] 首次公開,最新手機QQ客戶端架構的技術演進實踐
[21] 大型IM穩定性監測實踐:手Q客戶端性能防劣化系統的建設之路
(本文已同步發布于:http://www.52im.net/thread-4821-1-1.html)