成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

我這樣減少了26.5M Java內(nèi)存!

Miracle / 2175人閱讀

摘要:分析應(yīng)用靜息態(tài)內(nèi)存占用。這里采用的方式是靜息態(tài)內(nèi)存進(jìn)入,立即內(nèi)存操作一段時間之后再內(nèi)存一共有三次,可以利用對比的功能對比內(nèi)存增量。

作者:楊超,騰訊移動客戶端開發(fā) 工程師
商業(yè)轉(zhuǎn)載請聯(lián)系騰訊WeTest獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
原文鏈接:http://wetest.qq.com/lab/view/359.html

WeTest 導(dǎo)讀

歷時五天的內(nèi)存優(yōu)化已經(jīng)結(jié)束,這里總結(jié)一下這幾天都做了什么,有哪些收獲。優(yōu)化了,或可以優(yōu)化的地方都有哪些。(因為很多事還沒做,有些結(jié)論需要一定樣本量才能斷定,所以叫一期)一期優(yōu)化減少JavaHeap內(nèi)存占用約26.5M。

在任何性能優(yōu)化之前,要做的第一件事就是找到性能瓶頸!而找到性能瓶頸通常需要強(qiáng)大的debug工具輔助。內(nèi)存方面Android有 AndroidStudio 的 Android Profiler、Allocation Tracker,以及Eclipse的MAT用于分析java的內(nèi)存占用,相當(dāng)強(qiáng)大。而偏向native層面的內(nèi)存占用則找不到太好的工具,因此這里在做優(yōu)化前,先造了幾個工具。

一、造輪子

1. 線程創(chuàng)建分析工具

該工具使用native hook的方式,直接hook了pthread_create調(diào)用,并記錄每一個線程創(chuàng)建時的堆棧,并打印日志。同時維護(hù)一個running thread的集合,必要時 dump下來所有running thread的創(chuàng)建堆棧,用于分析野蠻線程創(chuàng)建的場景。以及對應(yīng)的日志分析工具。

2、 Linux /proc//smaps 文件分析腳本

主要用于跟蹤進(jìn)程的 Code 部分內(nèi)存(見下文)占用,分析出占用內(nèi)存較多的dex,so文件。排查第三方SDK占用過多內(nèi)存場景。網(wǎng)上只能找到一個perl腳本,功能不是很強(qiáng)大,鑒于筆者不熟悉perl的語法規(guī)范,改起來會比較困難,因此直接用python重寫了一個。

代碼在這里:https://gist.github.com/LanderlYoung/aedd0e1fe09214545a7f20c40c01776c

3、 快速Dump Android java heap腳本

因為分析內(nèi)存需要很多dump操作,所以干脆寫了個Bash腳本。

Bash腳本鏈接:https://gist.github.com/LanderlYoung/9cd0f49e49e42746622cc8e7b4bbcc8a

(順便提一下,android提供的 hprof-conv 工具有個參數(shù) -z 用于排除zygote的內(nèi)存,十分便利。)

二、Android 進(jìn)程 內(nèi)存分類

通常我們在系統(tǒng)的內(nèi)存管理頁面看到的內(nèi)存占用是進(jìn)程的PSS,也就是整個進(jìn)程的內(nèi)存占用,因此我們做優(yōu)化的要考慮到所有的內(nèi)存,不僅僅是Java Heap。

使用Android Studio(3.0 beta)的 Android Profiler工具。

我們可以很清晰的看到

1)進(jìn)程總內(nèi)存占用: 180M

2)JavaHeap: 48M

3)NativeHeap:native層的 so 中調(diào)用malloc或new創(chuàng)建的內(nèi)存 —— 28M

4)Graphics:OpenGL和SurfaceFlinger相關(guān)內(nèi)存 ——58M

5)Stack:線程?!?.89M

6)Code:dex+so相關(guān)代碼占用內(nèi)存——37.75M

7)Other:蜜汁存在

上述6中內(nèi)存占用除了兩種不需要考慮,其他5中通通需要優(yōu)化。不需要考慮的是:

1)Other:暫時無從分析

2)Graphics:若應(yīng)用沒有直接調(diào)用OpenGL,則可以確定這部分內(nèi)存是由Android Framework操控的,可以忽略。(當(dāng)然對于游戲類應(yīng)用,這里肯定是優(yōu)化重點。)

下面按照內(nèi)存分類分開逐一介紹分析方法,和結(jié)論:

JavaHeap

這里必然是內(nèi)存優(yōu)化的重點,無需多言。但是企鵝FM的業(yè)務(wù),UI,代碼已經(jīng)比較龐大,分析起來會顯得力不從心。因此這里主要從兩個方面入手,希望能總結(jié)出一套分析方法。

1、分析應(yīng)用 靜息態(tài) 內(nèi)存占用。
所謂靜息態(tài),是筆者自行定義的概念:

應(yīng)用在退后臺之后,不保留活動的場景下的內(nèi)存占用。

為什么要考察這個維度?因為這個是一個應(yīng)用內(nèi)存占用最低點的時候,后續(xù)打開任何Activity內(nèi)存只會更多,不會更少!

2、分析方法

1)開發(fā)者選項開啟“不保留活動”

2)進(jìn)入MainActivity,滑動頁面,操作一下

3)退后臺,Android Studio中強(qiáng)制執(zhí)行GC

4)dump java heap (注意上面提到的 hprof-conf 加上 -z 參數(shù)排除zygote的干擾)

5)MAT 分析 dump 下來的JavaHeap

重點介紹一下MAT:

這里可以直接打開domanitor_tree看占用內(nèi)存最多的實例。

從這里按照RetainedHeap倒序排列,一點一點的排查內(nèi)存占用。很容易發(fā)現(xiàn)不正常的內(nèi)存情況。

在企鵝FM中發(fā)現(xiàn):

1)圖片的內(nèi)存級緩存退后臺沒清空(此處屬于onTrimMemory回調(diào)的處理有誤),占用10M內(nèi)存

2)ImageMisc — 280k

② 是一個buffer,可以在不用的時候釋放內(nèi)存

③ 優(yōu)化目標(biāo),徹底干掉

3)播放頁應(yīng)用動畫的關(guān)系,UI是單例。其中相關(guān)View占用數(shù)百K內(nèi)存,而button的icon直接引用住了5-6M的bitmap資源。

4)播放列表存儲了103個ShowInfo,每個ShowInfo 22k,總計內(nèi)存約2.24M,ShowInfo冗余信息很多,可以考慮優(yōu)化數(shù)據(jù)結(jié)構(gòu)

5) DanmuManager — 510k

● mDanmuItemManager 內(nèi)含眾多彈幕

● 每條彈幕6k

● UI相關(guān)數(shù)據(jù),離開播放頁后應(yīng)該清理彈幕(因為無需展示了)

● 優(yōu)化目標(biāo),徹底干掉。

6) FileCacheService — 362k

② 其中緩存了每一個cache entry,其中圖片緩存較多

③ 每一個entry記錄完整文件路徑其比較長,因此路徑的字符串占用了很多內(nèi)存

④ 優(yōu)化方案:

● 文件Parent可以共用同一個File對象。

● entry = new File(parent, “entry_name”)

⑤ 優(yōu)化目標(biāo) 到100k

7)LiveRoomShowListManager -- 287k

② 優(yōu)化目標(biāo):UI相關(guān)數(shù)據(jù),離開界面應(yīng)該徹底干掉

8) DB InsertHelper, Sql Statement clearBinding

① 700K到2M

② InsetHelper中會引用住最后一次執(zhí)行DB insert調(diào)用的 數(shù)據(jù)(占位符)

③ InsertHelper的占位數(shù)據(jù)可以在insert完成之后清掉

針對上面提到的ShowInfo的數(shù)據(jù)結(jié)構(gòu)優(yōu)化

擬定優(yōu)化方案:

1)ShowList存儲的ShowInfo數(shù)量過多,30個足矣。

2)ShowInfo中Album字段占用10k內(nèi)存,其實同一個ShowList中大多數(shù)album是完全一致的(比如專輯類型的ShowList,主播類型的,自選集類型的,本地專輯的,etc...)。

預(yù)計內(nèi)存占用 2M -> 30*12K = 360K

3)靜息態(tài)內(nèi)存優(yōu)化總結(jié):

上述幾點加起來預(yù)期可以減少內(nèi)存占用:

10M + 280K + 5M + 2M + 510K + 260k + 287k + 1M = 約20M

3、 MainActivity 操作一段時間之后內(nèi)存增量

上面分析的是靜息態(tài)內(nèi)存,下面看一下MainActivity操作一點時間之后,內(nèi)存有怎樣的變化。

這里采用的方式是:

1)dump靜息態(tài)內(nèi)存

2)進(jìn)入MainActivity,立即dump內(nèi)存

3)操作一段時間之后再dump內(nèi)存

一共有三次dump,可以利用MAT對比heap的功能對比內(nèi)存增量。

打開MAT的historgram視圖

工具欄最右邊有個雙箭頭的icon,點擊可對比dump:如下圖

增量最多的還是Bitmap(底層用byte[]存儲),借助MAT的 Finer 工具可以直接看到Bitmap的圖片。

這里發(fā)現(xiàn)的幾個問題是(時間關(guān)系,應(yīng)該多次測試的,會發(fā)現(xiàn)更多問題):

① Banner的大圖沒有 Clip 導(dǎo)致 分辨率 很高

② 分類頁的 配置區(qū)域 沒有Clip

③ onRecycle沒有清除掉已經(jīng)引用的Bitmap,導(dǎo)致引用住不能gc

主要說一下第3點,是Banner每一個Item有一個大圖做背景,當(dāng)item的view被回收的時候,相應(yīng)的ImageView仍然持有著大圖,導(dǎo)致其不能回收。這里發(fā)現(xiàn)了4張1M+的大圖,其實理論上應(yīng)該只有1張。

這個問題可以推廣到所有的ListView場景,建議方式是:

替換為RecyclerView,在view回收的時候,ScarpView釋放圖片引用。

此外,MainActivity有5個tab,各個tab之間其實會用到相同的View(listview 的item),如果使用RecyclerView可以做到5個tab的RecyclerView共同復(fù)用同一個RecyclerPool,在節(jié)省內(nèi)存的同時還能顯著提高性能。

這里不方便直接測試內(nèi)存占用,預(yù)估可以節(jié)省內(nèi)存5-10M。

4、 正常操作應(yīng)用,觀察內(nèi)存占用圖表是否有突起

這里主要用來測試異常內(nèi)存分配的場景。

這里仍然需要很大人力,過很多頁面。

目前發(fā)現(xiàn)問題有:

1)service進(jìn)程,發(fā)送wns請求的時候,內(nèi)存異常增長2-3M。

這時可以使用AllocationTracker工具(點擊下圖工具欄的紅點),記錄峰值那一段內(nèi)存的分配,如圖:

這里可以直接看到分配的棧,定位過去看,發(fā)現(xiàn)是這樣的代碼,因為head是一個65536長的數(shù)組(在 com.tencent.wns.session.Session 的構(gòu)造函數(shù)寫死的長度),這里創(chuàng)建string就浪費了超大量的內(nèi)存。建議可以改成下圖彈窗里的樣子

2)另外一個問題是播放進(jìn)程,在切換節(jié)目的時候內(nèi)存會突然增長2-3M,簡單跟進(jìn)去看是exo創(chuàng)建buffer。似乎有問題,需要再多分析一下~

Native Heap

目前能看到的NativeHeap大小是

應(yīng)用啟動:26M 此時已經(jīng)初始化了 X5內(nèi)核和IM SDK

UGC錄音:26M->34M 退出之后時32M,還有部分沒釋放,疑似內(nèi)存泄漏

發(fā)起直播:32M->72M 退出之后42M,同樣沒有完全釋放

具體內(nèi)部占用情況還沒測。。。(都說了是一期)。

官方文檔:

https://source.android.com/devices/tech/debug/native-memory

Code

這一段明顯看到占用了很多內(nèi)存。各個場景下的使用情況是:

1)剛進(jìn)入應(yīng)用:38M

2)再使用UGC錄音:38.28M

3)再使用視頻直播(發(fā)起直播):46M

4)打開應(yīng)用內(nèi)WebView(X5內(nèi)核):56M

以上是主進(jìn)程的內(nèi)存,占用相當(dāng)多。需要注意的是code內(nèi)存占用一般是通過read-only方式mmap映射到內(nèi)存中的的dex、odex、so等文件,因此在內(nèi)存緊張的情況下,系統(tǒng)會回收這些內(nèi)存,只是在oom-killer中仍然會計算在內(nèi)。

另外播放進(jìn)程2.27M,service進(jìn)程1.1M還屬于比較正常的水平。

顯然主進(jìn)程的Code內(nèi)存占用太多了,需要分析。這里通過解析Linux標(biāo)準(zhǔn)的 /proc//smaps文件,這個文件記錄了進(jìn)程內(nèi)每一段虛擬內(nèi)存的文件映射情況,這個文件只有進(jìn)程自己有讀權(quán)限,所以要么用root的機(jī)器,要么就自己寫段代碼copy出來。結(jié)合上面提到的工具。分析結(jié)果如下

● 應(yīng)用so占用 app so map Rss = 3984 kB (其中IM SDK 2576k)

● 應(yīng)用的dex占用 app dex map Rss = 15101 kB

● X5內(nèi)核的so+dex內(nèi)存占用 tbs mem map Rss = 29048 kB

● 直播so相關(guān) avlive mem map Rss = 3092 kB

● 其中X5內(nèi)核的代碼沒有打進(jìn)apk,因此可以比較獨立的統(tǒng)計出來,占用有29M之多,讓人驚訝!

● 其次直播的java代碼打進(jìn)了apk不方便多帶帶統(tǒng)計內(nèi)存用量,但是so是獨立加載的,內(nèi)存占用3M也是不少的。

● 最后是應(yīng)用自身的dex占用有15M之多,因為自身代碼量很大,似乎可以理解,但是仍然很多?。?/p>

這里需要考慮的是 X5 內(nèi)核能否延時加載?因為沒打開WebView的時候就已經(jīng)占用了數(shù)M了。另外WebView關(guān)閉之后是否可以銷毀。

直播相關(guān)SO,可以考慮直播退出之后從內(nèi)存中卸載掉。(java規(guī)范是加載so的classloader被GC,相關(guān)so即可卸載)。

應(yīng)用自身dex占用。android 8.0 對art優(yōu)化一個叫做DexLayout 的能力,應(yīng)為mmap映射的文件不會被立即加載進(jìn)內(nèi)存,在用到的時候是按照頁大?。?k)加載的,當(dāng)用到的類在dex中分布很分散的時候,就會導(dǎo)致盲目加載很多頁,DexLayout就是把熱點類集中放到一起。這里FaceBook推出了ReDex工具,可以參考一下。

PS:關(guān)于DexLayout

三、線程創(chuàng)建

在AndroidStudio的Memory Profiler中沒有線程數(shù)這個維度。但是運行中,主進(jìn)程的線程數(shù)量通常會在100個左右,這是個驚人的數(shù)字,要知道Mac版的AndroidStudio也不過77個線程。。。。請自行體會一下。

關(guān)于線程的創(chuàng)建和內(nèi)存占用,請參考筆者的另一篇文章:《Android 創(chuàng)建線程源碼與OOM分析》 。

這里分析用的自制工具,dump下載所有running的線程,和他們創(chuàng)建時的堆棧。

結(jié)果是

● X5:25個線程(簡直。。。)

● IMSDK:17個線程

● StackBlur:8個線程

● WNS:7個線程

● ImageLoader:6個線程

● magnifiersdk:5個線程

需要注意,這里的棧和線程名,是創(chuàng)建線程的時候的調(diào)用棧,以及對應(yīng)的線程名(而不是子線程名)

事實上,用同樣的方法,還可以分析一下進(jìn)程歷史中所有創(chuàng)建過的線程,統(tǒng)計哪里創(chuàng)建線程最多。

通常來說,所有線程應(yīng)該有應(yīng)用統(tǒng)一的線程池來管理,sdk內(nèi)部需要線程池,應(yīng)該有外部注入一個線程池來提供給sdk使用。

如果有其他情況,如:不是在線程池創(chuàng)建的線程,在sdk自己的線程池里創(chuàng)建的線程,這種都可能導(dǎo)致線程數(shù)量的野蠻增長,需要聯(lián)系sdk的開發(fā)人員杜絕這種情況。

四、總結(jié)

以上就是這5天的工作結(jié)果:

java內(nèi)存占用基本合理,靜息態(tài) 內(nèi)存占用可以優(yōu)化20M,MainActivity運行時的內(nèi)存占用可以優(yōu)化5-10M。

code內(nèi)存占用太多,其中X5內(nèi)核占用29M實在太多,需要考慮優(yōu)化。

應(yīng)用內(nèi)的線程數(shù)量主要有X5內(nèi)核,IMSDK和WNS貢獻(xiàn),外網(wǎng)線程創(chuàng)建的OOM crash 系WNS的bug,需要聯(lián)系相關(guān)sdk開發(fā)人員。

最后是Native內(nèi)存占用還沒有詳細(xì)分析,暫時看不到使用情況。但是可以知道目前的結(jié)論是:Native內(nèi)存占用很多,且應(yīng)該存在內(nèi)存泄漏。

PS: 實際效果反饋

按照上述分析結(jié)果,進(jìn)行了相關(guān)的代碼調(diào)整。

執(zhí)行的點包括:

1、IntelliShowList pageSize 50->20

2、IntelliShowList 公用Album結(jié)構(gòu)

3、Afc-db clearBinding after insert, 數(shù)據(jù)庫

4、Afc-FileCacheService cache Entry with fileName not full path, 文件緩存

5、 fix onTrimMemory bug,退后臺清空圖片內(nèi)存緩存

6、播放頁相關(guān)控件,退后臺之后清掉icon,釋放bitma引用

未執(zhí)行的點包括:

1、播放頁的bottomPannel部分icon因為邏輯較為復(fù)雜,暫時未進(jìn)行處理。預(yù)計內(nèi)存占用1M

2、PlayLogic的historyList邏輯復(fù)雜暫時未處理,預(yù)計內(nèi)存占用500K

3、24h直播間LiveRoomShowListManager -- 287k

4、DanmuManager — 510k

5、經(jīng)過ice提醒,下載節(jié)目的record也會全部加載進(jìn)內(nèi)存。每個ShowInfo 22k,內(nèi)存占用取決于用戶下載的節(jié)目數(shù)。

效果對比:

before:39.32M

after:12.88M

                   優(yōu)化內(nèi)存占用 26.44M!










UPA—— 一款針對Unity游戲/產(chǎn)品的深度性能分析工具,由騰訊WeTest和unity官方共同研發(fā)打造,可以幫助游戲開發(fā)者快速定位性能問題。旨在為游戲開發(fā)者提供更完善的手游性能解決方案,同時與開發(fā)環(huán)節(jié)形成閉環(huán),保障游戲品質(zhì)。

目前,限時內(nèi)測正在開放中,點擊http://wetest.qq.com/cube/ 即可預(yù)約。

對UPA感興趣的開發(fā)者,歡迎加入QQ群:633065352

如果對使用當(dāng)中有任何疑問,歡迎聯(lián)系騰訊WeTest企業(yè)QQ:800024531

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70873.html

相關(guān)文章

  • (轉(zhuǎn))JVM調(diào)優(yōu)

    摘要:是指設(shè)定程序運行期間最大可占用的內(nèi)存大小。持久代一般固定大小為,所以增大年輕代后,將會減小年老代大小。更具應(yīng)用的線程所需內(nèi)存大小進(jìn)行調(diào)整。但是操作系統(tǒng)對一個進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無限生成,經(jīng)驗值在左右。此配置僅對年輕代有效。 1、freeMemory(), totalMemory(), maxMemory()比較 最近在網(wǎng)上看到一些人討論到j(luò)ava.lang.Runtime類...

    youkede 評論0 收藏0
  • 一次線上問題排查所引發(fā)的思考

    摘要:直到有一天你會碰到線上奇奇怪怪的問題,如線程執(zhí)行一個任務(wù)遲遲沒有返回,應(yīng)用假死。正好這次借助之前的一次生產(chǎn)問題來聊聊如何排查和解決問題。本地模擬上文介紹的是線程相關(guān)問題,現(xiàn)在來分析下內(nèi)存的問題。盡可能的減少多線程競爭鎖。 showImg(https://segmentfault.com/img/remote/1460000015568421?w=2048&h=1150); 前言 之前或...

    levy9527 評論0 收藏0
  • [譯]GC專家系列3-GC調(diào)優(yōu)

    摘要:原文鏈接本篇是專家系列的第三篇。但是,請記住調(diào)優(yōu)是不得已時的選擇??s短耗時的單次執(zhí)行與相比,耗時有較明顯的增加。創(chuàng)建文件過程中,進(jìn)程會中斷,因此不要在正常運行時系統(tǒng)上做此操作。因此校驗結(jié)果并根據(jù)具體的服務(wù)需要,決定是否要進(jìn)行調(diào)優(yōu)。 原文鏈接:http://www.cubrid.org/blog/dev-platform/how-to-tune-java-garbage-collecti...

    leap_frog 評論0 收藏0
  • JVM詳解1.Java內(nèi)存模型

    摘要:編譯參見深入理解虛擬機(jī)節(jié)走進(jìn)之一自己編譯源碼內(nèi)存模型運行時數(shù)據(jù)區(qū)域根據(jù)虛擬機(jī)規(guī)范的規(guī)定,的內(nèi)存包括以下幾個運運行時數(shù)據(jù)區(qū)域程序計數(shù)器程序計數(shù)器是一塊較小的內(nèi)存空間,他可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器。 點擊進(jìn)入我的博客 1.1 基礎(chǔ)知識 1.1.1 一些基本概念 JDK(Java Development Kit):Java語言、Java虛擬機(jī)、Java API類庫JRE(...

    TANKING 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<