android 北斗定位代码_大牛三步教你解决,BAT资深APP性能优化系列-卡顿定位问题,收藏哦
前言
講解的內容大體包含,異步優化,啟動優化,卡頓優化,內存優化,ARTHook, 監控耗時盲區,網絡,電量,瘦身及APP容災方案等
性能優化的系統學習方法
330頁 PDF Android進階核心筆記(對應思維導圖)
性能優化對應學習思維導圖(對應核心筆記)
性能優化學習資料視頻(系統,對應導圖和筆記)
- 學習資料
- 學習視頻
既然我們選擇了學習Android,那么我們能做的就是不斷提升自身的能力,我學每一塊都會自己做一張導圖,然后對于去找學習資料,視頻。這樣我學習下來,不僅有程序,有系統,學習效率還高。“精”一個點,就努力做到最好,這就是我對于Android的學習態度。如果也是走上了Android這條路,如果現在的你對性能優化這塊感興趣,但是沒有一個明確的學習思路,我給你分享我實戰經驗總結,幫助你少走一點彎路。
有需要的朋友 私信【進階】我免費分享給你,當然還是老樣子,如果你覺得對你有幫助,希望你能多多,點贊,轉發+關注,你們的支持就是我繼續的動力。還有其他Android方面想學習的知識,可以留言。最多的我會發文章,并且分享對應的資料給大家。
1.簡介
本篇文章是該系列文章中的第一篇,主要介紹的是在一些一線大廠的實際項目中,如果APP發生卡頓是如何進行定位問題的。主要介紹 程序的耗費時間
2.測量時間方式
首先,如果要查看頁面加載花費的時間有3種方式
3.adb命令
只需要一行命令,就可以查看加載頁面的時間。
adb shell am start -W 包名/包名.Activity復制代碼使用后會顯示
ThisTime: 代表啟動最后一個Activity的耗時
TotalTime: 代表啟動所有的Activity的耗時
WaitTime: 代表AMS啟動所有的Activity的耗時
注意點:該命令只能是獲取配置了的Activity, 其他的無效,因為Android組件中有個 exported 屬性,沒有intent-filter時exported 屬性默認為false,此組件只能由本應用用戶訪問,配備了intent-filter后此值改變為true,允許外部調用。
缺點: adb命令只能查看配置了的Activity,其他的無法查看,并且也無法精準的查看其方法具體耗費的時間,所以因為其局限性 并不能很好的解決我們問題,我們采用手動打點的方式查看。
4.手動打點
先看代碼
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); initBugly(); initBaiduMap(); initJPushInterface(); initShareSDK(); ... } private void initBugly() throws InterruptedException { Thread.sleep(1000); // 模擬耗費的時間 } private void initBaiduMap() throws InterruptedException { Thread.sleep(2000); // 模擬耗費的時間 } private void initJPushInterface() throws InterruptedException { Thread.sleep(3000); // 模擬耗費的時間 } private void initShareSDK() throws InterruptedException { Thread.sleep(500); // 模擬耗費的時間 }}代碼不用我說,項目中很常見,現在的問題是APP啟動加載很慢, 那么如何精準的查詢到具體耗時的方法?
long startTime = System.currentTimeMillis(); initBugly(); Log.d("lybj", "initBugly()方法耗時:"+ (System.currentTimeMillis() - startTime)); long startTime = System.currentTimeMillis(); initBaiduMap(); Log.d("lybj", "initBaiduMap()方法耗時:"+ (System.currentTimeMillis() - startTime)); ...這樣可以嗎?當然不行,耦合性太大,每一個方法都加,那么測試完了,刪除代碼也是個體力活,一不小心刪錯一個,就會造成災難性的問題,在實際項目中,比如中石油的一些項目,就會采用 AOP 的方式來測量方法的耗費時長。
4.1 AOP
AOP : Aspect Oriented Programming的縮寫,意為:面向切面編程
優點:
這里我們使用的是Aspectj
4.2 Aspectj 的使用
1.添加依賴
根目錄的build.gradle里
buildscript { ... dependencies { ... classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0' }}app項目的build.gradle及新建的module的build.gradle里添加
apply plugin: 'android-aspectjx'dependencies { ... implementation 'org.aspectj:aspectjrt:1.8.+'}2.創建切面
@Aspectpublic class PerformanceAop { @Around("call(* com.bj.performance.MyApplication.**(..))") public void getTime(ProceedingJoinPoint joinPoint){ long startTime = System.currentTimeMillis(); String methodName = joinPoint.getSignature().getName(); try { joinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } Log.d("lybj", methodName + "方法耗時:"+ (System.currentTimeMillis() - startTime)); }}看,根本無需修改任何工程代碼,就可以獲取運行時長了,點擊運行顯示
AspectJ語法參考
缺點: 如果項目比較龐大,上百個方法,總不能全部打掉,然后一個一個的分析到底是哪個地方運行時間過長吧,所以我們需要一個比較直觀的工具,一眼就能看到具體哪個方法運行時間過長。
5. traceView的使用
5.1 特點
5.2 使用方式
Debug.startMethodTracing("文件名");Debug.stopMethodTracing();在代碼中相應位置的地方打入埋點即可, startMethodTracing 有3個構造參數分別是
代碼運行完成后,會在
mnt/sdcard/Android/data/包名/files
生成一個.trace后綴的文件,可以用Profiler添加打開它。
當然也可以使用Profiler的錄制功能,但是因為要測量啟動時間,點擊錄制手速并不會那么的精準,所以采用埋點的方式獲取trace文件進行分析。
5.3 性能分析
打開文件后為上圖所示
5.4 時間模式
上圖標簽 1 所示:wallclock time 和 cpu time
注意:如果線程A執行函數b,但是因為函數b加了鎖,線程A進入等待狀態,那么wallclock time也是要計算時間的,而Thread time則只是計算CPU花費在它身上的時間。
一般根據經驗來講wall duration時間久說明耗時多,然后看Thread time 這個值說明cpu花費在其身上的時間多不多。不多的話基本可以直接異步(因為不搶占CPU)多的話需要合理調度好執行順序。
5.5 Call Chart
上圖標簽 2 所示:Call Chart
它的作用就是可以很直觀的查看到底是哪里耗時比較久,x軸為調用的時間線,越寬的表示耗時越久,y軸為調用的深度,也就是調用的子方法。父類在最上面,很明顯initBottomTab()方法調用是最耗時的。
鼠標懸浮可以查看耗費時間,雙擊可以跳轉到相應代碼
- 橙色:系統方法
- 藍色:第三方API(包括java語言的api)
- 綠色:App自身方法
簡易圖如下:
5.6 Flame Chart
上圖標簽 3 所示:Flame Chart 又稱之為火焰圖
y 軸表示調用棧,每一層都是一個函數。調用棧越深,火焰就越高,頂部就是正在執行的函數,下方都是它的父函數。 x 軸表示抽樣數,如果一個函數在 x 軸占據的寬度越寬,就表示它被抽到的次數多,即執行的時間長。注意,x 軸不代表時間,而是所有的調用棧合并后,按字母順序排列的。
火焰圖就是看頂層的哪個函數占據的寬度最大。只要有"平頂"(plateaus),就表示該函數可能存在性能問題。
練習1:
假如火焰圖如上圖所示,我們需要分析哪個函數嗎?
答:最頂層的函數g()占用 CPU 時間最多。d()的寬度最大,但是它直接耗用 CPU 的部分很少。b()和c()沒有直接消耗 CPU。因此,如果要調查性能問題,首先應該調查g(),其次是i()。 另外,從圖中可知a()有兩個分支b()和h(),這表明a()里面可能有一個條件語句,而b()分支消耗的 CPU 大大高于h()。
與Call Chart區別
方法D對B(B1、B2和B3)進行多次調用,其中一些調用B對C(C1和C3)進行調用。如果用Call Chart表示,則為
因為B1、B2和B3共享相同的序列調用者(A→D→B)聚合,如下所示。同樣,C1和C3聚合,因為它們共享相同的序列調用者(A→D→B→C)注意不包括C2, 因為它有不同的調用者序列(A→D→C)。
那么如果使用火焰圖,則表示:
也就是說,收集相同的調用序列的相同方法被收集并表示為火焰圖中的一個較長的欄(而不是將它們顯示為多個更短的條)
5.7 Top Down
上圖標簽 4 所示: Top Down 顯示一個函數調用列表,在該列表中展開函數節點會顯示函數的被調用方
看上圖右邊區域:
- Self:方法調用用于執行自己的代碼而不是它的子類的時間量。
- Children:方法調用花費的時間用于執行其被調用者,而不是其自己的代碼
- Total:方法的Self和Children的時間的總和。這表示應用程序執行方法調用的總時間量
5.8 Bottom Up
上圖標簽 5 所示: Bottom Up 顯示一個函數調用列表,在該列表中展開函數節點將顯示函數的調用方。
Bottom Up選項卡對于那些消耗最多(或最少)CPU時間的方法的排序方法很有用。可以檢查每個節點,以確定哪些調用者在調用這些方法上花費最多的CPU時間。
- Self:方法調用用于執行自己的代碼而不是它的子類的時間量。
- Children:方法調用花費的時間用于執行其被調用者,而不是其自己的代碼
- Total:方法的Self和Children的時間的總和。這表示應用程序執行方法調用的總和
簡略圖如下
缺點: 在項目中用到的,最多的還是Call Chart 和 Top Down, 但是traceView的原理就是抓取所有線程的所有函數里的信息,所以會導致程序變慢, 所以常用的是SysTrace
SysTrace 作者用的不多,有興趣的朋友可以自行百度,用法和traceView的使用差不多,就不在分析了
總結
以上是生活随笔為你收集整理的android 北斗定位代码_大牛三步教你解决,BAT资深APP性能优化系列-卡顿定位问题,收藏哦的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sourceinsight4 quick
- 下一篇: 笔记本电脑怎么清理灰尘_家里边边角角灰尘