重磅!支持鴻蒙!騰訊視頻ovCompose跨平臺(tái)框架發(fā)布
背景
隨著鴻蒙的推出,客戶端跨平臺(tái)需求被推到了前所未有的高度,單純的 UI 跨端已無(wú)法滿足業(yè)務(wù)訴求,構(gòu)建Android/iOS/鴻蒙平臺(tái)的全跨端APP能夠最大幅度的降低業(yè)務(wù)開發(fā)成本,提升人效。并且行業(yè)內(nèi)研發(fā)模式的逐步改進(jìn),單周發(fā)版已經(jīng)成為常態(tài),對(duì)于常規(guī)APP,動(dòng)態(tài)化的訴求并不是很強(qiáng)。開發(fā)者普遍希望在保持原生優(yōu)良性能的同時(shí),使用行業(yè)通用的UI開發(fā)語(yǔ)言,從而最大程度降低學(xué)習(xí)成本。
Kotlin 與 Compose 是 Google 官方推薦的 Android 開發(fā)語(yǔ)言與 UI 框架,也是深受開發(fā)者喜愛的應(yīng)用開發(fā)方案。與其他跨端方案相比,Kotlin Multiplatform 還具備高性能,與原生交互更靈活等優(yōu)點(diǎn)。因此騰訊視頻選擇了 Compose Multiplatform 作為全跨端APP的基礎(chǔ)。當(dāng)然,這套方案也存在不支持鴻蒙、iOS平臺(tái)混排能力受限、GC性能表現(xiàn)一般等一系列問題,使得落地的過程充滿了挑戰(zhàn)。經(jīng)過不懈努力,上述問題均已得到妥善解決,現(xiàn)在我們希望將這些解決方案開源,期待與全行業(yè)一同推動(dòng)Compose跨端生態(tài)走向成熟。
特性優(yōu)勢(shì)
ovCompose已經(jīng)在騰訊視頻鴻蒙平臺(tái)全面落地,成為鴻蒙平臺(tái)首個(gè)全跨端APP。同時(shí) KuiklyBase 基礎(chǔ)能力已在騰訊視頻、QQ 瀏覽器、騰訊體育等10+款A(yù)PP廣泛落地。Android、iOS、鴻蒙三端一碼的開發(fā)方式,使得業(yè)務(wù)的開發(fā)效率得到大幅度地提升。隨著鴻蒙系統(tǒng)的發(fā)展,ovCompose 和 KuiklyBase 也會(huì)在未來(lái)進(jìn)一步擴(kuò)展到TV和PC端。
鴻蒙高性能
Kotlin鴻蒙適配有JS與Native兩種技術(shù)方案可供選擇,KuiklyBase最終選擇了Native方案。因?yàn)镵N相比JS有更快的執(zhí)行速度,更好的三端一致性。
關(guān)于 JS 和 KN 的性能測(cè)試的數(shù)據(jù)如上圖所示。我們對(duì) KN 和 Compose 兩者都進(jìn)行了性能優(yōu)化,在Compose "小球碰撞" Demo 中。以 30 FPS 為最低極限,經(jīng)優(yōu)化小球數(shù)量由600提升到1500(Android 1600球),繪制性能提升150%。后續(xù)將開放更多優(yōu)化策略。
相關(guān)資料如下:
1、 JS 和 KN 性能測(cè)試詳細(xì)數(shù)據(jù):https://docs.qq.com/sheet/DQXB4YmxQaENSdkpD?u=255d89f8184e4be69e865ce6001f298b&no_promotion=1&tab=BB08J2
2、 ovCompose 小球碰撞 Demo:https://github.com/Tencent-TDS/ovCompose-sample
3、 Kotlin 官方的 Benchmark :https://github.com/JetBrains/kotlin/tree/master/kotlin-native/performance/ring
鴻蒙三明治架構(gòu)支持混排
鴻蒙平臺(tái)采用了 Skia 的渲染方案,能夠100%支持 Compose 語(yǔ)法和渲染能力。Skia 渲染使用 XComponent 組件作為畫布,通過三明治鏤空結(jié)構(gòu),很好地解決了與原生組件的混排問題,原生UI可以展示在 Compose 上層或下層,滿足了絕大部分的業(yè)務(wù)需求。同時(shí)支持了 粘貼按鈕 等安全組件的混排,使得 Compose 無(wú)需申請(qǐng)權(quán)限也能使用系統(tǒng)能力。
三端高一致性
對(duì)于邏輯運(yùn)行:由于在鴻蒙平臺(tái)采取 Kotlin-Native 方案,解決了 Kotlin-JS 使用 TaskPool 時(shí),Kotlin 語(yǔ)法無(wú)法約束跨線程訪問的問題,保持了高度的三端一致性。
對(duì)于UI繪制:iOS、鴻蒙平臺(tái)均采用Skia渲染,Android底層使用Skia渲染,應(yīng)用層暴露了Paragraph/Canvas的繪制接口。所以基于Skia封裝后的Skiko可以完美還原Android繪制效果,達(dá)到三端一致的效果。三平臺(tái)均可以100%使用Compose的控件與繪制能力。
iOS多模態(tài)渲染解放混排能力
iOS端大量存量業(yè)務(wù)模塊高度依賴Compose與原生UI的混合編排能力,其靈活混排的技術(shù)實(shí)現(xiàn)及與原生UI性能標(biāo)準(zhǔn)的精準(zhǔn)對(duì)齊,是業(yè)務(wù)Compose化改造成功推進(jìn)的核心前提。
Compose Multiplatform 官方在 iOS 端上使用 Skia + CAMetaLayer 實(shí)現(xiàn) UI 的渲染能力,這種方案的好處是與其他端表現(xiàn)完全一致,缺點(diǎn)就是與原生 UI 的混排能力較弱,且內(nèi)存占用較高,不適合多個(gè) Compose 實(shí)例并存。因此我們必須考慮以下兩種方案:
1. 指令映射,即使用 UIKit 實(shí)現(xiàn)Compose Canvas 。
2. 組件映射:即將Compose組件映射為Native組件。
組件映射方案在組件層進(jìn)行映射實(shí)現(xiàn),是業(yè)內(nèi)最常見的跨端 UI 框架設(shè)計(jì)方案,實(shí)現(xiàn)難度相對(duì)較低,但存在后期維護(hù)成本高,多端不一致等問題。指令映射在畫布層進(jìn)行映射實(shí)現(xiàn),實(shí)現(xiàn)的邏輯層級(jí)更低也更加抽象,雖然開發(fā)難度相對(duì)較高,但卻可以充分利用 UIKit 豐富的渲染能力對(duì)Compose的繪制效果實(shí)現(xiàn)較高的還原度。
因此我們最終采用了指令映射的自研實(shí)現(xiàn)方案解決了 Compose 在 iOS 上面臨的諸多難題。這套方案也成功地在騰訊視頻 iOS 端核心業(yè)務(wù)場(chǎng)景落地。事實(shí)上,業(yè)務(wù)團(tuán)隊(duì)甚至可以根據(jù)實(shí)際應(yīng)用場(chǎng)景在基于 UIKit 實(shí)現(xiàn)的自研指令映射方案或官方的Skia渲染方案之間進(jìn)行自由切換,并且可以在 Runtime 期共存。
關(guān)于 UI 的多端一致性,文本渲染較為復(fù)雜,我們采取 Skia 將文本渲染成圖片,利用 CALayer 進(jìn)行展示的方案,保持了高度的一致性。
Kotlin Native 內(nèi)存優(yōu)化
GC優(yōu)化
GC抑制
當(dāng)APP處于滑動(dòng)等對(duì)幀率要求較高的場(chǎng)景,我們會(huì)短暫抑制GC,來(lái)?yè)Q取更好的流暢度。
GC分段
不影響幀率情況下,進(jìn)行更高頻次的 GC,降低 PSS 水位。通過分析 CMS(Concurrent Mark-Sweep)垃圾回收算法,發(fā)現(xiàn)其存在兩次 Stop-The-World(STW)暫停,并且第一次 STW 時(shí)間較短,第二次 Sweep 期間的 STW 較長(zhǎng)。利用 GC 掛起的能力,我們?cè)?Vsync 時(shí)進(jìn)行 GC掛起,在 idle時(shí)進(jìn)行 GC恢復(fù)。具體效果如下圖:
Sweep 優(yōu)化
Kotlin Native GC 在Sweep 階段,會(huì)有大量的munmap系統(tǒng)調(diào)用,導(dǎo)致STW時(shí)間過長(zhǎng),從而影響主線程。為此,我們將munmap移出STW階段,在STW階段僅做Page收集。在Resume后再進(jìn)行集中 munmap。將第二次 STW時(shí)間降低到 1ms以內(nèi)。
KN堆Dump優(yōu)化
Kotlin Native(KN)支持生成堆內(nèi)存轉(zhuǎn)儲(chǔ)文件,用于內(nèi)存泄漏排查(類似 Android Profiler),但Dump過程需暫停所有KN線程,導(dǎo)致秒級(jí)界面凍結(jié)。針對(duì)不同平臺(tái)特性我們采用了不同優(yōu)化方案,從而達(dá)成線上可用的目標(biāo)。
鴻蒙系統(tǒng)
基于 Linux 內(nèi)核的 fork() 系統(tǒng)調(diào)用特性,采用「父進(jìn)程無(wú)感知-子進(jìn)程異步轉(zhuǎn)儲(chǔ)」方案實(shí)現(xiàn)零延遲內(nèi)存快照。
iOS系統(tǒng)
針對(duì)iOS系統(tǒng)無(wú)法支持fork的限制,我們重新設(shè)計(jì)了堆內(nèi)存分析流程,在保持性能的同時(shí)顯著降低主線程阻塞時(shí)間。
堆凍結(jié)階段:將堆內(nèi)存數(shù)據(jù)保存到緩存文件,這里的堆內(nèi)存是指 KN 堆用來(lái)分配對(duì)象內(nèi)存的幾種 Page 類,粒度很大,一種 Page 可能會(huì)有上千個(gè)對(duì)象,寫文件時(shí)無(wú)需解析 Page 內(nèi)容,所以耗時(shí)很少且不會(huì)因?yàn)閷?duì)象數(shù)量的增加而顯著增加耗時(shí)。
線程恢復(fù)后:異步地從緩存文件中讀取對(duì)象內(nèi)容并寫到 Dump 文件,由于每次從文件讀取的只是對(duì)象大小數(shù)據(jù),所以內(nèi)存消耗很低。
優(yōu)化后450MB 堆內(nèi)存轉(zhuǎn)儲(chǔ)耗時(shí)從 2.8 秒降低到 410 毫秒達(dá)到線上可用水平。該功能預(yù)計(jì) 6 月份上線。
方案對(duì)比
KuiklyBase組件生態(tài)
—Kotlin Native 堆棧還原組件
提供 Kotlin 異常堆棧還原,方便定義 Kotlin異常對(duì)應(yīng)的Kotlin 代碼行號(hào)、方法名等。
—Kotlin Native/ ArkTS 互調(diào)用組件
提供 ArkTS 與 Kotlin Native 跨語(yǔ)言訪問場(chǎng)景的解決方案,支持基礎(chǔ)類型、閉包、ArrayBuffer等類型互轉(zhuǎn),統(tǒng)一的生命周期管理,支持跨線程同步調(diào)用,支持跨Runtime的服務(wù)發(fā)現(xiàn),為開發(fā)者提供簡(jiǎn)便的跨語(yǔ)言互調(diào)用能力。
—資源管理組件
本項(xiàng)目基于Kotlin Multiplatform技術(shù),構(gòu)建了一套跨平臺(tái)原生資源管理解決方案,支持Android、iOS及HarmonyOS三大移動(dòng)端平臺(tái)。通過構(gòu)建時(shí)同步生成類型安全的資源訪問類(Resource Class),結(jié)合Kotlin/Native(klib)/ Kotlin/Jvm(aar)的標(biāo)準(zhǔn)化資源封裝機(jī)制,實(shí)現(xiàn)了多平臺(tái)資源統(tǒng)一管理與編譯器強(qiáng)校驗(yàn),為開發(fā)者提供與Android R類相仿的資源調(diào)用體驗(yàn)。
—原子操作組件
基于Kotlin 官方提供的多平臺(tái)原子操作庫(kù),旨在以高效且符合 Kotlin 慣用語(yǔ)法的方式實(shí)現(xiàn)線程安全的并發(fā)編程,提供輕量級(jí)的原子類型(如 AtomicInt、AtomicReference),支持原子讀寫、CAS(Compare-And-Swap)等操作,無(wú)需顯式鎖即可實(shí)現(xiàn)線程安全。
—協(xié)程組件
基于Kotlin 官方提供的協(xié)程庫(kù),旨在簡(jiǎn)化異步和并發(fā)編程,通過輕量級(jí)協(xié)程替代傳統(tǒng)線程和回調(diào)機(jī)制。支持協(xié)程構(gòu)建器、調(diào)度器、掛起函數(shù)、結(jié)構(gòu)化并發(fā)、流處理、通信與同步、異常處理、超時(shí)控制等能力。
—序列化組件
基于Kotlin 官方提供的多平臺(tái)序列化庫(kù)。專為 Kotlin 語(yǔ)言設(shè)計(jì),支持高效、類型安全的對(duì)象序列化與反序列化。多格式支持、編譯器插件集成、兼容Kotlin類型安全與空安全。支持嵌套對(duì)象、泛型類、密封類(sealed class)等復(fù)雜類型。
—日期時(shí)間處理庫(kù)
基于 Kotlin 官方提供的多平臺(tái)日期時(shí)間處理庫(kù),簡(jiǎn)化跨平臺(tái)的日期和時(shí)間操作。支持時(shí)區(qū)處理、時(shí)間運(yùn)算。
—IO庫(kù)
基于 Square 提供的高效 I/O 庫(kù),旨在簡(jiǎn)化輸入輸出操作。提供高效緩沖區(qū)管理、同一流抽象、智能數(shù)據(jù)移動(dòng)。
—不可變集合庫(kù)
基于 Kotlin 官方提供的不可變集合庫(kù),專注于為開發(fā)提供線程安全、高效且符合函數(shù)式編程范式的數(shù)據(jù)結(jié)構(gòu)。提供不可變的集合接口,確保集合創(chuàng)建后不可修改,避免意外數(shù)據(jù)變更。
—并發(fā)集合庫(kù)
基于StatelyConcurrency提供的并發(fā)集合庫(kù),簡(jiǎn)化跨平臺(tái)開發(fā)中的狀態(tài)管理和并發(fā)控制設(shè)計(jì)。支持線程安全集合、并發(fā)控制、同步機(jī)制。針對(duì) Kotlin/Native 的嚴(yán)格內(nèi)存模型優(yōu)化,減少線程切換開銷。簡(jiǎn)化狀態(tài)管理。
—Lottie動(dòng)畫庫(kù)
基于 Airbnb 開源的跨平臺(tái)動(dòng)畫渲染庫(kù),能夠?qū)?Adobe After Effects 設(shè)計(jì)的動(dòng)畫轉(zhuǎn)換為輕量級(jí) JSON 文件,并在多平臺(tái)上高效渲染。提供豐富的動(dòng)畫控制、動(dòng)態(tài)屬性修改、輕量高效。
—PAG 動(dòng)畫流解決方案
騰訊開源的一套跨平臺(tái)動(dòng)畫工作流解決方案,專注于將 Adobe After Effects (AE) 動(dòng)畫高效轉(zhuǎn)換為輕量級(jí)文件,并在多終端渲染。支持AE動(dòng)畫無(wú)縫導(dǎo)出、運(yùn)行時(shí)編輯、高性能渲染、配套工具鏈完善。
—數(shù)據(jù)庫(kù)
基于 SQLite 封裝的輕量級(jí)、嵌入式的關(guān)系型數(shù)據(jù)庫(kù),嵌入式設(shè)計(jì)、標(biāo)準(zhǔn)SQL支持、事務(wù)與ACID合規(guī)。輕量高效、弱類型系統(tǒng),并且支持高級(jí)功能擴(kuò)展(索引、觸發(fā)器、視圖等)
—工具庫(kù)
屏蔽Android/iOS/Harmony系統(tǒng)平臺(tái)差異,對(duì)外部統(tǒng)一提供常用的工具api集合作為業(yè)務(wù)開發(fā)的強(qiáng)力支撐。包括不限于 App信息管理(名稱、版本號(hào)、安裝時(shí)間、更新時(shí)間、包名等)、設(shè)備信息管理(設(shè)備類型、品牌、制造商、系統(tǒng)版本、電池狀態(tài)、亮度、內(nèi)存信息等)、屏幕信息管理(寬度、高度、分辨率、是否亮屏、鎖屏、屏幕旋轉(zhuǎn)、狀態(tài)欄、安全區(qū)域獲取、全屏模式等)、傳感器管理(重力、震動(dòng)、陀螺儀、加速度)、前后臺(tái)狀態(tài)管理、音頻及音頻焦點(diǎn)管理、加解密管理(3DES、RSA、AES)、字符編碼(UTF-8、UTF-16、BASE64)、存儲(chǔ)空間管理、網(wǎng)絡(luò)狀態(tài)監(jiān)聽、沙盒目錄獲取、監(jiān)聽分屏/浮窗等狀態(tài)、圖片保存相冊(cè)能力。
—網(wǎng)絡(luò)庫(kù)
提供基于HTTP協(xié)議的POST、GET請(qǐng)求能力以及關(guān)鍵信息采集。
實(shí)現(xiàn)原理
KN鴻蒙平臺(tái)適配
kotlin 1.9 使用的LLVM 11,kotlin 2.1升級(jí)到LLVM 16,但是鴻蒙平臺(tái)能夠支持的版本在LLVM 12 ~ 15,蘋果和鴻蒙都是基于公共版本的LLVM進(jìn)行修改,增加了自己的特性優(yōu)化,蘋果相對(duì)好的點(diǎn)在于公共版本的LLVM中包含有蘋果的target,所以鴻蒙版本的LLVM既可以支持iOS,又可以支持鴻蒙平臺(tái)。(KukilyBase-Kotlin當(dāng)前基于2.0.21進(jìn)行鴻蒙適配)
—常規(guī)方案:常規(guī)的Kotlin適配思路是分別使用鴻蒙和蘋果的LLVM進(jìn)行編譯,這種方案的好處是修改簡(jiǎn)單,且不存在兼容性問題。缺點(diǎn)是由于Kotlin本身不支持多l(xiāng)lvm架構(gòu),導(dǎo)致鴻蒙平臺(tái)的kotlin和iOS平臺(tái)要進(jìn)行分別編譯,需要依賴不同的Kotlin版本。
—KuiklyBase方案:在第一步Kotlin IR轉(zhuǎn)LLVM IR時(shí)采用蘋果的LLVM 11,在LLVM IR生成可執(zhí)行文件時(shí)使用鴻蒙的LLVM 12,這樣既可以滿足訴求,Kotlin本身也無(wú)需進(jìn)行架構(gòu)調(diào)整。
KN性能優(yōu)化
完成適配后,我們發(fā)現(xiàn)卡頓情況非常嚴(yán)重,從而進(jìn)一步對(duì)Kotlin-Native性能進(jìn)行評(píng)估,我們采用了官方Benchmark進(jìn)行對(duì)比,測(cè)試發(fā)現(xiàn)鴻蒙耗時(shí)是iOS相同性能機(jī)器的2.48倍。
我們需要針對(duì)鴻蒙平臺(tái)進(jìn)行一系列的優(yōu)化,經(jīng)過初步分析,我們也規(guī)劃了性能優(yōu)化的初步優(yōu)化思路。
內(nèi)聯(lián)優(yōu)化
我們分別對(duì)比了相同benchmark生成的Kotlin IR、LLVM IR文件。發(fā)現(xiàn)LLVM IR在內(nèi)斂上更加充分,特別是對(duì)于關(guān)鍵函數(shù),例如EnterFrame等,反觀鴻蒙平臺(tái)此類優(yōu)化更少。
嘗試添加always inline后,發(fā)現(xiàn)程序性能得到了較為顯著的影響。但相對(duì)iOS仍然有一定差距。通過分析LLVM的內(nèi)聯(lián) pass 發(fā)現(xiàn),在處理 EnterFame 等函數(shù)時(shí),會(huì)對(duì)比cpu feature的兼容性,Kotlin和框架內(nèi)部C++代碼在生成LLVM的函數(shù)時(shí),他們各自攜帶的cpu feature不一致,導(dǎo)致無(wú)法進(jìn)行內(nèi)聯(lián)。配置正確的屬性后,此問題得到修復(fù)。
ThreadLocal引發(fā)的性能低
通過對(duì) Benchmark 中耗時(shí)超 iOS 的 case 進(jìn)行深度分析,最終發(fā)現(xiàn)如下高頻堆棧。線程私有數(shù)據(jù)的性能測(cè)試結(jié)果表明 Ohos 耗時(shí)波動(dòng)較大。Ohos 耗時(shí)是 iOS 的 2-3 倍。(展示0ns是由于初期鴻蒙trace工具不完善導(dǎo)致,現(xiàn)已修復(fù))
由于Kotlin-Native在內(nèi)存分配時(shí)都依賴ThreadLocal來(lái)訪問線程獨(dú)立的Page,故訪問頻率極高,導(dǎo)致性能低下。分析發(fā)現(xiàn)鴻蒙平臺(tái)默認(rèn)采用了軟件模擬的thread_local。所以我們?cè)诰幾g時(shí)通過參數(shù)強(qiáng)制使用硬件thread_local,整體性能提升了30%。
協(xié)程性能優(yōu)化
將 Jetbrains 的 Compose 成功適配到 Ohos 后,長(zhǎng)列表的滑動(dòng)過程中頻繁出現(xiàn)卡頓現(xiàn)象。trace分析發(fā)現(xiàn)異常的處理花費(fèi)了大量的時(shí)間。
經(jīng)技術(shù)架構(gòu)分析,Compose Multiplatform 框架的協(xié)程調(diào)度機(jī)制深度依賴異常處理模型實(shí)現(xiàn)任務(wù)恢復(fù)與取消控制。其底層實(shí)現(xiàn)中,KN運(yùn)行時(shí)將異常處理橋接至C++異常體系,該設(shè)計(jì)在運(yùn)行時(shí)會(huì)產(chǎn)生顯著性能損耗:當(dāng)異常觸發(fā)時(shí),系統(tǒng)需沿調(diào)用棧進(jìn)行逐級(jí)回溯以定位匹配的異常捕獲點(diǎn),其時(shí)間復(fù)雜度與調(diào)用棧深度呈正相關(guān)。更值得注意的是,該過程伴隨大量C++異常對(duì)象的動(dòng)態(tài)構(gòu)建與析構(gòu)操作,頻繁的內(nèi)存分配與釋放行為進(jìn)一步加劇了執(zhí)行時(shí)延,導(dǎo)致關(guān)鍵路徑上的協(xié)程調(diào)度效率受限于異常處理機(jī)制的性能瓶頸。
同時(shí)鴻蒙系統(tǒng)libhilog.so捕獲了拋出的異常進(jìn)行處理,造成了大量延遲,與鴻蒙專家溝通后得到妥善優(yōu)化。最終長(zhǎng)列表在滑動(dòng)場(chǎng)景能夠穩(wěn)定在120Hz,處理方式如下:
—緩存或放棄部分關(guān)鍵位置的異常,降低異常處理的耗時(shí)與頻率。
—解決libhilog.so系統(tǒng)庫(kù)對(duì)于異常的非法捕獲。
調(diào)試性能優(yōu)化
使用 Jetbrains 的 Kotlin Native debuging 腳本后,調(diào)試斷點(diǎn)及打印變量耗時(shí)遠(yuǎn)超 Native 。通過trace分析發(fā)現(xiàn)其 KDS 與 LLDB 交互極為原始和簡(jiǎn)單。
經(jīng)技術(shù)架構(gòu)分析與處理,在 KDS 與 LLDB 上運(yùn)用流程合并、復(fù)用、緩存、預(yù)加載潛在下一跳、局部調(diào)試的可容錯(cuò)優(yōu)化等手段提高其通信和處理效率。整體性能視實(shí)際情況提升數(shù)倍至幾十倍(提升幅度隨調(diào)試棧的變量加密加深等因素影響),近似 Native。
鴻蒙繪制不同步問題解決
由于兩種組件屬于獨(dú)立的繪制層,在鴻蒙系統(tǒng)中存在不同步的問題。整體效果如圖,Compose的列表混排ArkUI的元素進(jìn)行滾動(dòng),兩個(gè)同步向上進(jìn)行運(yùn)動(dòng),由于不同步,UI銜接處會(huì)展現(xiàn)出空白區(qū)域,出現(xiàn)割裂的現(xiàn)象。
核心問題時(shí)鴻蒙采用的是集中渲染架構(gòu),XComponent的獨(dú)立繪制模式與ArkUI的繪制發(fā)生在不同的進(jìn)程,無(wú)法保證完全不同。所以我們采用XComponent的Texture模式,將內(nèi)容繪制到FBO中,由FBO參與原有的ArkUI的繪制節(jié)奏,來(lái)保證完全的同步。
iOS多模態(tài)渲染
在基于 UIKit 進(jìn)行渲染的基礎(chǔ)思路上,我們也發(fā)現(xiàn)了如 CALayer 重疊、未正確放置、無(wú)法復(fù)用等問題。對(duì)于Android來(lái)說,其是獨(dú)立繪制架構(gòu),每個(gè)進(jìn)程自己完成內(nèi)容的繪制,所以畫布是一整塊,內(nèi)容都繪制在其中,通過Skia的PictureRecorder命令錄制功能進(jìn)行命令的快速回放。但這種模式在iOS集中渲染架構(gòu)上就不太適用了,需要有一個(gè)工具來(lái)進(jìn)行差量處理繪制命令。所以我們?cè)O(shè)計(jì)了基于iOS的PictureRecorder局部更新架構(gòu)。
在PictureRecorder中,我們對(duì)繪制命令進(jìn)行差量,只更新變化的部分,從而提升繪制效率。PictureRecorder核心就是我們通過hash來(lái)判斷繪制指令是否發(fā)生變化,常規(guī)的這種方式能夠提升繪制效率,但當(dāng)頁(yè)面無(wú)比復(fù)雜時(shí),hash計(jì)算偶爾也會(huì)變成一種負(fù)擔(dān)。
PictureRecorder進(jìn)行了進(jìn)一步升級(jí)
我們優(yōu)化的核心思路是,通過增量hash來(lái)減少hash的計(jì)算量。每一個(gè) draw 函數(shù)執(zhí)行的時(shí)候,都會(huì)對(duì)當(dāng)前的 hash 和 指令id 進(jìn)行一次合并。并計(jì)算出最終的 hash。這個(gè) hash 記錄了一次完整地使用。增量 hash 的目的是減少 diff操作,這種方式可以有效地減少,兩次指令相同的比較。在壓力測(cè)試中還發(fā)現(xiàn) OC 對(duì)象的創(chuàng)建和釋放耗時(shí)也會(huì)被放大。這種情況在騰訊視頻復(fù)雜頁(yè)面回遷的過程中尤其明顯,因此,這里還將原先由 OC 對(duì)象代表的指令,改為了非常簡(jiǎn)單的 C 結(jié)構(gòu)體。之前的OC 閉包也去掉了。
優(yōu)化效果:以騰訊視頻的視頻播放頁(yè)面為例,首次渲染耗時(shí)降低13%,再次渲染耗時(shí)降低56%。
與KuiklyUI的差異
跨端框架自渲染與原生渲染在性能表現(xiàn)與多端適配層面各具優(yōu)勢(shì)。為滿足業(yè)務(wù)場(chǎng)景的差異化需求,騰訊大前端Oteam同時(shí)進(jìn)行兩個(gè)方案探索。
—原生渲染方案 KuiklyUI:側(cè)重于靜態(tài)化+動(dòng)態(tài)化雙運(yùn)行模式,采用輕量原生渲染保持原生UI體驗(yàn)并具備高度一致性,并基于原生組件映射的方式支持Compose API(本次已同步推出),支持H5和小程序(6月底推出)。
—自渲染方案 ovCompose:專注于全面對(duì)齊 Compose Multiplatform 標(biāo)準(zhǔn) API,采用自渲染方式實(shí)現(xiàn)鴻蒙平臺(tái)的適配,確保三端高度一致性。針對(duì) iOS 上較多的存量業(yè)務(wù),提出了多模態(tài)渲染方案解決低端iPhone內(nèi)存緊張、混排原生視圖、手勢(shì)等問題。
開源說明
此次開源共包含5個(gè)倉(cāng)庫(kù),包含了ovCompose和KuiklyBase。倉(cāng)庫(kù)Group地址為:https://github.com/Tencent-TDS
計(jì)劃
隨著這幾年的快速發(fā)展,KMM生態(tài)得到了長(zhǎng)足的發(fā)展,Kotlin-Native的執(zhí)行性能在很多方面已經(jīng)超越了Kotlin-JVM,但目前 Compose Multiplatform 跨平臺(tái)技術(shù)還沒有達(dá)到成熟的狀態(tài)(特別是GC),ovCompose & KuiklyBase將持續(xù)優(yōu)化,為開發(fā)者帶來(lái)體驗(yàn)更好、性能更強(qiáng)的跨端開發(fā)體驗(yàn)。以下是我們重點(diǎn)優(yōu)化的方向:
—GC在業(yè)務(wù)場(chǎng)景的表現(xiàn)
—Kotlin-Native組件化
—Kotlin-Native的開發(fā)體驗(yàn)優(yōu)化
—UIKit渲染模式進(jìn)一步對(duì)齊Skia 的渲染