摘要:全稱應(yīng)用性能管理監(jiān)控后面我會通過一系列的文章來介紹的原理框架設(shè)計與實現(xiàn)等等。在應(yīng)用構(gòu)建期間,通過修改字節(jié)碼的方式來進行字節(jié)碼插樁就是實現(xiàn)自動化的方案之一。
歡迎關(guān)注微信公眾號:BaronTalk,獲取更多精彩好文!一. 前言
性能問題是導(dǎo)致 App 用戶流失的罪魁禍首之一,如果用戶在使用我們 App 的時候遇到諸如頁面卡頓、響應(yīng)速度慢、發(fā)熱嚴重、流量電量消耗大等問題的時候,很可能就會卸載掉我們的 App。而往往獲取用戶的成本是高昂的,因此因為性能問題導(dǎo)致用戶流失的情況是我們要極力避免的,做不好這一點是我們開發(fā)人員的失職。
去年我們團隊完成了整個項目架構(gòu)方面的重構(gòu)(有興趣的同學(xué)可以參考我之前的文章安居客 Android 項目架構(gòu)演進 與Android 模塊化探索與實踐 ),目前已經(jīng)能夠很好的支撐我們的業(yè)務(wù),并對團隊的開發(fā)效率也有了一定的提升、項目質(zhì)量也有了大幅的進步。
但是項目上線后,到底有沒有性能問題?用戶體驗到底怎么樣?在用戶的使用場景中到底會遇到哪些性能問題?我們項目的性能短板又在哪里?這些問題的答案我們都不得而知,因此開發(fā)一套完善的性能監(jiān)控體系勢在必行。我們團隊在今年開始著手開發(fā)自己的性能監(jiān)控組件 APM,希望通過它來采集線上性能數(shù)據(jù),找到性能短板,針對性的優(yōu)化用戶體驗。
APM 全稱 Application Performance Management & Monitoring (應(yīng)用性能管理/監(jiān)控)
后面我會通過一系列的文章來介紹 APM 的原理、框架設(shè)計與實現(xiàn)等等。本篇就是這個系列的第一篇,主要從實現(xiàn)原理方面來介紹 APM。按照目前的計劃,這個系列大致會從如下幾個方面來展開:
原理篇:主要介紹 APM 的實現(xiàn)原理;
設(shè)計篇:介紹整個 APM 框架設(shè)計;
實現(xiàn)篇-Gradle Plugin:介紹 Gradle 插件在 APM 項目中的應(yīng)用,以及如何開發(fā)一個 Gradle Plugin;
實現(xiàn)篇-Javassist/ASM:Javassist、ASM 等字節(jié)碼操作庫的介紹,以及如何使用它們在編譯時插入代碼來采集各項性能數(shù)據(jù);
實現(xiàn)篇-數(shù)據(jù)存儲及上報:介紹 APM 框架的存儲上報機制及實現(xiàn)過程;
發(fā)布集成:最后會介紹如何將庫發(fā)布到 jCenter() 以及如何在生產(chǎn)項目中集成。
這里要向大家交代一點是,之前的文章為了極力做到將復(fù)雜的問題用通俗易懂的方式解釋清楚,又要面面俱到,往往篇幅過長;諸如之前寫過的RxJava系列6(從微觀角度解讀RxJava源碼) 、神兵利器Dagger2 、安居客 Android 項目架構(gòu)演進 、Android 模塊化探索與實踐 、寫給 Android 應(yīng)用工程師的 Binder 原理剖析等文章,篇幅通常都在 8000~10000字以上,通篇閱讀下來可能需要近半個小時的時間,不太符合當下碎片化閱讀的需求;因此在后面的寫作上會控制篇幅,盡量控制在 10 分鐘以內(nèi)的長度。
這也是我為什么會將 APM 作為一個系列來介紹的原因,同時這也能保證后面在介紹 APM 的時候能夠深入到實現(xiàn)細節(jié),避免泛泛而談。
二. Android APM 的基本原理市場上有很多商業(yè)化的 APM 平臺,比如著名的 NewRelic,還有國內(nèi)的 聽云、OneAPM 等等。這些平臺的工作流程基本都是一致的:
首先在客戶端(Android、iOS、Web等)采集數(shù)據(jù);
接著將采集到的數(shù)據(jù)整理上報到服務(wù)器;
服務(wù)器接收到數(shù)據(jù)后建模、存儲、挖掘分析,讓后將數(shù)據(jù)可視化,供用戶使用。
如下圖:
我們介紹的 Android APM 框架其實就是在 Android 平臺上應(yīng)用的一個數(shù)據(jù)采集上報 SDK。主要包含三大模塊:
數(shù)據(jù)采集
數(shù)據(jù)存儲
數(shù)據(jù)上報
其中數(shù)據(jù)采集是整個 APM 框架的核心。
數(shù)據(jù)采集我們可以通過手動埋點的方式,但這種方式工作量巨大、不靈活,而且無法覆蓋到所有場景;因此只能通過自動化的方式來采集數(shù)據(jù)。在應(yīng)用構(gòu)建期間,通過修改字節(jié)碼的方式來進行字節(jié)碼插樁就是實現(xiàn)自動化的方案之一。
三. Android 打包流程及字節(jié)碼插樁原理在談字節(jié)碼插樁的原理之前,首先我們看看 Android 的打包流程,如下圖:
從上面這張打包流程圖我們可以看到,一個 App 的所有 class 文件,包括第三方的 class 文件都會經(jīng)過 dex 的過程打包成一個或者多個 dex 文件。
這其中涉及到兩個很關(guān)鍵的環(huán)節(jié):
javac:將 .java 格式的源代碼文件編譯成 class 文件;
dex: 將 class 格式的文件打包匯總,組成一個或者多個 dex 文件。
我們想要對字節(jié)碼進行修改,只需要在 javac 之后 dex 之前遍歷所有的字節(jié)碼文件,并按照一定的規(guī)則過濾修改就好了,這里便是字節(jié)碼插樁的入口。
那么我們到底如何介入打包過程,在 class 轉(zhuǎn)換為 dex 文件的時候?qū)崿F(xiàn)對字節(jié)碼的修改呢?
答案是 transform api
Android Gradle Plugin 1.5.0 及以上版本,Google 官方提供了 transform api 作為字節(jié)碼插樁的入口。我們只需要實現(xiàn)一個自定義的 Gradle Plugin,然后在編譯階段去修改字節(jié)碼文件。對于 Gradle Plugin 的具體實現(xiàn)后面的文章再做詳細講解。
四. 修改字節(jié)碼找到了插樁入口,接下來就要對字節(jié)碼進行修改。對于字節(jié)碼的修改,比較常用的框架有 Javassist 和 ASM。
Javassist 是一個開源的分析、編輯和創(chuàng)建 Java 字節(jié)碼的類庫,它提供了源碼級別的 API 以及字節(jié)碼級別的 API,源碼級別的 API,直接使用 Java 編碼的形式,而不需要深入了解虛擬機指令,就能動態(tài)改變類的結(jié)構(gòu)或者動態(tài)生成類。
ASM 是一個 Java 字節(jié)碼操控框架。它能被用來動態(tài)生成類或者增強既有類的功能。ASM 可以直接產(chǎn)生二進制 class 文件,也可以在類被加載入 Java 虛擬機之前動態(tài)改變類行為。
ASM 和 Javassit 相比,API 貼近底層,比較難使用,需要對 Java 字節(jié)碼和虛擬機方面有一定程度的了解。ASM 的優(yōu)點就在于性能上的優(yōu)勢,且更加靈活;Javassist 的實現(xiàn)中大量使用的反射,所以性能偏低。
簡單的說就是 ASM 雖然難以使用,但是功能強大效率高。是很多無痕埋點、APM框架的首選方案。
ASM 的具體時候我們放到這個系列后面的文章介紹。
五. 總結(jié)Android APM 的原理其實非常簡單,用一句話總結(jié)就是:
依據(jù)打包原理,在 class 轉(zhuǎn)換為 dex 的過程中,調(diào)用 gradle transform api 遍歷 class 文件,借助 Javassist、ASM 等框架修改字節(jié)碼,插入我們自己的代碼實現(xiàn)性能數(shù)據(jù)的統(tǒng)計。
以上所有過程都是在編譯期完成的。
其實 Android 上的無痕埋點也是同樣的原理,區(qū)別只不過是我們 hook 的點不同,采集的數(shù)據(jù)不同,因此掌握了 APM 的實現(xiàn)原理同樣可以實現(xiàn)無痕埋點系統(tǒng)。
原理很簡單,難的是實現(xiàn)細節(jié)。比如如何插樁采集到頁面幀率、流量、耗電量等等。這些具體細節(jié)我們放到后面一一介紹。至于為什么放到后面……因為很多東西自己沒做過我也不知道啊……
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/69645.html
摘要:不努力不奮斗,可能就會在基層一輩子止步不前。不過,只一句,如果你還在做這一行,還是一名程序猿媛,想走上坡路的你,也許我這到手的十幾家一線互聯(lián)網(wǎng)公司性能優(yōu)化項目實戰(zhàn)可能會對你有所幫助。 ...
摘要:阻塞,非阻塞首先,阻塞這個詞來自操作系統(tǒng)的線程進程的狀態(tài)模型網(wǎng)絡(luò)爬蟲基本原理一后端掘金網(wǎng)絡(luò)爬蟲是捜索引擎抓取系統(tǒng)的重要組成部分。每門主要編程語言現(xiàn)未來已到后端掘金使用和在相同環(huán)境各加載多張小圖片,性能相差一倍。 2016 年度小結(jié)(服務(wù)器端方向)| 掘金技術(shù)征文 - 后端 - 掘金今年年初我花了三個月的業(yè)余時間用 Laravel 開發(fā)了一個項目,在此之前,除了去年換工作準備面試時,我并...
摘要:阻塞,非阻塞首先,阻塞這個詞來自操作系統(tǒng)的線程進程的狀態(tài)模型網(wǎng)絡(luò)爬蟲基本原理一后端掘金網(wǎng)絡(luò)爬蟲是捜索引擎抓取系統(tǒng)的重要組成部分。每門主要編程語言現(xiàn)未來已到后端掘金使用和在相同環(huán)境各加載多張小圖片,性能相差一倍。 2016 年度小結(jié)(服務(wù)器端方向)| 掘金技術(shù)征文 - 后端 - 掘金今年年初我花了三個月的業(yè)余時間用 Laravel 開發(fā)了一個項目,在此之前,除了去年換工作準備面試時,我并...
摘要:昨天有個小學(xué)弟給我發(fā)來微信,說他現(xiàn)在有點后悔選擇開發(fā)了,月月光不說,還加班特別嚴重,平時也沒有屬于自己的時間去學(xué)習(xí),問我剛畢業(yè)的時候是不是這樣。每天回到出租屋都是倒頭就睡,非常累,也沒有其他時間提升自己的技術(shù)。 昨天有個小學(xué)弟給我發(fā)來微信,說他現(xiàn)在有點后悔選擇Android開發(fā)了,月月光不說...
閱讀 2129·2023-04-25 21:11
閱讀 2994·2021-09-30 09:47
閱讀 2299·2021-09-24 09:48
閱讀 4477·2021-08-23 09:43
閱讀 927·2019-08-30 15:54
閱讀 590·2019-08-28 18:01
閱讀 1431·2019-08-27 10:55
閱讀 610·2019-08-27 10:55