1.1Android的官方文檔主要提供了四種優(yōu)化策略
1.Disable JIT映皆,運(yùn)行時(shí)動(dòng)態(tài)編譯,JIT編譯出來(lái)的本地代碼體積通常比較大,按官網(wǎng)的說(shuō)法己肮,運(yùn)行事的系統(tǒng)大概多花費(fèi)3-6m內(nèi)存骂际,一個(gè)大型app一般多花費(fèi)1m,平均而言,一個(gè)app多占用100K and 200K bytes
2.lowmemorykiller纽窟,在達(dá)到某個(gè)內(nèi)存門(mén)限的情況下去選擇進(jìn)程刪除來(lái)釋放內(nèi)存尘盼,通過(guò)/sys/module/lowmemorykiller/parameters/minfree配置相關(guān)參數(shù)來(lái)殺掉次要進(jìn)程憨愉,每個(gè)應(yīng)用都會(huì)有一個(gè)進(jìn)程的優(yōu)先級(jí)。通過(guò)殺次要進(jìn)程來(lái)釋放內(nèi)存卿捎。
3.KSM (Kernel samepage merging)配紫,內(nèi)核同頁(yè)合并,這特性允許更有效的處理內(nèi)存午阵,系統(tǒng)運(yùn)行的越久越會(huì)節(jié)省內(nèi)存躺孝,由于ksm是在后臺(tái)運(yùn)行的后臺(tái)線程,在使用ksm會(huì)造成cpu性能損耗和消耗更多的電池底桂,根據(jù)網(wǎng)上的說(shuō)法是10%植袍,目前沒(méi)有相關(guān)的測(cè)試手段還沒(méi)有測(cè)試。
4.Swap to zRAM戚啥,zRAM 因?yàn)樾枰_(kāi)辟一小塊內(nèi)存作為 compressed block 使用奋单,讓系統(tǒng)當(dāng)作虛擬內(nèi)存來(lái)使用。傳統(tǒng)的虛擬內(nèi)存是存放在磁盤(pán)上的猫十,而zRAM存在內(nèi)存里览濒,并會(huì)進(jìn)行壓縮,以達(dá)到“增加ram容量”的目的 拖云。這樣的虛擬內(nèi)存訪問(wèn)速度可以提高很多贷笛,內(nèi)存利用率也會(huì)大幅提高。目前我配的內(nèi)存的壓縮比是50%宙项,文檔介紹是在30%-50%乏苦,最優(yōu)值需要大量的測(cè)試,在性能和內(nèi)存之間找到一個(gè)平衡尤筐。
1.2系統(tǒng)gpu優(yōu)化
優(yōu)化GPU驅(qū)動(dòng)汇荐,復(fù)用ION內(nèi)存,解決游戲不能運(yùn)行 問(wèn)題盆繁,ION占用80M內(nèi)存是不能避免的掀淘,但可以修改GPU驅(qū)動(dòng),讓游戲可以使用ION內(nèi)存油昂,從而解決游戲因?yàn)閮?nèi)存不足閃退問(wèn)題革娄。
mali400驅(qū)動(dòng)修改如下:
1倾贰,mali已分配頁(yè)數(shù)超過(guò)mali最大可分配頁(yè)數(shù)一定比例
2,當(dāng)前進(jìn)程的rss size超過(guò)一定比例
3拦惋,當(dāng)前進(jìn)程的adj=0
當(dāng)以上三者同時(shí)滿足的情況下匆浙,mali將優(yōu)先從ion獲取內(nèi)存,如果ion沒(méi)有足夠內(nèi)存厕妖,則轉(zhuǎn)向os memory繼續(xù)分配物理頁(yè)首尼,如果此時(shí)os memory無(wú)足夠內(nèi)存可供分配,則認(rèn)為當(dāng)前系統(tǒng)內(nèi)存已飽和叹放。
2在系統(tǒng)中實(shí)現(xiàn)
2.1Disable JIT:
在系統(tǒng)的makefile文件中加入下面一行
PRODUCT_PROPERTY_OVERRIDES += dalvik.vm.jit.codecachesize=0
設(shè)置為0之后會(huì)節(jié)省內(nèi)存饰恕,但是會(huì)導(dǎo)致虛擬機(jī)的性能下降,在跑antutu發(fā)現(xiàn)設(shè)置0導(dǎo)致跑分變低井仰,設(shè)置為200k基本沒(méi)有影響。
2.2內(nèi)核進(jìn)程kswapd管理內(nèi)存
Unix系統(tǒng)能夠利用磁盤(pán)存放超過(guò)物理內(nèi)存容量的部分內(nèi)存內(nèi)容破加,稱作交換空間(swap space)俱恶。Kswapd就是用來(lái)處理頁(yè)面的交換,它可以在內(nèi)存不足時(shí)范舀,將一些進(jìn)程的頁(yè)面交換到swap空間之中合是。在 kswapd 中,有2 個(gè)閥值, pages_hige和pages_low,當(dāng)空閑內(nèi)存頁(yè)的數(shù)量低于 pages_low 的時(shí)候, kswapd進(jìn)程就會(huì)掃描內(nèi)存并且每次釋放出32 個(gè)free pages,直到 free page 的數(shù)量到達(dá)pages_high.
kswapd和pages_low锭环、pages_high這兩個(gè)參數(shù)的設(shè)置值很有關(guān)系:
l 增加pages_low的值聪全,可以使得kswapd不要等到內(nèi)存消耗得太厲害再開(kāi)始釋放頁(yè)面,這樣似乎可以增加內(nèi)存成功分配的幾率辅辩。
l 增加pages_high的值难礼,可以使得kswapd每次多釋放一些內(nèi)存,這樣對(duì)于大型應(yīng)用軟件的使用玫锋,可以減少調(diào)用kswapd進(jìn)行內(nèi)存釋放的次數(shù)蛾茉。不過(guò)這樣做帶來(lái)的缺陷是,如果系統(tǒng)始終釋放不出pages_high這樣多的內(nèi)存撩鹿,那么是否會(huì)陷入一種死循環(huán)谦炬,或者過(guò)多地調(diào)用OOM函數(shù)?因此节沦,如果pages_high設(shè)置得比較高键思,那么需要一種平衡機(jī)制。
pages_low甫贯、pages_high的值是在函數(shù)void setup_per_zone_wmarks(void)中進(jìn)行設(shè)置的吼鳞,這個(gè)函數(shù)位于kernel/mm/page_alloc.c之中。
Pagas_low的值可以在framework config.xml設(shè)置
<integer name="config_extraFreeKbytesAbsolute>-1</integer>直接賦值
<integer name="config_extraFreeKbytesAdjust">0</integer>在默認(rèn)值(3個(gè)全屏大谢癫)上加上這個(gè)值
2.3Low Memory Killer
Android中赖条,進(jìn)程的生命周期都是由系統(tǒng)控制的失乾,即使用戶關(guān)掉了程序,進(jìn)程依然是存在于內(nèi)存之中纬乍。這樣設(shè)計(jì)的目的是為了下次能快速啟動(dòng)碱茁。當(dāng)然,隨著系統(tǒng)運(yùn)行時(shí)間的增長(zhǎng)仿贬,內(nèi)存會(huì)越來(lái)越少纽竣。
Android 采用特殊的內(nèi)存管理機(jī)制,Android Kernel會(huì)定時(shí)執(zhí)行一次檢查茧泪,殺死一些進(jìn)程蜓氨,釋放掉內(nèi)存。Low Memory Killer是在標(biāo)準(zhǔn)linux kernel的OOM基礎(chǔ)上修改而來(lái)的一種內(nèi)存管理機(jī)制队伟,當(dāng)系統(tǒng)內(nèi)存不足時(shí)穴吹,殺死Bad進(jìn)程釋放其內(nèi)存。
Low Memory Killer的源代碼在drivers/staging/android/lowmemorykiller.c中嗜侮,它是通過(guò)注冊(cè)Cache Shrinker來(lái)實(shí)現(xiàn)的港令。Cache Shrinker是標(biāo)準(zhǔn)linux kernel回收內(nèi)存頁(yè)面的一種機(jī)制,它由內(nèi)核線程kswapd監(jiān)控锈颗,當(dāng)空閑內(nèi)存頁(yè)面不足時(shí)顷霹,kswapd會(huì)調(diào)用注冊(cè)的Shrinker回調(diào)函數(shù),來(lái)回收內(nèi)存頁(yè)面击吱。
(1)每個(gè)程序都會(huì)有一個(gè)oom_adj值淋淀,這個(gè)值越小,程序越重要覆醇,被殺的可能性越低朵纷。
(2)進(jìn)程的內(nèi)存,通過(guò)get_mm_rss獲取叫乌,在相同的oom_adj下柴罐,內(nèi)存大的,優(yōu)先被殺憨奸。
(3)Android提供了兩個(gè)數(shù)組革屠,一個(gè)lowmem_adj,一個(gè)lowmem_minfree排宰。前者存放著oom_adj的閥值似芝,后者存放著minfree的警戒值,以page為單位(4K)板甘。如下圖:
以上就是兩個(gè)閥值党瓮。
<integer name="config_lowMemoryKillerMinFreeKbytesAbsolute">-1</integer>
<integer name="config_lowMemoryKillerMinFreeKbytesAdjust">0</integer>
以下是該閥值計(jì)算公式:
mOomMinFree[i] += (long)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]);
2.4開(kāi)啟KSM
開(kāi)啟KSM,要打開(kāi)驅(qū)動(dòng)KSM配置CONFIG_KSM,然后加入下面的幾行在你的init..rc文件中:
write /sys/kernel/mm/ksm/pages_to_scan 100
write /sys/kernel/mm/ksm/sleep_millisecs 500
write /sys/kernel/mm/ksm/run 1
驅(qū)動(dòng)配置Kernel Features --->[*] Enable KSM for page merging
查看是否有效在控制臺(tái)輸入ksminfo -a
2.5開(kāi)啟ZRAM
ZRAM是linux的一種內(nèi)存優(yōu)化技術(shù)盐类,基本工作原理是:通過(guò)劃定一片區(qū)域寞奸,將壓縮過(guò)后的硬盤(pán)數(shù)據(jù)放入該區(qū)域呛谜,以實(shí)現(xiàn)高速讀取。
ZRAM的實(shí)現(xiàn)方式有兩種:
1枪萄、實(shí)現(xiàn)內(nèi)存壓縮隐岛,以達(dá)到“增加ram容量”的目的;
2瓷翻、壓縮區(qū)域數(shù)據(jù)聚凹,以實(shí)現(xiàn)“快速讀取”的目的。
在系統(tǒng)的fstab.xxboard下配置:
/dev/block/zram0 none swap defaults zramsize=,swapprio=<swap partition priority>
Zram size的值是強(qiáng)制配置的齐帚,表示要多少未壓縮的內(nèi)存預(yù)留給zram的妒牙,大概是30%-50%,這個(gè)需要觀察的
write /proc/sys/vm/page-cluster 0
如果想要一次寫(xiě)入一頁(yè)到swap區(qū)对妄,在init.rc加入該行湘今,0表示1頁(yè),1表示2頁(yè)剪菱,2表示4頁(yè)象浑。
在`mount_all /fstab.X`后面加入該行:?swapon_all /fstab.xxboard
驅(qū)動(dòng)配置
General setup --->
[*] Control Group support --->
[*] Memory Resource Controller for Control Groups
[*] Memory Resource Controller Swap Extension
[*] Memory Resource Controller Swap Extension enabled by defaultDevice Drivers --->
[*] Staging drivers --->[*] Memory allocator for compressed pages
<*> Compressed RAM block device support
可以用一下的命令查看你配置是否生效:cat /sys/block/zram0/disksize
3Android低內(nèi)存接口
ActivityManager.isLowRamDevice(),用這個(gè)判斷是否是低內(nèi)存設(shè)備琅豆,在andriod自帶的系統(tǒng)應(yīng)用中,就找到settings的應(yīng)用有使用到這個(gè)接口篓吁,來(lái)決定系統(tǒng)的鎖屏界面是否可以加載widget茫因,設(shè)置ro.config.low_ram=true后為低內(nèi)存設(shè)備,該功能可以使用杖剪,就是說(shuō)低內(nèi)存沒(méi)有鎖屏界面加載widget的功能冻押。該設(shè)置是給應(yīng)用提供的接口,應(yīng)用程序確定他們是否應(yīng)該關(guān)閉特定的內(nèi)存消耗多的方法盛嘿,以便能很好地工作在低內(nèi)存設(shè)備上洛巢。
4查看系統(tǒng)優(yōu)化后的運(yùn)行狀態(tài)
通過(guò)控制臺(tái)命令dumpsys meminfo:
Total RAM: 524288 kB
Free RAM: 192308 kB (33624 cached pss + 133752 cached + 24932 free)
Used RAM: 154814 kB (132538 used pss + 5808 buffers + 324 shmem + 16144 slab)
Lost RAM: 177166 kB
ZRAM: 4 kB physical used for 0 kB in swap (262140 kB total swap)
KSM: 224 kB saved from shared 32 kB
3588 kB unshared; 77056 kB volatile
Tuning:48(large256), oom 122880 kB, restore limit 40960 kB (low-ram)
紅色表示ZRAM和KSM使用的情況,48是dalvik.vm.heapgrowthlimit=48m(每個(gè)應(yīng)用最大可分配的內(nèi)存)次兆,256是dalvik.vm.heapsize=256m(單個(gè)虛擬機(jī)可分配的最大內(nèi)存256m)稿茉。
Oom122880設(shè)置/sys/module/lowmemorykiller/parameters/minfree最后一個(gè)值,(見(jiàn)2.3)表示剩余內(nèi)存超過(guò)這個(gè)值將開(kāi)始?xì)⑺肋M(jìn)程回收內(nèi)存芥炭。
5優(yōu)化前后對(duì)比
5.1開(kāi)機(jī)后剩余內(nèi)存:
以下優(yōu)化后的meminfo是在開(kāi)機(jī)時(shí)根據(jù)dumpsys meminfo命令打印出來(lái)的漓库,上面是優(yōu)化后的,一般剩下160m左右园蝠,機(jī)器上看剩下只有120m左右渺蒿,以下可以很明顯的看到有用了zram交換4k,ksm合并相同的內(nèi)存也224kb彪薛,說(shuō)明是優(yōu)化有效果的茂装,優(yōu)化會(huì)比沒(méi)有優(yōu)化省幾m的內(nèi)存空間怠蹂。
Total RAM: 524288 kB
Free RAM: 192308 kB (33624 cached pss + 133752 cached + 24932 free)
Used RAM: 154814 kB (132538 used pss + 5808 buffers + 324 shmem + 16144 slab)
Lost RAM: 177166 kB
ZRAM: 4 kB physical used for 0 kB in swap (262140 kB total swap)
KSM: 224 kB saved from shared 32 kB
3588 kB unshared; 77056 kB volatile
Tuning: 64 (large 384), oom 122880 kB, restore limit 40960 kB (low-ram)
===========================================================================Total RAM: 524288 kB
Free RAM: 172751 kB (32023 cached pss + 112916 cached + 27812 free)
Used RAM: 163733 kB (141609 used pss + 7528 buffers + 336 shmem + 14260 slab)
Lost RAM: 187804 kB
Tuning: 64 (large 384), oom 122880 kB, restore limit 40960 kB (high-end-gfx)
開(kāi)機(jī)后剩余內(nèi)存對(duì)比,這些數(shù)值隨著使用時(shí)間加長(zhǎng)得到優(yōu)化更多
5.2經(jīng)常使用的游戲內(nèi)存使用分析
以下是兩臺(tái)機(jī)器跑捕魚(yú)拷機(jī)1個(gè)晚上后捕魚(yú)占用的內(nèi)存少态,這個(gè)應(yīng)用會(huì)節(jié)省4m左右城侧。對(duì)比發(fā)現(xiàn)private clean,private dirty差別比較大
Private clean况增,包括該進(jìn)程私有的干凈的內(nèi)存赞庶。包括該進(jìn)程獨(dú)自使用的so和進(jìn)程的二進(jìn)制代碼段。
Private dirty澳骤,表示該進(jìn)程私有的不跟disk數(shù)據(jù)一致的內(nèi)存段堆(heap)歧强,棧(stack),bss段为肮。
說(shuō)明優(yōu)化后在該應(yīng)用的私有的內(nèi)存占用有所減低摊册,從而減低內(nèi)存的消耗
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------------------------
start ? end ? virtual ? ? ? ? ? ? ? ? ? ? ? ?shared ? ? shared ? ?private ? ?private
addr ?addr ? size ? RSS ? ?PSS ? ? clean ? ? ? ?dirty ? ? ? clean ? ? ? dirty ? ? object
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------------------------
? ? ? ? ? ? ? ?854420 49648 ?31572 ?11108 ? ? ? 9212 ? ? ?4276 ? ? ?25052 ? ? ?TOTAL
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------------------------
start? end? virtual? ? ? ? ? ? ? ? ? ? ? ? shared? ? shared? ? private? ? private
addr? addr? size ? ?RSS? ? PSS ? ? clean? ? ? ? dirty? ? ? clean ? ? ? dirty ? ? object
-------- -------- -------- -------- -------- -------- -------- -------- -------- ------------------------------
? ? ? ? ? ? ? ? 849380 48084 28717 12504 ? ?9148 ? ? ? ?5420 ? ?21012 ? ? ?TOTAL
? ? ?