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

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

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

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

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

實(shí)例三:
在主線程中,加載本地xml文件導(dǎo)致卡慢。

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