天天看點

使用友盟+的APM服務實作基于Xamarin.Android的應用程式啟動性能優化背景測試總啟動時間診斷問題安卓ARTAOT啟動跟蹤實際分析解決方案結論:

背景

随着移動應⽤程式開發越來越流⾏, 越來越多的應⽤程式浮現于市場。 但是, 開發移動應⽤程式 并不是⼀個簡單的過程, 需要花費⼤量時間, 尤其是如果想要⼀個可跨 Apple、Android 和 Windows 運⾏的可擴充移動應⽤程式。

然⽽, 糟糕的性能可能會極⼤地損害⽤戶體驗。 ⽤戶在任何時候都不希望看到 10 秒以上的啟動 畫⾯。 如果等待時間過⻓,他們可能會感到⽣⽓、 放棄購物、 減少停留時間或完全解除安裝應⽤程式。

随着開發平台的普及, 我們需要正确的⼯具和⽅法來滿⾜不斷增⻓的需求。Xamarin就是這樣⼀種架構, 它⽀持在 Android、 iOS 和 Windows 平台上共享單個代碼庫。

是以,我們将在 Xamarin.Android應⽤程式中測試性能, 就像在 AndroidStudio 中使⽤ Java 開發⼀樣, 我們可以使⽤c#對性能進⾏測試, 從⽽優化啟動時間。

測試總啟動時間

⾸先測試程式在不同裝置的啟動時間,此處⽤到的⼯具是

友盟+推出的U-APM

。從圖中可以看 出應⽤程式在啟動時間上還存在着⼀定的優化空間。

使用友盟+的APM服務實作基于Xamarin.Android的應用程式啟動性能優化背景測試總啟動時間診斷問題安卓ARTAOT啟動跟蹤實際分析解決方案結論:

在 Android 上,ActivityManager系統程序會顯示⼀條“初始顯示時間”⽇志消息,可以更好地了 解整體啟動時間。在指令⾏使⽤adb logcat快速檢視Android裝置⽇志。或者使⽤Visual Studio 中的Android 調試⽇志。

在 Windows 上,運⾏以下powershell:

> adb logcat -d | Select-String Displayed

輸出:

ActivityTaskManager: Displayed com.lgq.wood.expiramentation/.MainActivity:

上述⽇志消息是在 x86 Android 模拟器上從 Visual Studio 調試應⽤程式時捕獲的。啟動/連接配接 調試器會産⽣⼀些額外的開銷,并且缺少Debug編譯時的優化。如果我們簡單地切換到Release配置并再次部署和運⾏應⽤程式:

因為我們最終⽬标是提⾼移動應⽤程式的性能,那麼第⼀步應該是實際測試卡頓函數的具體位置。 如果盲⽬地進⾏代碼更改,最終可能會和我們推測的結果産⽣很⼤的分歧,如果⼀些複雜的 性能改進甚⾄會損害代碼庫的可維護性。這個過程應該是:測試,做出修改,再次測試,并且重複以上步驟。

采⽤

U-APM

測得卡頓位置主要出現于:

com.lgq.wood.expiramentation.apache.http.impl.exec.readRawTextFile
使用友盟+的APM服務實作基于Xamarin.Android的應用程式啟動性能優化背景測試總啟動時間診斷問題安卓ARTAOT啟動跟蹤實際分析解決方案結論:

診斷問題

好, ⽬前應⽤程式由于readRawTextFile很慢。 現在我該怎麼辦?

⾸先我們需要對以下⼏個元件有⼀個系統性的了解

安卓ART

Android 運⾏時 (ART) 是 Android 上的應⽤程式和系統服務使⽤的托管運⾏時。ART 作為運⾏ 時執⾏ Dalvik 可執⾏⽂件 (.dex ⽂件 - D alvik EX可執⾏⽂件) , 這是⼀種⽤于存儲 Dalvik    位元組碼的緊湊格式。 

ART 通過在安裝應⽤程式時将整個應⽤程式編譯為本機代碼, 引⼊了提前 (AOT) 編譯。 這帶來 了更快的應⽤程式執⾏和改進的記憶體配置設定。 以及垃圾收集機制、 更準确的分析等等。

為了實作這⼀點, ART使⽤dex2oat來建立⼀個ELF (可執⾏和連結格式) 的可執⾏⽂件。 缺點 是需要額外的時間來編譯。 此外, 應⽤程式會占⽤⼤量磁盤記憶體來存儲已編譯的代碼。

AOT

Mono 運⾏時提供AOT 功能。 Mono 将預編譯程式集以最⼩化 JIT時間并減少記憶體使⽤ 。            Mono 可以在⽀持它的平台 (如 Android)   上⽣成 ELF.so ⽂件。 然後它在原始程式集旁邊存儲 ⼀個預編譯的圖像。

Mono.Android.dll → libaot-Mono.Android.dll.so

然後, 這些⽂件可以被 Mono 運⾏時使⽤, 并省略 JIT 開銷

啟動跟蹤

Mono 引⼊了⼀項功能, 允許在應⽤程式上使⽤内置的 AOT 分析器來⽣成 AOT配置⽂件。 分 析器進⾏記憶體分析、執⾏時間分析, 甚⾄是基于統計的抽樣分析。 這會⽣成⼀個 AOT 配置⽂    件, 當使⽤帶有配置⽂件的 Mono 的 AOT 功能時, 該配置⽂件可⽤于優化應⽤程式。啟動跟蹤可⽤于Visual Studio 2019 版本 16.2或Visual Studio for Mac 2019 版本 8.2。

可以通過編輯 Android 項⽬的 .csproj ⽂件并在Release <PropertyGroup> 中添加以下屬性來 開始使⽤啟動跟蹤:

<PropertyGroup Condition = " '$(Configuration)|$(Platform)' == 'Release|Any

也可以在項⽬設定的Android 選項中進⾏設定,  Mono的 AOT編譯器啟⽤使⽤會預設配置⽂件 的啟動跟蹤, 并在部署時加快 Android 應⽤程式的啟動時間。

實際分析

我們需要實際分析我們的代碼并需要改進。 切換回Debug配置, 并通過運⾏以下指令啟⽤Mono 分析器:

$ adb shell setprop debug.mono.profile log:calls

adb shell在 Android 裝置或模拟器上運⾏單個 shell 指令。 setprop設定Android系統屬性, 類 似于其他平台上的環境變量。

然後隻需強制退出并重新啟動應⽤程式。 下次啟動時, Mono 會在 Android應⽤程式的本地⽬ 錄中儲存⼀個⽂件。 profile.mlpd注意這⾥存在⼀個問題, 該⽂件隻能由應⽤程式本身通路, 是以我們必須使⽤指令來定位⽂件: run-as

$ adb shell run-as com.lgq.wood.expiramentation ls -l files/.__override__

-rw-rw-r-- 1 u0_a411 u0_a411 515303 2020-07-27 09:29 profile.mlpd

為了從裝置上擷取⽂件, 我使⽤了⼀個已知的可寫⽬錄, 例如:  /sdcard/Download/

$ adb shell run-as com.lgq.wood.expiramentation cp files/.__override__/prof

複制⽂件後, 您可以使⽤adbpull将⽂件擷取到您的台式計算機:profile.mlpd

$ adb pull /sdcard/Download/profile.mlpd

/sdcard/Download/profile.mlpd: 1 file pulled, 0 skipped. 162.7 MB/s (515303

profile.mlpd是⼀個⼆進制⽂件,

Windows ⽤戶需要在⽤于 Linux 的 Windows ⼦系統中安裝 Mono才能運⾏。

有了上⾯的⼀系列代碼, 就會出現⼀些有趣的數字。

解決方案

我們通過前⽂的調⽤, 可以發現以下⼏個函數可能需要相當⻓的時間:

使用友盟+的APM服務實作基于Xamarin.Android的應用程式啟動性能優化背景測試總啟動時間診斷問題安卓ARTAOT啟動跟蹤實際分析解決方案結論:

還可以看到記憶體配置設定, 例如:

使用友盟+的APM服務實作基于Xamarin.Android的應用程式啟動性能優化背景測試總啟動時間診斷問題安卓ARTAOT啟動跟蹤實際分析解決方案結論:

請注意, 如果您需要檢視這些配置設定來⾃哪些⽅法, 您可以傳遞到。 --tracesmprof-report

我們做出了多種嘗試, 也都收到了⼀定成效。 但是我們最意想不到的是, 下⾯這個簡單的改動。 我們嘗試将string直接從stream中讀取, ⽽不是使⽤響應的内容建立, 然後使⽤新的System.Text.Json庫來進⾏更⾼效的 JSON解析:

// At the top

using System.Text.Json;

//...

async Task<Response> GetSlides()

{

var response = await httpClient.GetAsync("https://httpbin.org/json");

response.EnsureSuccessStatusCode();

using (var stream = await response.Content.ReadAsStreamAsync())

return await JsonSerializer.DeserializeAsync<Response>(stream);

}

檢視⽅法調⽤的差異, 我們可以看到⼀個明顯的時間優化:

使用友盟+的APM服務實作基于Xamarin.Android的應用程式啟動性能優化背景測試總啟動時間診斷問題安卓ARTAOT啟動跟蹤實際分析解決方案結論:

我們還可以看到以下記憶體配置設定的差異:

使用友盟+的APM服務實作基于Xamarin.Android的應用程式啟動性能優化背景測試總啟動時間診斷問題安卓ARTAOT啟動跟蹤實際分析解決方案結論:

這⼀點, 和我們在

中測試得到的瓶頸函數相吻合, 瓶頸确實是處在readRawTextFile函數中, 我們嘗試了以下⼏種⽅法, 也⼀定程度上緩解了啟動問題, 但收益并沒有

中的    readRawTextFile那麼⼤。在此列出, 僅供參考:

1.  我們可以緩存 Web 請求的結果

2.  我們可以從磁盤上的⽂件加載之前的調⽤結果, ⽐如設定24 ⼩時内有效。

3.  由于調⽤不是互相依賴,我們可以同時進⾏異步調⽤

4.  在伺服器端, 我們可以進⾏⼀個新的 API 調⽤, 在⼀個請求中傳回所有調⽤的資料

結論:

優化性能很難, ⽅向也很多。 關于代碼慢的定位部分, 改動後可能會發現這⼀部分根本不會産⽣ 效果, 對代碼産⽣影響的最佳⽅法是測試、 測試, 然後再次測試。 改變後再次測試。 ⽽通過測試 去提升性能, 往往能針對問題做預先準備。 也往往能更核⼼地提升核⼼性能瓶頸, 從⽽帶來⽅⽅⾯⾯的全⽅位提升。

作者:丁立戈