Android 4.4以上 低內(nèi)存優(yōu)化說(shuō)明

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)存門限的情況下去選擇進(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%,目前沒有相關(guān)的測(cè)試手段還沒有測(cè)試。

4.Swap to zRAM,zRAM 因?yàn)樾枰_辟一小塊內(nèi)存作為 compressed block 使用,讓系統(tǒng)當(dāng)作虛擬內(nèi)存來(lái)使用。傳統(tǒng)的虛擬內(nèi)存是存放在磁盤上的,而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沒有足夠內(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基本沒有影響。

2.2內(nèi)核進(jìn)程kswapd管理內(nèi)存

Unix系統(tǒng)能夠利用磁盤存放超過(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)存消耗得太厲害再開始釋放頁(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開啟KSM

開啟KSM,要打開驅(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開啟ZRAM

ZRAM是linux的一種內(nèi)存優(yōu)化技術(shù),基本工作原理是:通過(guò)劃定一片區(qū)域,將壓縮過(guò)后的硬盤數(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

如果想要一次寫入一頁(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)存沒有鎖屏界面加載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è)值,(見2.3)表示剩余內(nèi)存超過(guò)這個(gè)值將開始?xì)⑺肋M(jìn)程回收內(nèi)存。

5優(yōu)化前后對(duì)比

5.1開機(jī)后剩余內(nèi)存:

以下優(yōu)化后的meminfo是在開機(jī)時(shí)根據(jù)dumpsys meminfo命令打印出來(lái)的,上面是優(yōu)化后的,一般剩下160m左右,機(jī)器上看剩下只有120m左右,以下可以很明顯的看到有用了zram交換4k,ksm合并相同的內(nèi)存也224kb,說(shuō)明是優(yōu)化有效果的,優(yōu)化會(huì)比沒有優(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)

開機(jī)后剩余內(nèi)存對(duì)比,這些數(shù)值隨著使用時(shí)間加長(zhǎng)得到優(yōu)化更多

? ? ? ?

5.2經(jīng)常使用的游戲內(nèi)存使用分析

以下是兩臺(tái)機(jī)器跑捕魚拷機(jī)1個(gè)晚上后捕魚占用的內(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

? ? ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • HereAndroid的內(nèi)存優(yōu)化是性能優(yōu)化中很重要的一部分,而避免OOM又是內(nèi)存優(yōu)化中比較核心的一點(diǎn)。這是一篇關(guān)于...
    HarryXR閱讀 3,915評(píng)論 1 24
  • 本文轉(zhuǎn)載來(lái)源 http://www.csdn.net/article/2015-09-18/2825737/1 (...
    yoosir閱讀 1,211評(píng)論 0 5
  • 一、概述 1.1 內(nèi)存指標(biāo)概念 Item 全稱 含義 等價(jià) USSUnique Set Size物理內(nèi)存進(jìn)程獨(dú)占的...
    tiger桂閱讀 2,785評(píng)論 0 0
  • 之前在Python的專題中看到了很多大佬都在說(shuō)Python可以做為膠水語(yǔ)言,一直不理解。昨晚在網(wǎng)上看到一篇文章,詳...
    肥宅_Sean閱讀 11,159評(píng)論 2 3
  • 中考的風(fēng)波過(guò)去,上高中了,還留在我身邊的男同學(xué)就只有他――“大黑”。于是,初中就要好的他,在成為我男閨的道路上一...
    70255bf615a6閱讀 283評(píng)論 0 0

友情鏈接更多精彩內(nèi)容