Android ANR監控與分析,androidanr監控
轉載自:http://www.10tiao.com/html/203/201609/2649752287/1.html
ANR(Application Not Responding),系統檢測到APP長時間沒有反應,ANR雖然不是異常但會嚴重影響使用者體驗,所以上報解決ANR是非常必要的。
ANR的觸發條件
“觸發ANR的必要條件是主線程阻塞。
分為以下三類:
主線程在5s內沒有處理完輸入事件;
Service阻塞20s;
前台廣播阻塞10s或後台廣播阻塞60s。
實際使用中ANR通常是由第一類觸發條件觸發的。
ANR執行流程
瞭解ANR執行流程有利於我們制定ANR監控策略和擷取ANR的相關資訊,ANR的執行步驟如下:
系統捕獲到ANR發生;
Process 依次向本進程及其他正在啟動並執行進程發送Linux訊號量3;
進程接收到Linux訊號量,並向 /data/anr/traces.txt 中寫入進程資訊;
Log日誌列印ANR資訊;
進程進入ANR狀態(此時可以擷取到進程ANR資訊);
彈出ANR提示框;
提示框消失,進程迴歸正常狀態。
由於向 /data/anr/traces.txt 檔案中寫入資訊耗時較長,從Input ANR觸發到彈出ANR提示框一般在10s左右(不同rom時間不同)。
ANR監控機制
當APP發生ANR時,並不會像發生java異常時有回調介面,因此我們需要主動式監控ANR何時發生並擷取ANR相關資訊。
1FileObserver監控機制
監控方法:通過 FileOberver 監控 data/anr 檔案夾下檔案的變化,來確定ANR的發生。
擷取資訊:主線程堆棧資訊+ANR資訊。
優點:基於Linux底層通知機制,不額外消耗效能。
缺點:監控不到Android5.0及以上版本的大部分機型。
ANR發生時多個進程會依次向 data/anr/traces.txt 檔案中寫入資訊,因此 onEvent 方法會被多次回調,所以第一次回調 onEvent 方法後不再執行方法內部的邏輯。
FileObserver監控流程:
由於剛監控到ANR發生時進程並沒有進入ANR狀態,而是先向 /data/anr/traces.txt 檔案中寫入進程資訊,此時並不會立即擷取到進程的ANR資訊,需要迴圈等待進程進入ANR狀態。
ANR資訊擷取流程:
擷取主線程堆棧資訊
Thread mainThread = Looper.getMainLooper().getThread();
StackTraceElement[] mainStackTrace = mainThread.getStackTrace();
2WatchDog監控機制
監控方法:在子線程中每隔5s向主線程發送資訊來判斷主線程是否阻塞,如果阻塞則認為發生ANR。
擷取資訊:主線程堆棧資訊+ANR資訊。
優點:可以監控到任意機型的ANR,不會因為系統的某些改變而失效。
缺點:會產生額外消耗(影響不大)。
設定一個本地變數和全域變數,開啟監控時兩個變數相等,並讓主線程執行全域變數+1操作 ,5秒後判斷全域變數是否還和本地變數相等,若相等說明主線程阻塞了5s。繼續讓主線程執行 全域變數+1操作 ,由於上個5s主線程處於阻塞狀態,進程可能發生ANR因此接下來5s不斷地擷取ANR資訊,5s後未擷取到繼續判斷 全域變數是否完成+1 操作。(不斷地擷取ANR資訊是為了確定進程是否真正發生了ANR)
WatchDog監控流程:
WatchDog監控周期:
設定監控間隔為5s,則監控周期為 5s~10s。
如,綠色代表主線程空閑,紅色代表主線程阻塞。在0s時向主線程發送資訊,此時主線程沒有阻塞,執行全域變數+1,在5s時全域變數已經+1WatchDog不認為主線阻塞,並繼續向主線程發送資訊,9s時主線程空閑執行全域變數+1,10s時全域變數完成+1,WatchDog不認為主線程阻塞。
現象:監控間隔為5s的WatchDog並沒有發現主線程持續了8s的阻塞。
結論:WatchDog監控到主線程阻塞的條件是,在一個監控間隔內主線程持續阻塞。
監控間隔5s,主線程阻塞8s,WatchDog監控機率 (8-5)/5 * 100% = 60%,主線程阻塞10s及以上WatchDog監控機率為100%。
由於主線程的阻塞通常持續到ANR提示框消失後,這個過程大約是10秒左右,所以監控間隔設定為5s。
3混合監控
利用以上兩種監控機制的優勢最終使用如下方案實現ANR的全機型監控:
FileObserver + WatchDog
Android 5.0 以下版本使用 FileObserver;
Android 5.0 及以上版本判斷是否可以監控到 data\anr 檔案夾的事件
a.可以監控到,使用 FileObserver;
b.監控不到,使用 WatchDog。
日誌分析
通過ANR資訊和主線程堆棧資訊分析ANR
1ANR資訊
發生ANR的進程及組件;
ANR的類型(5.0以上帶有等待隊列的長度和隊列頭等待的時間長度);
CPU資訊(可以判斷是否是由於效能問題導致的ANR)
CPU平均負載 Load (1分鐘,5分鐘,15分鐘) 某一時刻正在使用和等待使用CPU的進程平均數量;
ANR之前、之後CPU平均使用率 佔用CPU時間 / 總時間 * 100%;
user:使用者態已耗用時間
kernel:核心態已耗用時間
iowait:等待I/O操作的時間
irq:CPU硬中斷的時間
softirq:CPU非強制中斷的時間
faults:minor(次要頁錯誤)
major(主要頁錯誤)
核心在讀取資料時會先尋找CPU的cache和記憶體,如果找不到發出MPF資訊,磁碟資料被載入到記憶體後,核心再次讀取時會發出一個MnPF資訊。可通過major次數來推斷那個進程在進行磁碟I/O操作。
2主線程堆棧資訊
主線程堆棧資訊最底層是進程啟動時調用的函數,其中 ActivityThread.main 是Android程式的入口,最頂層是主線程正在執行的函數。
如何避免ANR
1主線程
避免在主線程中進行網路,資料庫和大量運算等耗時操作;
主線程要避免使用Thread.wait() 或者 Thread.sleep()等待子線程,使用AsynTask Handler Bolts等架構,子線程完成時通知主線程;
使用IntentService,IntentServcie是在子線程中執行的;
降低子線程的優先順序,主線程可以擁有更多的機會使用CPU資源。
2停頓感
人們感知的時間是100ms到200ms
QACR平台
QACR平台支援監控Android用戶端的 java異常,native異常,ANR卡頓。並及時將異常上報到QACR異常統計平台,平台會對異常進行管理和多維度統計。QACR為開發人員提供release、beta兩套環境,便於開發人員對線上包和開發測試包的異常分別進行管理和統計。
查看評論