程序結構優化

程序優化

對用戶體驗影響

```
所有的控件繪制、組件生命周期、控件回調 都是在主線程執行,因此減少主線程負擔 是在16ms內能繪制完一幀 ,提升用戶體驗的主要因素之一
```

工具

Traceview

關于UI卡頓問題我們還可以通過運行Traceview工具進行分析,他是一個分析器,記錄了應用程序中每個函數的執行時間;我們可以打開DDMS然后選擇一個進程,接著點擊上面的“Start Method Profiling”按鈕(紅色小點變為黑色即開始運行),然后操作我們的卡頓UI(小范圍測試,所以操作最好不要超過5s),完事再點一下剛才按的那個按鈕,稍等片刻即可出現分析圖表

整個界面包括上下兩部分,上面是你測試的進程中每個線程運行的時間線,下面是每個方法(包含parent及child)執行的各個指標的值。通過上圖的時間面板可以直觀發現,整個trace時間段main線程做的事情特別多,其他的做的相對較少。當我們選擇上面的一個線程后可以發現下面的性能面板很復雜,其實這才是TraceView的核心圖表,它主要展示了線程中各個方法的調用信息(CPU使用時間、調用次數等),這些信息就是我們分析UI性能卡頓的核心關注點。如下

* Incl CPU Time 當前方法(包含內部調運的子方法)執行占用的CPU時間;
* Excl CPU Time 當前方法(不包含內部調運的子方法)執行占用的CPU時間;
* Incl Real Time    當前方法(包含內部調運的子方法)執行的真實時間,ms單位;
* Excl Real Time    當前方法(不包含內部調運的子方法)執行的真實時間,ms單位;
* Calls+Recur Calls/Total   當前方法被調運的次數及遞歸調運占總調運次數百分比;
* CPU Time/Call 當前方法調運CPU時間與調運次數比,即當前方法平均執行CPU耗時時間;
* Real Time/Call    當前方法調運真實時間與調運次數比,即當前方法平均執行真實耗時時間;(重點關注)

有了對上面Traceview圖表的一個認識之后我們就來看看具體導致UI性能后該如何切入分析,一般Traceview可以定位兩類性能問題:

* 方法調運一次需要耗費很長時間導致卡頓;
* 方法調運一次耗時不長,但被頻繁調運導致累計時長卡頓。

譬如我們來舉個實例,有時候我們寫完App在使用時不覺得有啥大的影響,但是當我們啟動完App后靜止在那卻十分費電或者導致設備發熱,這種情況我們就可以打開Traceview然后按照Cpu Time/Call或者Real Time/Call進行降序排列,然后打開可疑的方法及其child進行分析查看,然后再回到代碼定位檢查邏輯優化即可;當然了,我們也可以通過該工具來trace我們自定義View的一些方法來權衡性能問題

dmtracedump

可以看見,Traceview能夠幫助我們分析程序性能,已經很方便了,然而Traceview家族還有一個更加直觀強大的小工具,那就是可以通過dmtracedump生成方法調用圖。具體做法如下:

dmtracedump -g result.png target.trace  //結果png文件  目標trace文件

每次用到Traceview分析就已經搞定問題了,所以說dmtracedump自己酌情使用吧。

Systrace

Systrace其實有些類似Traceview,它是對整個系統進行分析(同一時間軸包含應用及SurfaceFlinger、WindowManagerService等模塊、服務運行信息),不過這個工具需要你的設備內核支持trace(命令行檢查/sys/kernel/debug/tracing)且設備是eng或userdebug版本才可以,所以使用前麻煩自己確認一下```

監控

目前在debug階段 對cpu進行監控

優化點

緩沖

a. 線程池 連接池
b. 網絡緩存
    http response,
    根據http頭信息中的Cache-Control域確定緩存過期時間。
c. 文件IO緩存
    使用具有緩存策略的輸入流,BufferedInputStream替代InputStream,BufferedReader替代  Reader,BufferedReader替代BufferedInputStream.對文件、網絡IO皆適用。
d. layout緩存

數據結構選擇

ArrayList和LinkedList的選擇,ArrayList根據index取值更快,LinkedList更占內存、隨機插入刪除更快速、擴容效率更高。一般推薦ArrayList。
ArrayList、HashMap、LinkedHashMap、HashSet的選擇,hash系列數據結構查詢速度更優,ArrayList存儲有序元素,HashMap為鍵值對數據結構,LinkedHashMap可以記住加入次序的hashMap,HashSet不允許重復元素。
HashMap、WeakHashMap選擇,WeakHashMap中元素可在適當時候被系統垃圾回收器自動回收,所以適合在內存緊張型中使用。
Collections.synchronizedMap和ConcurrentHashMap的選擇,ConcurrentHashMap為細分鎖,鎖粒度更小,并發性能更優。Collections.synchronizedMap為對象鎖,自己添加函數進行鎖控制更方便。
 
Android也提供了一些性能更優的數據類型,如SparseArray、SparseBooleanArray、SparseIntArray、Pair。
Sparse系列的數據結構是為key為int情況的特殊處理,采用二分查找及簡單的數組存儲,加上不需要泛型轉換的開銷,相對Map來說性能更優。不過我不太明白為啥默認的容量大小是10,是做過數據統計嗎,還是說現在的內存優化不需要考慮這些東西,寫16會死嗎,還是建議大家根據自己可能的容量設置初始值

延遲操作

Java中延遲操作可使用ScheduledExecutorService,不推薦使用Timer.schedule;
Android中除了支持ScheduledExecutorService之外,還有一些delay操作,如
handler.postDelayed,handler.postAtTime,handler.sendMessageDelayed,View.postDelayed,AlarmManager定時等

避免在主線程執行過多操作。尤其某些輕微耗時操作

可以通過TraceView工具找出主線程的耗時操作和其他耗時的線程并作優化。另外減少主線程的GC停頓,因為即使并行GC,也會對heap加鎖,如果主線程請求分配內存的話,也會被掛起,所以盡量避免在主線程分配較多對象和較大的對象,特別是在onDraw等函數中,以減少被掛起的時間。另外可以通過去掉ListView ,ScrollView等控件的EdgeEffect效果,來減少內存分配和加快控件的創建時間

線程優先級

注意線程的優先級,對于占用CPU較多時間的函數,也要判斷線程的優先級。重要工作 及 主線程優先級要高,其他如埋點 日志等優先級放低

減少GC次數

安卓上的GC會引起性能卡頓,必須重點優化。除了第三章會詳細介紹對于圖片內存引起GC的優化,我們還做了如下工作:

* 減少對象分配,找出不必要的對象分配,如可以使用非包裝類型的時候,使用了包裝類型;字符串的+號和擴容;Handler.post(Runnable r)等頻繁使用。
* 對象的復用,對于頻繁分配的對象需要使用復用池。
* 盡早釋放無用對象的引用,特別是大對象和集合對象,通過置為NULL,及時回收。
* 防止泄露,除了最基本的文件、流、數據庫、網絡訪問等都要記得關閉以及unRegister自己注冊的一些事件外,還要盡量少的使用靜態變量和單例。
* 控制finalize方法的使用,在高頻率函數中使用重寫了finalize的類,會加重GC負擔,使得性能上有幾倍的差別。
* 合理選擇容器,在性能上優先考慮數組,即使我們現在習慣了使用容器,也要注意頻繁使用容器在性能上的隱患點:首先是擴容開銷, HashMap擴容時重新Hash的開銷較大。其次是內存開銷,HashMap需要額外的Map.Entry對象分配 ,需要額外內存,也容易產生更多的內存碎片。SparseArray和ArrayList等在內存方面更有優勢。再次是遍歷,對于實現了RandomAccess接口的容器如ArryList的遍歷,不應該使用foreach循環。
* 用工具監控和精雕細琢:在頁面滑動過程中,通過Memory Monitor查看內存波動和GC情況,還可通過AlloCation Tracker工具觀察內存的分配,發現很多小對象的分配問題。
* 利用Trace For OpenGL工具找出界面上導致硬件加速耗時的點,例如一些圓角圖片的處理等。

優化中間件代碼

中間件的代碼被上層業務方調用的比較頻繁,容易有較多的高頻率函數,也容易產生細節上的問題。除了頻繁分配對象外,例如類初始化性能,同步鎖的額外開銷,接口的調用時間,枚舉的使用 stringbuffer&stringbuilder 的使用 等等都是不能忽視的問題。

其他

異步 并發 算法優化 jni
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,002評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,400評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,136評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,714評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,452評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,818評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,812評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,997評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,552評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,292評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,510評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,035評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,721評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,121評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,429評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,235評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,480評論 2 379

推薦閱讀更多精彩內容

  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區別 13、...
    Miley_MOJIE閱讀 3,722評論 0 11
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,332評論 11 349
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,733評論 18 399
  • Java SE 基礎: 封裝、繼承、多態 封裝: 概念:就是把對象的屬性和操作(或服務)結合為一個獨立的整體,并盡...
    Jayden_Cao閱讀 2,130評論 0 8
  • Friday,August 18th. 本想打著出差沒時間的緣故,放棄寫今日的晨讀,可這次是天使戰勝了魔鬼。 此時...
    文小輝cool閱讀 161評論 0 2