業務運維實戰:騰訊是怎么優化APP用戶體驗的?
作者簡介:
黃偉俊(henry),騰訊高級運維工程師,多年研發與運維工作經驗。專注(移動端+服務端)性能管理,大數據分析領域的探索與實踐。
引言
當前,用戶體驗已成為一種新的產品價值。當技術實現不再是產品核心競爭力時,產品的競爭就是用戶體驗的競爭。而用戶彈指間感知到的性能體驗對于用戶體驗尤為重要。
移動互聯網產品因為用戶的手機型號繁多、手機操作系統版本不一致、app版本難統一等問題,很難在開發或測試環節就完全解決掉移動app的性能問題,這使得移動app產品在運維過程中,不得不面對用戶體驗不優、性能不佳的問題。
如何讓開發可以高效定位性能問題?
讓開發,測試,運維清晰的把控各個產品的性能狀況?
我們結合了當前業界商用的APM技術,實現了一套騰訊社交運維的myAPM方案。
myAPM是什么?
APM(Application Performance Management)應用性能管理,它是一套集終端,網絡,服務端性能管理于一體的監控方案。在這里,就不展開介紹了。
myAPM,專注于移動端的性能管理。既能監控定位性能問題(卡慢),也能應用于日常的app性能運營分析,提升產品用戶體驗。
監控方式
myAPM采用BCI注入方式,實現業務方法粒度監聽。
在注入技術選型時,myAPM采用了類ASM的注入技術,其注入效率,校錯能力,學習成本,都比ASM要好一些。
注入階段
myAPM實現性能監控與功能開發零耦合。在編譯階段注入監控能力,對開發零感知。
myAPM特點:
實現方法粒度的自動化注入監控;
myAPM采用插件化設計:各個特性功能可自由組合,以滿足開發者定制化需求。
myAPM可以做什么?
當前,我們利用myAPM的能力,主要從以下四個方面進行探索與實踐:
一、Apk 包大小分析
二、App卡慢監控分析
三、App啟動性能分析
四、App 核心鏈路性能分析
一、Apk 包大小分析
一個app,隨著新功能的持續增加,其apk的大小也在不斷地膨脹。Apk size的問題,越來越困擾和限制著開發同學,影響某些功能的上線,同時,也降低了用戶體驗。
同時,app運營時間越長,功能迭代 / 代碼重構次數越多,“垃圾”代碼(就是沒有被實際調用過的代碼)的數量就會越多。
由于代碼量大,代碼調用層次深,每個開發同學只負責部分功能開發。如果讓開發同學人工去做全局“垃圾代碼”的分析,顯然,其難度很大,效率不高。
而myAPM的apk包大小分析,就是用來幫助開發同學,快速暴露這些“垃圾代碼”,開發同學只須集中精力,針對梳理出來的問題代碼,做進一步確認和清理即可。
1、Apk包大小分析原理
myAPM會在類或方法中,注入一個唯一ID;
內測環境部署,通過大量的自動化用例,過濾掉有調用關系代碼;
對未調用代碼,進行重新注入,灰度外網,收集線上真實用戶的行為。通過內網測試,可以過濾掉部分常用代碼,從而減少因注入增加的app包量。
通過長時間、大用戶量的數據運營,我們即可定位出無實際調用的代碼。開發小伙伴即可集中精力在這些問題方法的確認及清理。
2、Apk包大小分析應用場景
定位完全無調用或被引用的類;(粒度粗,清理方便)
定位孤島方法:即沒有主調和被調的方法(粒度細,清理全面)
定位無調用的方法鏈路;
3、Apk包大小分析特點
結合線下模擬測試行為大數據分析
結合線上用戶實際行為大數據分析
性能消耗小
自動注入
4、開源工具 & apk包分析
可能有同學,會羅列出一系列開源的工具,也可以很方便地甄別出app這種無調用代碼。但對于有調用關系的一條鏈路(一組方法),僅僅通過線下分析,無法判斷其是否有被調用。我們只能利用線上大量用戶的真實行為分析,更好地去判斷和確認。
5、方法注入樣例
通過一個唯一ID(14236)來上報,既避免了代碼中敏感信息的泄漏風險,同時,也大大節省上報量。
6、Qzone –android應用實例
Qzone android app,針對業務代碼以及第三方包代碼,采用類無調用分析。(類中所有變量或方法,沒有被引用或調用。)
內部測試階段:
在內部測試中,由于機型,測試用例有限,分析結果是42%的類沒有調用或引用。

灰度外網階段:
在灰度外網用戶后發現,所有類都被調用或引用。但40%類被調用次數少于10次。由于灰度用戶是50W,即40%的代碼只有萬分之二的用戶有調用。針對這些,后續我們可以分析,調整這些類的啟動加載順序(如:延時加載)。

結論:
當前QQ空間 APP,不存在多余無調用類文件。
后續,在監控粒度上,我們會從“類方法”進行深層面的挖掘分析。
二、App卡慢分析
在app用戶體驗上,除了crash故障外,相信app主線程卡慢(負責與用戶交互的線程),是用戶最不能忍受的。
我們這里所說的卡慢分析,是指對app主線程代碼的卡慢監控分析。
1、工作原理
myAPM卡慢監控,實現對目標代碼的“方法粒度”的注入、卡慢監聽。
其本質,是在目標方法調用的前后,注入時間,進行卡慢監聽及分析。原理圖,如下:
2、卡慢分析全流程
app編譯時,注入 : 跟上面“apk包大小分析”的注入階段一樣:在class編譯后,實現監控邏輯注入。
注入時,我們會根據當前注入方法的“主調方法-被調方法”方法對,生成ID。同樣,也是用于信息加密及節省上報量。
app卡慢監控 : app版本上線后,myAPM會監控目標方法線上運行耗時,出現卡慢,則觸發卡慢方法上層全鏈路上報,同時上報app當前基本軟硬件CPU等使用率等環境信息。
myAPM后臺,會根據app上報的一組ID,進行鏈路還原。開發同學,可以針對卡慢方法,以及上層鏈路進行性能分析;
說明:
myAPM上報的卡慢鏈路,還原了業務方法運行調用的過程。是一種輕量級的堆棧/快照。其好處是避免打印堆棧的性能消耗。因為,在卡慢監控中,最消耗性能的就是打印堆棧。
收集堆棧,輔助分析 : 若某些卡慢方法,通過卡慢鏈路沒法分析定位出問題,可以將指定方法推送到指定用戶app上,收集線上用戶指定卡慢方法再次出現時,對應的堆棧信息,用于輔助開發同學的分析定位。
3、卡慢實例
在主線程卡慢監控中,比較常見的案例是:主線程加載文件,底層DB讀寫,圖片處理這些比較耗時的操作。我們優化的方案,通常是將這些耗時操作移到異步線程中進行處理。
以下是四個案例片斷:
實例一:
主線程進行DB查詢導致卡慢。
平均耗時視圖:
myAPM后臺,會先統計卡慢鏈路的次數,計算鏈路中每個節點的平均耗時。
卡慢鏈路最后的兩組數值含義:(代碼調用行號), [方法平均耗時]。耗時單位為ms。

明細視圖:
在明細視圖中,我們會列出所有卡慢實例,以及用戶基礎環境信息。
卡慢鏈路最后的兩組數值含義:(代碼調用行號), [方法耗時]。耗時單位為ms。

實例二:
主線程中加載dex文件引起的卡慢實例。

實例三:
在主線程中,加載本地xml文件導致卡慢。

實例四:
在主線程中,圖片處理耗時比較大。
Process()方法消耗了1.3秒,setFacadeImage(),也另外消耗了1秒。
4、myAPM卡慢監控的優勢
監控粒度: myAPM卡慢監控的粒度為方法。
性能消耗: myAPM卡慢方案,采用卡慢業務鏈路上報,是一種輕量級的業務堆棧,避免直接使用原生堆棧。避免了打堆棧的性能消耗。(打印原生堆棧:1-3ms,打印業務鏈路:0.1-0.3ms)。
數據上報: 采用了的一組鏈路ID。而非堆棧信息。上報量小,不用加解密過程。
代碼依賴: 卡慢邏輯與業務代碼完全解耦,對開發者透明,零感知。只是在測試,發布前注入。
5、不足及方案
myAPM,也存在不足。由于采用注入方式,會使apk的包,稍微變大。
以qzone android apk注入進行全量業務代碼時,其apk大小增長0.5M,增長率為2.79%.
方案:
若用戶對apk大小比較敏感,可以采用部分注入分析。
可以配合myAPM的apk包大小分析方案,做apk瘦身分析。
myAPM新特性
app卡慢只是用于問題方法的性能優化。其實,對于一個產品,我們不但要關注及處理卡慢的問題,還需要關注app應用常規的性能狀況與監控。
因為,這個性能波動,不會像卡慢那么明顯。但是在一次次新版本迭代中,可以會讓總體性能變慢。
1、監聽app啟動性能
我們可以將卡慢監控范圍進行定制縮小,提供個性化功能:只監聽啟動方法。
通過數據分析及比對,我們可以知道:
app每個版本的啟動性能及變化;
接入的各個產品在啟動性能上的差異,讓各個產品間可以相互借鑒與提升。
2、核心鏈路分析
無論是產品,開發,測試與運維,都會想知道:
一個APP中,哪些代碼是屬于核心鏈路?
這些核心鏈路的性能怎樣?
每個新版本中,這些核心鏈路的性能是否受到明顯的損耗?
我們可以繼續將卡慢上報范圍擴大,上報全量方法。通過數據分析及篩選,我們可以挖掘出核心鏈路及其性能數據;
3、延時加載
通過鏈路特性分析,我們也可以抽取出調用次數很少,非主場景調用的代碼。對于這些代碼,在app啟動加載時,我們可以使用延時加載。從而提升APP的啟動效率。
續集說明
對于App 啟動性能分析以及App 核心鏈路性能分析,我們將在后續做單獨的介紹。
最后
myAPM,是我們結合部門實際需求和APM理念,在移動端性能管理的一個新探索,新實踐。不僅面向性能問題的定位,也應用于日常的app性能運營分析。
簡單分享myAPM在移動性能管理方面的一點思考及應用,希望大家打造好自己移動端的性能小船,關鍵時刻,不會說翻就翻。共勉!