《高性能鴻蒙應用開發實踐解析-王雷.pdf》由會員分享,可在線閱讀,更多相關《高性能鴻蒙應用開發實踐解析-王雷.pdf(28頁珍藏版)》請在三個皮匠報告上搜索。
1、高性能鴻蒙應用開發分享人:鴻蒙ArkUI框架技術專家 王雷鴻蒙應用構成鴻蒙應用構成構成構成Stage模型模型應用組件1.組件分類stage-model-component -UIAbility組件:包含UI,提供展示UI的能力,主要用于和用戶交互。詳細介紹請參見UIAbility組件概述。-ExtensionAbility組件:提供特定場景(如卡片、輸入法)的擴展能力,滿足更多的使用場景。詳細介紹請參見ExtensionAbility組件概述。2.開發方式 采用面向對象的方式,將應用組件以類接口的形式開放給開發者,可以進行派生,利于擴展能力。進程模型1.主進程2.ExtensionAbilit
2、y進程3.渲染進程線程模型1.ArkTS引擎實例的創建 一個進程可以運行多個應用組件實例,所有應用組件實例共享一個ArkTS引擎實例。2.線程模型 ArkTS引擎實例在主線程上創建。3.進程內對象共享:支持。任務管理模型 每個UIAbility組件實例創建一個任務。-任務會持久化存儲,直到超過最大任務個數(根據產品配置自定義)或者用戶主動刪除任務。-UIAbility組件之間不會形成棧的結構。配置文件使用app.json5描述應用信息,module.json5描述HAP信息、應用組件信息。Stage ModeUIAbilityServiceExtensionAbilityExtensionAb
3、ility.InputMethodExtensionAbilityDataShareExtensionAbilityDriverExtensionAbility性能影響性能影響緯度緯度 語言緯度:ArkTS 線程模型:Worker&TaskPool UI構成:ArkUI框架 圖形渲染:ArkGraphics渲染引擎 分析工具ArkTSArkTS語言語言特性特性高性能容器類庫高性能容器類庫線性線性容器容器非線性非線性容器容器ArrayListHashMapVectorHashSetListTreeMapLinkedListTreeSetDequeLightWeightMapQueueLightW
4、eightSetStackPlainArrayimport ArrayList from ohos.util.XXX;ArkTS語言使用過程中性能提升語言使用過程中性能提升方法方法 熱點循環中常量提取,減少屬性訪問次數 避免頻繁使用delete 數值計算避免溢出 避免使用稀疏數組 使用字面量進行對象創建 避免動態添加屬性 避免使用type類型標注 聲明參數要和實際的參數一致 避免動態聲明function與class了解啟動流程各階段執行內容,合理配置應用了解啟動流程各階段執行內容,合理配置應用結構,提升啟動結構,提升啟動速度速度合理配置啟動頁面圖標尺寸,減少解碼開銷合理配置啟動頁面圖標尺寸,減
5、少解碼開銷 abilities:name:EntryAbility,srcEntrance:./ets/entryability/EntryAbility.ts,description:$string:EntryAbility_desc,icon:$media:icon,label:$string:EntryAbility_label,startWindowIcon:$media:startWindowIcon,/在這里修改啟動頁圖標,建議不要超過256像素x256像素 startWindowBackground:$color:start_window_background,visible:t
6、rue,skills:entities:entity.system.home ,actions:action.system.home 按需引入模塊,合理使用生命周期,避免按需引入模塊,合理使用生命周期,避免耗時耗時操作操作首頁組件按需創建,頁面生命周期避免耗首頁組件按需創建,頁面生命周期避免耗時時操作操作使用異步機制,降低使用異步機制,降低UIUI線程同步線程同步操作負載操作負載組件中的異步組件中的異步邏輯邏輯T Ta as sk kP Po oo ol l機機制制wwo or rk ke er r機機制制Image解碼器UI ThreadBackground Thread共享內存 Pixel
7、Map應用異步應用異步機制機制UIUI框架運行流程與性能影響框架運行流程與性能影響點點應用組件樹應用組件樹階段階段1:1:數據數據處理處理階段階段2:UI2:UI更新更新狀態數據更新(應用)UI數據更新(框架)BuildMeasureLayoutRender臟節點臟節點列表列表性能影響點:性能影響點:狀態數據更新數量 更新臟組件數量開發開發約束:約束:布局約束 狀態更新約束 懶加載更新約束性能影響點:性能影響點:組件創建數量 屬性更新數量 布局更新范圍 繪制指令數量開發開發約束:約束:布局合理使用 組件復用,避免重復創建UIUI框架運行流程:數據處理框架運行流程:數據處理流程流程開發者視角開發
8、者視角EntryComponentstruct Index State message:string=Hello World build()Row()Column()Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).width(100%).onClick()=this.message=Hello ArkUI ).height(100%)依賴收集過程依賴收集過程build執行get:this.messge get()this.notifyPropertyHasBeenReadPU();return this.wrappedVa
9、lue_;記錄Text emId,建立組件&數據關聯關系存入狀態數據內部Set完成數據依賴收集recordDependentUpdate()const elmtId=ViewStackProcessor.GetElmtIdToAccountFor();if(elmtId ViewStackProcessor.StartGetAccessRecordingFor(elmtId);Text.create(this.message);Text.fontSize(50);Text.fontWeight(FontWeight.Bold);if(!isInitialRender)Text.pop();Vi
10、ewStackProcessor.StopGetAccessRecording(););刷新UI屬性渲染樹置臟繪制臟 or 布局臟FrameFrameNodeTreeNodeTree布局邊界布局臟繪制臟RowTextTextUIUI框架運行流程:框架運行流程:UIUI更新流程更新流程FrameFrameNodeTreeNodeTree布局邊界布局臟繪制臟布局布局過程過程查詢臟節點數組獲取臟節點對象measure遞歸遍歷children,進行measure布局參數未變化跳過Layoutmeasure 完成后,進入layout流程自底向上進行排布像素對齊繪制臟不一定觸發布局更新,布局臟一定觸發布局
11、更新和繪制更新繪制繪制過程過程遍歷臟組件生成繪制指令指令下發狀態管理合理使用,精準控制組件更新狀態管理合理使用,精準控制組件更新范圍范圍常見冗余刷新常見:大數據對象關聯組件過多,造成刷新范圍常見冗余刷新常見:大數據對象關聯組件過多,造成刷新范圍大大Observedclass UIStyle translateX:number=0;translateY:number=0;scaleX:number=0.3;scaleY:number=0.3;width:number=336;height:number=178;posX:number=10;posY:number=50;alpha:number=
12、0.5;borderRadius:number=24;imageWidth:number=78;imageHeight:number=78;translateImageX:number=0;translateImageY:number=0;fontSize:number=20;同一數據對象中,不同屬性被多個組件所使用,同一數據對象中,不同屬性被多個組件所使用,當數據對象任一屬性值發生變化時,所有綁定當數據對象任一屬性值發生變化時,所有綁定該對象的組件都被標記為臟,發生該對象的組件都被標記為臟,發生刷新刷新Component1UIStyle.translateXUIStyle.translate
13、YComponent2UIStyle.scaleXUIStyle.scaleYComponent3UIStyle.fontSize狀態管理合理使用,精準控制組件更新狀態管理合理使用,精準控制組件更新范圍范圍通過通過Observed裝飾器,進行數據合理拆分,實現更新范圍最小裝飾器,進行數據合理拆分,實現更新范圍最小化化Component1UIStyle.needRenderTranslateComponent2UIStyle.needRenderscaleComponent3UIStyle.needRenderFontSizeObservedclass NeedRenderTranslate p
14、ublic translateImageX:number=0;public translateImageY:number=0;Observedclass NeedRenderScale public scaleX:number=0.3;public scaleY:number=0.3;Observedclass NeedRenderFontSize public fontSize:number=20;Observedclass NeedRenderOthers /properties usually used together can be divided into the same new
15、divided class /。Observedclass UIStyle needRenderTranslate:NeedRenderTranslate=new NeedRenderTranslate();needRenderFontSize:NeedRenderFontSize=new NeedRenderFontSize();needRenderScale:NeedRenderScale=new NeedRenderScale();/。使用懶加載技術,控制列表更新范圍,避免超長列表更新使用懶加載技術,控制列表更新范圍,避免超長列表更新阻塞阻塞List 列表組件ForEach數據管理器數據
16、源一次性讀取全部數據,耗時長適用于列表項數量不多或只有1屏數據場景,當列表項數量大時,會造成加載耗時阻塞使用懶加載能力,按需讀取數據List 列表組件LazyForEach數據管理器數據源滾動過程中進行數據讀取和加載Item1Item2Item3Item4Item5Item6Item7Item8Item1Item2Item3Item4Item5Item6Item7Item8組件復用機制,減少組件創建組件復用機制,減少組件創建List 列表組件Item1Item2Item3Item4Item5Item6Item7Item8組件復用池摘除進入組件復用池不進行銷毀Item0從組件復用池中獲取組件不進
17、行創建LazyForEach(this.GoodDataOne,(item,index)=GridItem()GoodItems(img:item.data.img,webimg:item.data.webimg,hei:item.data.hei,).reuseId(this.CombineStr(item.type),(item)=JSON.stringify(item)ReusableComponentstruct GoodItems State img:Resource=$r(app.media.photo61)State webimg?:string=State hei:number
18、=0 LocalStorageLink(storageSimpleProp)simpleVarName:string=boo:boolean=true index:number=0 controllerVideo:VideoController=new VideoController();aboutToReuse(params)this.webimg=params.webimg this.img=params.img this.hei=params.hei build()/.懶加載機制與組件復用機制在組件中的使用懶加載機制與組件復用機制在組件中的使用瀑布流瀑布流布局布局 build()Colu
19、mn(space:2)WaterFlow()LazyForEach(this.datasource,(item:number)=FlowItem()Column()Text(N+item).fontSize(12).height(16)Image(res/waterFlowTest(+item%5+).jpg).objectFit(ImageFit.Fill).width(100%).layoutWeight(1).width(100%)/提前設定FlowItem高度,避免自適應圖片高度 .height(this.itemHeightArrayitem).backgroundColor(thi
20、s.colorsitem%5),(item:string)=item).columnsTemplate(1fr1fr).columnsGap(10).rowsGap(5).backgroundColor(0 xFAEEE0).width(100%).height(80%)效果展示效果展示懶加載能力與懶加載能力與WaterFlowWaterFlow組合組合使用使用 build()Column(space:2)WaterFlow()LazyForEach(this.datasource,(item:number)=FlowItem()Column()Text(N+item).fontSize(12
21、).height(16)Image(res/waterFlowTest(+item%5+).jpg).objectFit(ImageFit.Fill).width(100%).layoutWeight(1).onAppear()=/即將觸底時提前增加數據 if(item+20=this.datasource.totalCount()for(let i=0;i item)懶加載能力實現無限懶加載能力實現無限滾動滾動懶加載機制與組件復用機制在組件中的使用懶加載機制與組件復用機制在組件中的使用瀑布流瀑布流布局布局懶加載能力結合組件復用機制,達到最佳滾動性能懶加載能力結合組件復用機制,達到最佳滾動性能
22、體驗體驗 build()Column(space:2)WaterFlow()LazyForEach(this.datasource,(item:number)=FlowItem()/使用可復用自定義組件 ResuableFlowItem(item:item).onAppear()=/即將觸底時提前增加數據 if(item+20=this.datasource.totalCount()for(let i=0;i item).columnsTemplate(1fr1fr).columnsGap(10).rowsGap(5).backgroundColor(0 xFAEEE0).width(100%
23、).height(80%)ReusableComponentstruct ResuableFlowItem State item:number=0 /從復用緩存中加入到組件樹之前調用,可在此處更新組件的狀態變量以展示正確的內容 aboutToReuse(params)this.item=params.item;build()Column()Text(N+this.item).fontSize(12).height(16)Image(res/waterFlowTest(+this.item%5+).jpg).objectFit(ImageFit.Fill).width(100%).layoutW
24、eight(1)懶加載機制與組件預懶加載機制與組件預加載機制在組件中的使用加載機制在組件中的使用頁面頁面滑動滑動翻頁效果展示翻頁效果展示當頁面較多數量大時,一次性創建全部頁面顯然并不劃算優化機制:利用滑動過程動畫時間,并行進行頁面創建 控制加載的頁面數量通過通過cacheCountcacheCount設置預加載設置預加載頁面數量頁面數量滑動動畫滑動動畫&頁面創建頁面創建并行并行UI線程RS線程跟手滑動切換動畫執行加載下一頁面優化頁面布局,高效組織優化頁面布局,高效組織UIUI結構結構合理使用布局,降低合理使用布局,降低UIUI層級層級 歸并相同類型布局,避免冗余組件使用選用扁平選用扁平化布局,
25、降低化布局,降低UIUI層級層級 使用使用屬性動畫屬性動畫能力,避免幀動畫占用能力,避免幀動畫占用UIUI線程線程傳統動畫傳統動畫處理過程處理過程vsync信號動畫插值計算組件屬性更新布局計算繪制指令生成刷新當前幀鴻蒙動畫鴻蒙動畫處理過程處理過程vsync信號更新狀態數據計算最終位置配置動畫參數發送指令執行動畫vsync信號動畫插值繪制UI線程UI線程動畫線程動畫使用動畫使用示例示例 State textScaleX:number=1;State textScaleY:number=1;Text().backgroundColor(Color.Blue).fontColor(Color.Whi
26、te).fontSize(20).width(10).height(10).scale(x:this.textScaleX,y:this.textScaleY).margin(top:100)Button(圖形變換屬性).onClick()=animateTo(duration:1000,()=this.textScaleX=10;this.textScaleY=10;)通過節點組緩存(通過節點組緩存(renderGrouprenderGroup),提升渲染),提升渲染性能性能1組件渲染順序組件渲染順序234512345按按Z Z序自底向上逐層繪制序自底向上逐層繪制節點組緩存,一次性節點組緩存
27、,一次性繪制繪制1234512345首次首次繪制:按繪制:按Z Z序自底向上逐層繪制序自底向上逐層繪制緩存繪制紋理發生重繪讀取紋理,直接繪制通過節點組緩存(通過節點組緩存(renderGrouprenderGroup),提升渲染),提升渲染性能性能組組件件渲渲染染流流程程合理使用節點組緩存,平衡性能合理使用節點組緩存,平衡性能&內存內存緩存更新緩存更新條件:條件:組件在當前組件樹上 組件renderGroup被標記為true 組件內容被標臟緩存清理緩存清理條件:條件:組件不存在于組件樹上 組件renderGroup被標記為false適用場景適用場景 組件內容固定不變組件內容固定不變&內部無內部
28、無動效動效組件內容固定不變或更新頻率低,會加大緩存的使用率,減少緩存組件內容固定不變或更新頻率低,會加大緩存的使用率,減少緩存更新增加的開銷更新增加的開銷 執行動畫的過程執行動畫的過程執行動畫過程中內容通常沒有變化,此時在動畫執行前將動畫目標執行動畫過程中內容通常沒有變化,此時在動畫執行前將動畫目標組件標記為節點組,可提升動畫幀率,動畫結束后,恢復原始狀態組件標記為節點組,可提升動畫幀率,動畫結束后,恢復原始狀態探索中的性能提升探索中的性能提升思路思路組件預創建能力利用UI線程空閑時間,提前準備數據動畫配置動畫執行動畫結束回調組件創建屬性更新布局計算繪制提交渲染密集計算空閑時間動畫配置動畫執行
29、動畫結束回調屬性設置布局計算組件掛樹繪制提交渲染局部更新效率更高組件預創建屬性更新布局更新應用性能分析工具應用性能分析工具CPU ProfilerCPU Profiler:查看:查看ArkTSArkTS耗時耗時分析分析HiDumperHiDumper命令行工具:查看命令行工具:查看UIUI結構結構 開啟ArkUI的debug模式:hdc shell param set persist.ace.debug.enabled 1 重新啟動應用 獲取當前頁面對應應用的window ID:hdc shell hidumper-s WindowManagerService-a-a 通過WinId獲取對應頁
30、面的控件樹文件:hdc shell hidumper-s WindowManagerService-a-w 28-element-c 查看 arkui.dump 文件探索中的性能提升探索中的性能提升思路思路多線程離屏繪制:并行繪制,UI線程顯示紋理渲染線程UI線程后臺線程1后臺線程2繪制任務1繪制任務2Create OffscreenCanvasDraw PixelMapPost MessageCreate OffscreenCanvasDraw PixelMapPost Message收集繪制結果共享內存PixelMap1PixelMap2繪制紋理UI更新HiDumperHiDumper命令
31、行工具:查看命令行工具:查看UIUI結構結構/arkui.dump文件內容片斷|-GridItem childSize:1|ID:22|Depth:9|IsDisappearing:0|FrameRect:RectT(360.00,0.00)-180.00 x 29.00|BackgroundColor:#00000000 .|-Stack childSize:1|ID:23|Depth:10|IsDisappearing:0|FrameRect:RectT(0.00,0.00)-180.00 x 29.00|BackgroundColor:#FFFFFF00 .|-Stack childSi
32、ze:1|ID:24|Depth:11|IsDisappearing:0|FrameRect:RectT(0.00,0.00)-180.00 x 29.00|BackgroundColor:#FF0000FF .|-Stack childSize:1|ID:25|Depth:12|IsDisappearing:0|FrameRect:RectT(0.00,0.00)-180.00 x 29.00|BackgroundColor:#00000000 .|-Text childSize:0 ID:26 Depth:13 IsDisappearing:0 FrameRect:RectT(83.00,
33、0.00)-14.00 x 29.00 BackgroundColor:#00000000 .字段說明childSize:組件內子組件數量ID:當前組件的ID值,此ID非應用設置,而是自增累加Depth:當前組件在UI Tree中深度IsDisappearing:顯示狀態FrameRect:組件尺寸Background:組件背景色其他:各組件渲染屬性都可查看 SmartPerf-HostSmartPerf-Host工具分析應用性能工具分析應用性能配置SmartPerf參數分析UI數據幀率數據線程Trace耗時分析ArkUI-X ArkUI-X 跨平臺項目期待您的加入跨平臺項目期待您的加入共建共建https:/