AOSP CachedAppOptimizer:應用進程長期處于 Cached 狀態的內存壓縮和凍結優化管控
凍結和內存壓縮兩個功能獨立觸發,可以單獨觸發也可以組合觸發,默認順序:先壓縮,后凍結
public class OomAdjuster {
? ? protected boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now,{
? ? ? ? ...
? ? ? ? if (state.getCurAdj() != state.getSetAdj()) {
? ? ? ? ? ? //內存壓縮
? ? ? ? ? ? mCachedAppOptimizer.onOomAdjustChanged(state.getSetAdj(), state.getCurAdj(), app);
? ? ? ? }
? ? ? ? ...
? ? ? ? updateAppFreezeStateLSP(app, oomAdjReson, false);
? ? ? ? ...
? ? }
? ? void updateAppFreezeStateLSP(ProcessRecord app, @OomAdjReason int oomAdjReason,
...
? ? ? ? if (state.getCurAdj() >= FREEZER_CUTOFF_ADJ && !opt.isFreezeExempt() ? && !opt.shouldNotFreeze()) { ?
? ? ? ? ? ? // 異步凍結
? ?freezeAppAsyncLSP(app); // 調用 mCachedAppOptimizer.freezeProcess
}
? ? ? ? ...
}
public final class CachedAppOptimizer {
? ? @GuardedBy({"mService", "mProcLock"})
? ? void onOomAdjustChanged(int oldAdj, int newAdj, ProcessRecord app) {
? ? ? ? if (useCompaction()) {
? ? ? ? ? ? // Cancel any currently executing compactions
? ? ? ? ? ? // if the process moved out of cached state
? ? ? ? ? ? if (newAdj < oldAdj && newAdj < ProcessList.CACHED_APP_MIN_ADJ) {
? ? ? ? ? ? ? ? cancelCompactionForProcess(app, CancelCompactReason.OOM_IMPROVEMENT);
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? void onProcessFrozen(ProcessRecord frozenProc) {
? ? ? ? if (useCompaction()) {
? ? ? ? ? ? synchronized (mProcLock) {
? ? ? ? ? ? ? ? compactApp(frozenProc, CompactProfile.FULL, CompactSource.APP, false);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? frozenProc.onProcessFrozen();
? ? }
}
行為模式 | 觸發條件 | 資源壓力/策略 |
只凍結,不壓縮 | -state.getCurAdj() >= FREEZER_CUTOFF_ADJ -!opt.isFrozen() -!opt.shouldNotFreeze() | - 內存充足但需省電 - 進程優先級未觸發壓縮閾值 newAdj ≥ CACHED_APP_MIN_ADJ |
同時凍結+壓縮 | -oom_adj ≥ CACHED_APP_MIN_ADJ - 進程未被取消壓縮(!mPendingCompactionProcesses.contains(app) | - 內存碎片化嚴重(compact_full_rss_throttle_kb) - 低電量模式 |
只壓縮,不凍結 | -oom_adj ≥ CACHED_APP_MIN_ADJ -opt.isFreezeExempt()或 state.getCurAdj() < FREEZER_CUTOFF_ADJ | - CPU負載低 - 進程標記為不可凍結(如persistent) |
不凍結也不壓縮 | -oom_adj < CACHED_APP_MIN_ADJ - 或opt.shouldNotFreeze() - 或壓縮被取消(CancelCompactReason) |
凍結(Freezer)策略與壓縮交互
凍結(Freezer)和壓縮(Compaction)的執行順序是明確且不可隨意調換的。默認順序:先壓縮,后凍結,凍結依賴壓縮完成
凍結會將進程的內存頁標記為不可移動(PG_dontdump),若先凍結再壓縮,內核會跳過凍結進程的內存頁,導致壓縮失效。
場景 | 凍結狀態 | 壓縮狀態 | 說明 |
進程剛進入緩存 | ? 未凍結 | ? 可壓縮 | 優先觸發FULL壓縮,再根據資源壓力決定是否凍結。 |
進程長期緩存 | ? 已凍結 | ? 不壓縮 | 凍結后內存頁標記為不可移動(PG_dontdump),避免壓縮開銷。 |
進程解凍后 | ? 解凍 | ? 可壓縮 | 若仍滿足緩存條件,可能觸發新一輪壓縮(需冷卻時間)。 |