本文基于 AOSP android-8.1.0_r31
Android Low memory killer 已經(jīng)分析了低殺的情況傻谁。低殺意味著緩存的數(shù)量過多了老厌,或者內(nèi)存已經(jīng)出現(xiàn)了不足的情況温算。盡管經(jīng)過了低殺了襟锐,系統(tǒng)的內(nèi)存也可能隨時都會出現(xiàn)緊張的情況蒲列,那么此時比較好的作法就是通知當(dāng)前沒有被殺掉的進(jìn)程忽媒,讓這些進(jìn)程主動去釋放一些內(nèi)存争拐。否則下次進(jìn)行低殺的時候,這些進(jìn)程就可能會被殺掉猾浦。這樣的話陆错,這些進(jìn)程為了自保,也會被動的愿意去釋放一些不用的內(nèi)存金赦。這樣一來系統(tǒng)內(nèi)存就充足了音瓷,就不會低殺了。
所以一個App開發(fā)者是很有必要去實現(xiàn) onTrimMemory
Memory Trim發(fā)生的時機
Android Low memory killer 中 updateOomAdjLocked
在計算每個進(jìn)程的adj, 以及可能的低殺后夹抗,就會試著去通知app trim memory.
// Now determine the memory trimming level of background processes.
// Unfortunately we need to start at the back of the list to do this
// properly. We only do this if the number of background apps we
// are managing to keep around is less than half the maximum we desire;
// if we are keeping a good number around, we'll let them use whatever
// memory they want.
final int numCachedAndEmpty = numCached + numEmpty;
int memFactor;
if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
&& numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
}
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
}
計算當(dāng)前內(nèi)存因子绳慎,也就是當(dāng)前內(nèi)存的緊張程度。值越大漠烧,內(nèi)存越緊張杏愤。
這里特別注意,內(nèi)存因子是根據(jù)cached/empty進(jìn)程的數(shù)量來計算的已脓。
變量 | 默認(rèn)值 |
---|---|
CUR_TRIM_CACHED_PROCESSES | 5 |
CUR_TRIM_EMPTY_PROCESSES | 8 |
TRIM_CRITICAL_THRESHOLD | 3 |
TRIM_LOW_THRESHOLD | 5 |
也就是說
cached和empty總數(shù) | 系統(tǒng)內(nèi)存狀態(tài) |
---|---|
0 ~ 3 | critical |
4, 5 | low |
6 ~ 13 | moderate |
> 13 | normal |
這些數(shù)值好像與我們平時理解的剛好相反珊楼,比如當(dāng)cached/empty的進(jìn)程更多時,那此時系統(tǒng)不應(yīng)該內(nèi)存更緊張么度液?因為這些緩存的進(jìn)程并沒有完全釋放完內(nèi)存呀厕宗。
但是此時內(nèi)存因子確為normal狀態(tài)画舌, 是不是很奇怪。參考https://www.cnblogs.com/tiger-wang-ms/p/6445213.html
為什么能根據(jù)后臺進(jìn)程和空進(jìn)程數(shù)量來判斷出系統(tǒng)的內(nèi)存等級呢已慢?因為根據(jù)之前的分析可以知道曲聂,Android系統(tǒng)在后臺進(jìn)程和空進(jìn)程不超過數(shù)量上限時總是盡可能多的保留后臺進(jìn)程和空進(jìn)程,這樣用戶便可再再次啟動這些進(jìn)程時減少啟動時間從而提高了用戶體驗佑惠;而lowmemeorykiller的機制又會在系統(tǒng)可用內(nèi)存不足時殺死這些進(jìn)程朋腋,所以在后臺進(jìn)程和空進(jìn)程數(shù)量少于一定數(shù)量時,便表示了系統(tǒng)以及觸發(fā)了lowmemrorykiller的機制膜楷,而剩余的后臺進(jìn)程和空進(jìn)程的數(shù)量則正好體現(xiàn)了Lowmemroykiller殺進(jìn)程的程度旭咽,即表示當(dāng)前系統(tǒng)內(nèi)存的緊張程度。
那這里有個問題把将,如果系統(tǒng)剛開機時轻专,用戶并沒有操作過其它app, 那么此時系統(tǒng)的cached/empty的進(jìn)程豈不是為0,那這時如果啟動一個app, 然后它被緩存后察蹲,此時它豈不是要提示critical系統(tǒng)內(nèi)存请垛??洽议?
這個當(dāng)然不是宗收,系統(tǒng)在啟動時,會啟動很多非persistent的系統(tǒng)應(yīng)用亚兄,如email/calendar/dialer等等混稽,而這些此時用戶并沒有使用過,所以它們大多數(shù)是empty的進(jìn)程审胚,在PIXEL手機測試時匈勋,發(fā)現(xiàn)有10多個empty進(jìn)程,所以系統(tǒng)一開機時膳叨,并不會提示critical系統(tǒng)內(nèi)存洽洁。
// We always allow the memory level to go up (better). We only allow it to go
// down if we are in a state where that is allowed, *and* the total number of processes
// has gone down since last time.
if (memFactor > mLastMemoryLevel) {
if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
memFactor = mLastMemoryLevel;
}
}
決定是否對內(nèi)存因子降級
mLastMemoryLevel = memFactor;
mLastNumProcesses = mLruProcesses.size();
boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now);
final int trackerMemFactor = mProcessStats.getMemFactorLocked();
保存一些變量。
下面的是對內(nèi)存因子為critical, moderate, 以及l(fā)ow的情況下進(jìn)行memory trim.
if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
if (mLowRamStartTime == 0) {
mLowRamStartTime = now;
}
int step = 0;
int fgTrimLevel;
switch (memFactor) {
case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
break;
case ProcessStats.ADJ_MEM_FACTOR_LOW:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
break;
default:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
break;
}
將memFactor轉(zhuǎn)換成ComponentCallbacks2中定義的變量名
int factor = numTrimming/3;
int minFactor = 2;
if (mHomeProcess != null) minFactor++;
if (mPreviousProcess != null) minFactor++;
if (factor < minFactor) factor = minFactor;
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
計算factor, 這個是步進(jìn)的factor, curLevel,從最高等級開始
numTrimming是指那些比PROCESS_STATE_HOME不重要的進(jìn)程
for (int i=N-1; i>=0; i--) { //從最近最常使用的進(jìn)程開始菲嘴。
ProcessRecord app = mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
setProcessTrackerStateLocked(app, trackerMemFactor, now);
app.procStateChanged = false;
}
//那些重要性低于ActivityManager.PROCESS_STATE_HOME的進(jìn)程的處理饿自,
//包括B-Service進(jìn)程、cachedProcess和emptyProcess
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
if (app.trimMemoryLevel < curLevel && app.thread != null) {
try {
app.thread.scheduleTrimMemory(curLevel);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = curLevel;
step++;
//前面的那個步長龄坪,trim等級更高昭雌,每到一個步長,trim等級都下降一個level.
if (step >= factor) {
step = 0;
switch (curLevel) {
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
break;
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
break;
}
}
//heavy 的進(jìn)程
} else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
&& app.thread != null) {
try {
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
} else {
//important健田,以及那些短暫的, backup的進(jìn)程
if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
|| app.systemNoUi) && app.pendingUiClean) {
final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
if (app.trimMemoryLevel < level && app.thread != null) {
try {
app.thread.scheduleTrimMemory(level);
} catch (RemoteException e) {
}
}
app.pendingUiClean = false;
}
//其它的一些進(jìn)程
if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
app.thread.scheduleTrimMemory(fgTrimLevel);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = fgTrimLevel;
}
}
下面是對系統(tǒng)內(nèi)存為正常的情況下, 對優(yōu)先級低于PROCESS_STATE_IMPORTANT_BACKGROUND烛卧,最多給予TRIM_MEMORY_UI_HIDDEN的提示
} else {
if (mLowRamStartTime != 0) {
mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
mLowRamStartTime = 0;
}
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (allChanged || app.procStateChanged) {
setProcessTrackerStateLocked(app, trackerMemFactor, now);
app.procStateChanged = false;
}
if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
|| app.systemNoUi) && app.pendingUiClean) {
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
&& app.thread != null) {
try {
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
} catch (RemoteException e) {
}
}
app.pendingUiClean = false;
}
app.trimMemoryLevel = 0;
}
}
當(dāng)updateOomAdjLocked在killed超過limit的CACHED/EMPTY進(jìn)程后,接下來會對剩下的CACHED/EMPTY嘗試去做 Memory Trim的動作妓局。也就是觸發(fā)對應(yīng)進(jìn)程的scheduleTrimMemory唱星,試著讓進(jìn)程去釋放一些內(nèi)存雳旅。