1. 程式人生 > >效能分析與優化方案

效能分析與優化方案

效能問題分類

1、渲染問題:過度繪製、佈局冗雜

2、記憶體問題:記憶體浪費(記憶體管理)、記憶體洩漏

3、功耗問題:耗電

效能優化工具

以下優化工具在下面文章中具體介紹使用方法。

1、手機開發者選項:除錯GPU過度繪製、啟用嚴格模式、顯示CPU使用情況、GPU呈現模式分析、顯示所有"應用程式無響應"。(小米手機開發開發者選項中名字)

2、IDE中:Android Studio,比如靜態程式碼檢測工具、Memory Monitor、CPU Monitor、NetWork Monitor、GPU Monitor、Layout Inspector、Analyze APK等。

3、SDK中:sdk\tools,比如DDMS、HierarchyViewer、TraceView等。

4、第三方工具:MAT、LeakCanary、GT等。

效能優化指標

1、渲染

  • 滑動流暢度:FPS,即Frame per Second,一秒內的重新整理幀數,越接近60幀越好;

  • 過度繪製:單頁面的3X(粉紅色區域) Overdraw小於25%

  • 啟動時間:這裡主要說的是Activity介面啟動時間,一般低於300ms,需要用高頻攝像機計算時間。

2、記憶體

  • 記憶體大小:峰值越低越好,需要優化前後做對比

  • 記憶體洩漏:需要用工具檢查對比優化前後

3、功耗

  • 單位時間內的掉電量,掉電量越少越好,業內沒有固定標準。華為有專門測試功耗的機器,以及自己的標準。

1渲染問題

先來看看造成應用UI卡頓的常見原因都有哪些?

1、人為在UI執行緒中做輕微耗時操作,導致UI執行緒卡頓;

2、佈局Layout過於複雜,無法在16ms內完成渲染;

3、同一時間動畫執行的次數過多,導致CPU或GPU負載過重;

4、View過度繪製,導致某些畫素在同一幀時間內被繪製多次,從而使CPU或GPU負載過重;

5、View頻繁的觸發measure、layout,導致measure、layout累計耗時過多及整個View頻繁的重新渲染;

6、記憶體頻繁觸發GC過多(同一幀中頻繁建立記憶體),導致暫時阻塞渲染操作;

7、冗餘資源及邏輯等導致載入和執行緩慢;

8、臭名昭著的ANR;

1、過度繪製

造成過度優化的關鍵是什麼?多餘的背景(Background)

參考:

http://jaeger.itscoder.com/android/2016/09/29/android-performance-overdraw.html

優化步驟如下:

1、移除或修改Window預設的Background

2、移除XML佈局檔案中非必需的Background

3、按需顯示佔位背景圖片

4、控制繪製區域

2佈局優化

佈局太過複雜,層級巢狀太深導致繪製操作耗時,且增加記憶體的消耗。
我們的目標就是,層級扁平化。

佈局優化的建議:

第一個建議:可以使用相對佈局減少層級的就使用相對佈局,否則使用線性佈局。Android中RelativeLayout和LinearLayout效能分析,參考:http://www.jianshu.com/p/8a7d059da746#

第二個建議:用merge標籤來合併佈局,這可以減少佈局層次。

第三個建議:用include標籤來重用佈局,抽取通用的佈局可以讓佈局的邏輯更清晰明瞭,但要避免include亂用。

第四個建議:避免建立不必要的佈局層級。(最容易發生的!)

第五個建議:使用惰性控制元件ViewStub實現佈局動態載入

如何藉助工具檢視程式碼佈局?

Android SDK 工具箱中有一個叫做 Hierarchy Viewer 的工具,能夠在程式執行時分析 Layout。
可以用這個工具找到 Layout 的效能瓶頸
該工具的使用條件:模擬器或者Root版真機。
如何開啟該功能:AndroidStudio中,Tools — Android — Android Devices Monitor
該工具的缺點:使用起來麻煩。

ViewStub的使用

這個標籤最大的優點是當你需要時才會載入,使用他並不會影響UI初始化時的效能。

使用ViewStub可以避免記憶體的浪費,加快渲染速度。

其實ViewStub就是一個寬高都為0的一個View,它預設是不可見的,只有通過呼叫setVisibility函式或者Inflate函式才會將其要裝載的目標佈局給加載出來,從而達到延遲載入的效果,這個要被載入的佈局通過android:layout屬性來設定。

當準備inflate ViewStub時,呼叫inflate()方法即可。還可以設定ViewStub的Visibility為VISIBLE或INVISIBLE,也會觸發inflate。注意的是,使用inflate()方法能返回佈局檔案的根View。

注意:使用ViewStub載入的佈局中不能使用merge標籤。

3記憶體浪費

程式記憶體的管理是否合理高效對應用的效能有著很大的影響。
推薦閱讀Android效能優化典範-第3季,參考:
http://hukai.me/android-performance-patterns-season-3/

ArrayMap

Android為移動作業系統特意編寫了一些更加高效的容器,例如ArrayMap、SparseArray。

為了解決HashMap更佔記憶體的弊端,Android提供了記憶體效率更高的ArrayMap。

先來看看HashMap的原理

HashMap的整體結構如下:

儲存位置的確定流程:

再看來看看ArrayMap是如何優化記憶體的

它內部使用兩個陣列進行工作,其中一個數組記錄key hash過後的順序列表,另外一個數組按key的順序記錄Key-Value值,如下圖所示:

當你想獲取某個value的時候,ArrayMap會計算輸入key轉換過後的hash值,然後對hash陣列使用二分查詢法尋找到對應的index,然後我們可以通過這個index在另外一個數組中直接訪問到需要的鍵值對。

既然ArrayMap中的記憶體佔用是連續不間斷的,那麼它是如何處理插入與刪除操作的呢?它跟HashMap有什麼區別?二者之間的刪除插入效率有什麼差異?請看下圖所示,演示了Array的特性:

HashMap與ArrayMap之間的記憶體佔用效率對比圖如下:

與HashMap相比,ArrayMap在迴圈遍歷的時候更加高效。

什麼時候使用ArrayMap呢?

1、物件個數的數量級最好是千以內,沒有頻繁的插入刪除操作

2、資料組織形式包含Map結構

Autoboxing(避免自動裝箱)

Autoboxing的行為還經常發生在類似HashMap這樣的容器裡面,對HashMap的增刪改查操作都會發生了大量的autoboxing的行為。當key是int型別的時候,HashMap和ArrayMap都有Autoboxing行為。

SparseArray(專案中用到較多 -- 後面再說如何利用工具查詢該用SparseArray而沒有用到的地方)

為了避免Autoboxing行為Android提供了SparseArray,此容器使用於key為int型別。
SparseBooleanMap,SparseIntMap,SparseLongMap等容器,是key為int,value型別相應為boolean、int、long等。

Enum(列舉,專案中較多使用,應儘量避免)

Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.
Android官方強烈建議不要在Android程式裡面使用到enum。
關於enum的效率,請看下面的討論。假設我們有這樣一份程式碼,編譯之後的dex大小是2556 bytes,在此基礎之上,新增一些如下程式碼,這些程式碼使用普通static常量相關作為判斷值:

增加上面那段程式碼之後,編譯成dex的大小是2680 bytes,相比起之前的2556 bytes只增加124 bytes。假如換做使用enum,情況如下:

使用enum之後的dex大小是4188 bytes,相比起2556增加了1632 bytes,增長量是使用static int的13倍。不僅僅如此,使用enum,執行時還會產生額外的記憶體佔用,如下圖所示:

推薦一些文章:

  • HashMap,ArrayMap,SparseArray原始碼分析及效能對比,參考:http://www.jianshu.com/p/7b9a1b386265#

  • Android效能優化--小心自動裝箱:

    http://blog.csdn.net/lgz_ei/article/details/69208784

  • Android效能優化篇:Android中如何避免建立不必要的物件:http://blog.csdn.net/jia635/article/details/52525243

  • HashMap、ArrayMap、SparseArray分析比較:http://blog.csdn.net/chen_lifeng/article/details/52057427

  • Android效能優化之String篇:

    http://www.androidchina.net/5940.html

  • SharedPreferences的commit和apply分析:http://blog.csdn.net/u010198148/article/details/51706483

4記憶體洩露

什麼是記憶體洩漏?

一些不用的物件被長期持有,導致記憶體無法被釋放。

可能發生記憶體洩漏的地方有哪些?

內部類引用導致Activity的洩漏

在Java中,非靜態(匿名)內部類會預設隱性引用外部類物件。而靜態內部類不會引用外部類物件。

最典型的場景是Handler導致的Activity洩漏,如果Handler中有延遲的任務或者是等待執行的任務佇列過長,都有可能因為Handler繼續執行而導致Activity發生洩漏。

為了解決這個問題,可以在UI退出之前,執行remove Handler訊息佇列中的訊息與runnable物件。或者是使用Static + WeakReference的方式來達到斷開Handler與Activity之間存在引用關係的目的。

Activity Context被傳遞到其他例項中,這可能導致自身被引用而發生洩漏。

考慮使用Application Context而不是Activity Context。

例如:全域性Dialog或者Context被單例持有。

靜態造成的記憶體洩漏

還有靜態變數持有View,例如:

private static View view;
void setStaticView() {
  view = findViewById(R.id.sv_button);
}

注意監聽器的登出(稍後利用工具分析一個例子)

  • regist就要unregist

  • 注意Cursor物件是否及時關閉(專案中也存在,不再列舉)

  • WebView的引起的洩漏(暫時沒有研究)

相關推薦

效能分析優化方案

效能問題分類1、渲染問題:過度繪製、佈局冗雜2、記憶體問題:記憶體浪費(記憶體管理)、記憶體洩漏3、功耗問題:耗電效能優化工具以下優化工具在下面文章中具體介紹使用方法。1、手機開發者選項:除錯GPU過度繪製、啟用嚴格模式、顯示CPU使用情況、GPU呈現模式分析、顯示所有"應用程式無響應"。(小米手機開發開發者

Android效能全面分析優化方案研究

效能優化是一個持續的過程,要多種手段,一點一點優化,一般是優化影響比較大頭的,再逐步優化小頭的,

Android 系統性能優化(30)---Android效能全面分析優化方案研究

5.1、渲染問題先來看看造成應用UI卡頓的常見原因都有哪些?1、人為在UI執行緒中做輕微耗時操作,導致UI執行緒卡頓;2、佈局Layout過於複雜,無法在16ms內完成渲染;3、同一時間動畫執行的次數過多,導致CPU或GPU負載過重;4、View過度繪製,導致某些畫素在同一幀時間內被繪製多次,從而使CPU或G

MySQL服務器 IO 100%的分析優化方案

文件 %u mysq 希望 影響 前言 文章 興趣 排查 前言 壓力測試過程中,如果因為資源使用瓶頸等問題引發最直接性能問題是業務交易響應時間偏大,TPS逐漸降低等。而問題定位分析通常情況下,最優先排查的是監控服務器資源利用率,例如先用TOP 或者nmon等查看CPU、內存

由淺入深探究mysql索引結構原理、效能分析優化

第一部分:基礎知識 第二部分:MYISAM和INNODB索引結構 1、 簡單介紹B-tree B+ tree樹 2、 MyisAM索引結構 3、 Annode索引結構 4、 MyisAM索引與InnoDB索引相比較 第三部分:MYSQL優化 1、表資料型別選擇 2、sql語句優化 (1)     最左字首

帶你玩轉Visual Studio——效能分析優化

上一篇文章帶你玩轉Visual Studio——VC++的多執行緒開發講了VC++中多執行緒的主要用法。多執行緒是提升效能和解決併發問題的有效途經。在商用程式的開發中,效能是一個重要的指標,程式的效能優化也是一個重要的工作。 找到效能瓶頸 二八法則適

Top團隊大牛帶你玩轉Android效能分析優化

第1章 課程導學與學習指南 效能優化是高階工程師必備的技能,本課程將帶你由表及裡學到國內Top團隊對效能問題的體系化解決方案,滿滿的乾貨讓你輕鬆晉級高階工程師。  1-1 課前必讀(不看會錯過一個億)  1-2 課程導學試看

redis效能分析監控方案

1、redis slowlog分析2、SCAN,SSCAN,HSCAN和ZSCAN命令的使用方法3、檢查redis是否受到系統使用swap的影響4、使用redis watchdog定位延時5、關於redis的延時監控框架 redis官網資料參見這裡:https://red

css選擇器JQ選擇器的效能比對優化方案

css和JQ的選擇器寫起來似乎很相似,但他們的寫法在效能上有一定的區別。以下就較為常用的選擇器進行比對和優化:CSS選擇器效率高到低:1.id選擇器(#id)2.類選擇器(.class)3.標籤選擇器(div,h1,p)4.後代選擇器(li a)優化方案: 1.優先考慮用class選擇器,雖然id選擇器效率最

JavaScript 啟動效能瓶頸分析解決方案

在 Web 開發中,隨著需求的增加與程式碼庫的擴張,我們最終釋出的 Web 頁面也逐漸膨脹。不過這種膨脹遠不止意味著佔據更多的傳輸頻寬,其還意味著使用者瀏覽網頁時可能更差勁的效能體驗。瀏覽器在下載完某個頁面依賴的指令碼之後,其還需要經過語法分析、解釋與執行這些步驟。而本文則會

android TraceView效能分析效能優化

關於TraceView的效能分析的文章,我翻譯自官網,翻譯地址在eoe設局wiki上,網址: 關於效能優化,應該從以下基本的幾點做起: 1.避免建立不必要的物件,不要頻繁的建立物件。     對於有些操作如果可以不用穿件物件就儘量不要建立,建立物件即耗時又佔用空間。 2

Java內部類持有外部類的引用詳細分析解決方案

調用 lai urn star keyword inner android get sta 在Java中內部類的定義與使用一般為成員內部類與匿名內部類,他們的對象都會隱式持有外部類對象的引用,影響外部類對象的回收。 GC只會回收沒有被引用或者根集不可到達的對象(取決於GC算

ExoPlayer Talk 01 緩存策略分析優化

sca google mes efi allocator method policy 類型 let 操作系統:Windows8.1 顯卡:Nivida GTX965M 開發工具:Android studio 2.3.3 | ExoPlayer r2.5.1 使用 ExoP

PHP的fsockopen方式訪問接口慢的原因優化方案

gets 速度 odi 一點 部分 soc blog feof apach 在開發過程中常常遇到這樣的需求,模擬瀏覽器訪問某接口,並獲取返回數據。我們比較常使用的方法是fsockopen與接口建立連接,然後發出指令,然後通過fgets接受返回值。但是我們發現,通過PHP模擬

第五次作業——python效能分析幾個問題(個人作業)

結合 撰寫 porting tin 設計實現 cti personal 設計文檔 hub 第五次作業——效能分析與幾個問題(個人作業) 前言 閱讀了大家對於本課程的目標和規劃之後,想必很多同學都躍躍欲試,迫不及待想要提高自身實踐能力,那麽就從第一個個人項目開始吧,題目要求見

MySQL瓶頸分析優化

MySQL 優化 簡介通過sysbench的oltp_read_write測試來模擬業務壓力、以此來給指定的硬件環境配置一份比較合理的MySQL配置文件。環境介紹硬件配置軟件環境優化層級與指導思想優化層級MySQL數據庫優化可以在多個不同的層級進行,常見的有:SQL優化參數優化 架構優化本文重點關註:

大數據量數據庫設計優化方案(SQL優化)

把他 like 後者 結果集 表鎖 ted detail 出了 解決方案 轉自:http://blog.sina.com.cn/s/blog_6c0541d50102wxen.html 一、數據庫結構的設計 如果不能設計一個合理的數據庫模型,不僅會增加客戶端

OpenCV學習筆記(30)KAZE 演算法原理原始碼分析(四)KAZE特徵的效能分析比較

      KAZE系列筆記: 1.  OpenCV學習筆記(27)KAZE 演算法原理與原始碼分析(一)非線性擴散濾波 2.  OpenCV學習筆記(28)KAZE 演算法原理與原始碼分析(二)非線性尺度空間構

效能分析提升

圖形化工具進行效能分析 此篇部落格主要談談用圖形化工具分析與優化python程式碼,雖然我們的工程不是很大,但符合比較大吧,功能有字母頻率統計、詞頻統計、支援stopword、動詞時態歸一化、動介短語頻率統計。我以 step0-輸出某個英文文字檔案中 26 字母出現的頻率,由高到低

效能分析程式碼覆蓋率測試

效能分析 對程式碼優化的前提是需要了解效能瓶頸在什麼地方,程式執行的主要時間是消耗在哪裡,對於比較複雜的程式碼可以藉助一些工具來定位,python 內建了豐富的效能分析工具,如 profile,cProfile 與 hotshot 等。其中 Profiler 是 python 自帶的一組程式,能