Allow CacheOomRanker to rerank when there's <8 processes in the cache. am: 850b432ade
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15684472 Change-Id: I036ba49a10c86d1f08b1fb7a222ee07ed5324ad6
This commit is contained in:
@@ -38,16 +38,25 @@ public class CacheOomRanker {
|
||||
private static final boolean DEFAULT_USE_OOM_RE_RANKING = false;
|
||||
@VisibleForTesting
|
||||
static final String KEY_OOM_RE_RANKING_NUMBER_TO_RE_RANK = "oom_re_ranking_number_to_re_rank";
|
||||
@VisibleForTesting static final int DEFAULT_OOM_RE_RANKING_NUMBER_TO_RE_RANK = 8;
|
||||
@VisibleForTesting
|
||||
static final int DEFAULT_OOM_RE_RANKING_NUMBER_TO_RE_RANK = 8;
|
||||
@VisibleForTesting
|
||||
static final String KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS =
|
||||
"oom_re_ranking_preserve_top_n_apps";
|
||||
@VisibleForTesting
|
||||
static final int DEFAULT_PRESERVE_TOP_N_APPS = 3;
|
||||
@VisibleForTesting
|
||||
static final String KEY_OOM_RE_RANKING_LRU_WEIGHT = "oom_re_ranking_lru_weight";
|
||||
@VisibleForTesting static final float DEFAULT_OOM_RE_RANKING_LRU_WEIGHT = 0.35f;
|
||||
@VisibleForTesting
|
||||
static final float DEFAULT_OOM_RE_RANKING_LRU_WEIGHT = 0.35f;
|
||||
@VisibleForTesting
|
||||
static final String KEY_OOM_RE_RANKING_USES_WEIGHT = "oom_re_ranking_uses_weight";
|
||||
@VisibleForTesting static final float DEFAULT_OOM_RE_RANKING_USES_WEIGHT = 0.5f;
|
||||
@VisibleForTesting
|
||||
static final float DEFAULT_OOM_RE_RANKING_USES_WEIGHT = 0.5f;
|
||||
@VisibleForTesting
|
||||
static final String KEY_OOM_RE_RANKING_RSS_WEIGHT = "oom_re_ranking_rss_weight";
|
||||
@VisibleForTesting static final float DEFAULT_OOM_RE_RANKING_RSS_WEIGHT = 0.15f;
|
||||
@VisibleForTesting
|
||||
static final float DEFAULT_OOM_RE_RANKING_RSS_WEIGHT = 0.15f;
|
||||
|
||||
private static final Comparator<RankedProcessRecord> SCORED_PROCESS_RECORD_COMPARATOR =
|
||||
new ScoreComparator();
|
||||
@@ -66,15 +75,21 @@ public class CacheOomRanker {
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private boolean mUseOomReRanking = DEFAULT_USE_OOM_RE_RANKING;
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting
|
||||
int mPreserveTopNApps = DEFAULT_PRESERVE_TOP_N_APPS;
|
||||
// Weight to apply to the LRU ordering.
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting float mLruWeight = DEFAULT_OOM_RE_RANKING_LRU_WEIGHT;
|
||||
@VisibleForTesting
|
||||
float mLruWeight = DEFAULT_OOM_RE_RANKING_LRU_WEIGHT;
|
||||
// Weight to apply to the ordering by number of times the process has been added to the cache.
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting float mUsesWeight = DEFAULT_OOM_RE_RANKING_USES_WEIGHT;
|
||||
@VisibleForTesting
|
||||
float mUsesWeight = DEFAULT_OOM_RE_RANKING_USES_WEIGHT;
|
||||
// Weight to apply to the ordering by RSS used by the processes.
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting float mRssWeight = DEFAULT_OOM_RE_RANKING_RSS_WEIGHT;
|
||||
@VisibleForTesting
|
||||
float mRssWeight = DEFAULT_OOM_RE_RANKING_RSS_WEIGHT;
|
||||
|
||||
// Positions to replace in the lru list.
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@@ -93,6 +108,8 @@ public class CacheOomRanker {
|
||||
updateUseOomReranking();
|
||||
} else if (KEY_OOM_RE_RANKING_NUMBER_TO_RE_RANK.equals(name)) {
|
||||
updateNumberToReRank();
|
||||
} else if (KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS.equals(name)) {
|
||||
updatePreserveTopNApps();
|
||||
} else if (KEY_OOM_RE_RANKING_LRU_WEIGHT.equals(name)) {
|
||||
updateLruWeight();
|
||||
} else if (KEY_OOM_RE_RANKING_USES_WEIGHT.equals(name)) {
|
||||
@@ -159,6 +176,19 @@ public class CacheOomRanker {
|
||||
return mScoredProcessRecords == null ? 0 : mScoredProcessRecords.length;
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updatePreserveTopNApps() {
|
||||
int preserveTopNApps = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS, DEFAULT_PRESERVE_TOP_N_APPS);
|
||||
if (preserveTopNApps < 0) {
|
||||
Slog.w(OomAdjuster.TAG,
|
||||
"Found negative value for preserveTopNApps, setting to default: "
|
||||
+ preserveTopNApps);
|
||||
preserveTopNApps = DEFAULT_PRESERVE_TOP_N_APPS;
|
||||
}
|
||||
mPreserveTopNApps = preserveTopNApps;
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateLruWeight() {
|
||||
mLruWeight = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
@@ -183,6 +213,33 @@ public class CacheOomRanker {
|
||||
*/
|
||||
@GuardedBy({"mService", "mProcLock"})
|
||||
void reRankLruCachedAppsLSP(ArrayList<ProcessRecord> lruList, int lruProcessServiceStart) {
|
||||
// The lruList is a list of processes ordered by how recently they were used. The
|
||||
// least-recently-used apps are at the beginning of the list. We keep track of two
|
||||
// indices in the lruList:
|
||||
//
|
||||
// getNumberToReRank=5, preserveTopNApps=3, lruProcessServiceStart=7,
|
||||
// lruList=
|
||||
// 0: app A ^
|
||||
// 1: app B | These apps are re-ranked, as they are the first five apps (see
|
||||
// 2: app C | getNumberToReRank), excluding...
|
||||
// 3: app D v
|
||||
// 4: app E ^
|
||||
// 5: app F | The three most-recently-used apps in the cache (see preserveTopNApps).
|
||||
// 6: app G v
|
||||
// 7: service A ^
|
||||
// 8: service B | Everything beyond lruProcessServiceStart is ignored, as these aren't
|
||||
// 9: service C | apps.
|
||||
// 10: activity A |
|
||||
// ... |
|
||||
//
|
||||
// `numProcessesEvaluated` moves across the apps (indices 0-6) or until we've found enough
|
||||
// apps to re-rank, and made sure none of them are in the top `preserveTopNApps` apps.
|
||||
// Re-ranked apps are copied into `scoredProcessRecords`, where the re-ranking calculation
|
||||
// happens.
|
||||
//
|
||||
// Note that some apps in the `lruList` can be skipped, if they don't pass
|
||||
//`appCanBeReRanked`.
|
||||
|
||||
float lruWeight;
|
||||
float usesWeight;
|
||||
float rssWeight;
|
||||
@@ -202,52 +259,67 @@ public class CacheOomRanker {
|
||||
return;
|
||||
}
|
||||
|
||||
int numProcessesEvaluated = 0;
|
||||
// Collect the least recently used processes to re-rank, only rank cached
|
||||
// processes further down the list than mLruProcessServiceStart.
|
||||
int cachedProcessPos = 0;
|
||||
for (int i = 0; i < lruProcessServiceStart
|
||||
&& cachedProcessPos < scoredProcessRecords.length; ++i) {
|
||||
ProcessRecord app = lruList.get(i);
|
||||
int numProcessesReRanked = 0;
|
||||
while (numProcessesEvaluated < lruProcessServiceStart
|
||||
&& numProcessesReRanked < scoredProcessRecords.length) {
|
||||
ProcessRecord process = lruList.get(numProcessesEvaluated);
|
||||
// Processes that will be assigned a cached oom adj score.
|
||||
if (!app.isKilledByAm() && app.getThread() != null && app.mState.getCurAdj()
|
||||
>= ProcessList.UNKNOWN_ADJ) {
|
||||
scoredProcessRecords[cachedProcessPos].proc = app;
|
||||
scoredProcessRecords[cachedProcessPos].score = 0.0f;
|
||||
lruPositions[cachedProcessPos] = i;
|
||||
++cachedProcessPos;
|
||||
if (appCanBeReRanked(process)) {
|
||||
scoredProcessRecords[numProcessesReRanked].proc = process;
|
||||
scoredProcessRecords[numProcessesReRanked].score = 0.0f;
|
||||
lruPositions[numProcessesReRanked] = numProcessesEvaluated;
|
||||
++numProcessesReRanked;
|
||||
}
|
||||
++numProcessesEvaluated;
|
||||
}
|
||||
|
||||
// TODO maybe ensure a certain number above this in the cache before re-ranking.
|
||||
if (cachedProcessPos < scoredProcessRecords.length) {
|
||||
// Ignore we don't have enough processes to worry about re-ranking.
|
||||
return;
|
||||
// Count how many apps we're not re-ranking (up to mPreserveTopNApps).
|
||||
int numProcessesNotReRanked = 0;
|
||||
while (numProcessesEvaluated < lruProcessServiceStart
|
||||
&& numProcessesNotReRanked < mPreserveTopNApps) {
|
||||
ProcessRecord process = lruList.get(numProcessesEvaluated);
|
||||
if (appCanBeReRanked(process)) {
|
||||
numProcessesNotReRanked++;
|
||||
}
|
||||
numProcessesEvaluated++;
|
||||
}
|
||||
// Exclude the top `mPreserveTopNApps` apps from re-ranking.
|
||||
if (numProcessesNotReRanked < mPreserveTopNApps) {
|
||||
numProcessesReRanked -= mPreserveTopNApps - numProcessesNotReRanked;
|
||||
if (numProcessesReRanked < 0) {
|
||||
numProcessesReRanked = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Add scores for each of the weighted features we want to rank based on.
|
||||
if (lruWeight > 0.0f) {
|
||||
// This doesn't use the LRU list ordering as after the first re-ranking
|
||||
// that will no longer be lru.
|
||||
Arrays.sort(scoredProcessRecords, LAST_ACTIVITY_TIME_COMPARATOR);
|
||||
Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked,
|
||||
LAST_ACTIVITY_TIME_COMPARATOR);
|
||||
addToScore(scoredProcessRecords, lruWeight);
|
||||
}
|
||||
if (rssWeight > 0.0f) {
|
||||
synchronized (mService.mAppProfiler.mProfilerLock) {
|
||||
Arrays.sort(scoredProcessRecords, LAST_RSS_COMPARATOR);
|
||||
Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, LAST_RSS_COMPARATOR);
|
||||
}
|
||||
addToScore(scoredProcessRecords, rssWeight);
|
||||
}
|
||||
if (usesWeight > 0.0f) {
|
||||
Arrays.sort(scoredProcessRecords, CACHE_USE_COMPARATOR);
|
||||
Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, CACHE_USE_COMPARATOR);
|
||||
addToScore(scoredProcessRecords, usesWeight);
|
||||
}
|
||||
|
||||
// Re-rank by the new combined score.
|
||||
Arrays.sort(scoredProcessRecords, SCORED_PROCESS_RECORD_COMPARATOR);
|
||||
Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked,
|
||||
SCORED_PROCESS_RECORD_COMPARATOR);
|
||||
|
||||
if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
|
||||
boolean printedHeader = false;
|
||||
for (int i = 0; i < scoredProcessRecords.length; ++i) {
|
||||
for (int i = 0; i < numProcessesReRanked; ++i) {
|
||||
if (scoredProcessRecords[i].proc.getPid()
|
||||
!= lruList.get(lruPositions[i]).getPid()) {
|
||||
if (!printedHeader) {
|
||||
@@ -260,12 +332,18 @@ public class CacheOomRanker {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < scoredProcessRecords.length; ++i) {
|
||||
for (int i = 0; i < numProcessesReRanked; ++i) {
|
||||
lruList.set(lruPositions[i], scoredProcessRecords[i].proc);
|
||||
scoredProcessRecords[i].proc = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean appCanBeReRanked(ProcessRecord process) {
|
||||
return !process.isKilledByAm()
|
||||
&& process.getThread() != null
|
||||
&& process.mState.getCurAdj() >= ProcessList.UNKNOWN_ADJ;
|
||||
}
|
||||
|
||||
private static void addToScore(RankedProcessRecord[] scores, float weight) {
|
||||
for (int i = 1; i < scores.length; ++i) {
|
||||
scores[i].score += i * weight;
|
||||
|
||||
@@ -142,6 +142,15 @@ public class CacheOomRankerTest {
|
||||
assertThat(mCacheOomRanker.getNumberToReRank())
|
||||
.isEqualTo(CacheOomRanker.DEFAULT_OOM_RE_RANKING_NUMBER_TO_RE_RANK + 2);
|
||||
|
||||
mExecutor.init();
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS,
|
||||
Integer.toString(CacheOomRanker.DEFAULT_PRESERVE_TOP_N_APPS + 1),
|
||||
false);
|
||||
mExecutor.waitForLatch();
|
||||
assertThat(mCacheOomRanker.mPreserveTopNApps)
|
||||
.isEqualTo(CacheOomRanker.DEFAULT_PRESERVE_TOP_N_APPS + 1);
|
||||
|
||||
mExecutor.init();
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_LRU_WEIGHT,
|
||||
@@ -173,6 +182,7 @@ public class CacheOomRankerTest {
|
||||
@Test
|
||||
public void reRankLruCachedApps_lruImpactsOrdering() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 5,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* usesWeight= */ 0.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */1.0f);
|
||||
@@ -211,6 +221,7 @@ public class CacheOomRankerTest {
|
||||
@Test
|
||||
public void reRankLruCachedApps_rssImpactsOrdering() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* usesWeight= */ 0.0f,
|
||||
/* pssWeight= */ 1.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -251,6 +262,7 @@ public class CacheOomRankerTest {
|
||||
@Test
|
||||
public void reRankLruCachedApps_usesImpactsOrdering() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 4,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -286,23 +298,24 @@ public class CacheOomRankerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reRankLruCachedApps_notEnoughProcesses() throws InterruptedException {
|
||||
public void reRankLruCachedApps_fewProcesses() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 4,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
|
||||
ProcessList list = new ProcessList();
|
||||
ArrayList<ProcessRecord> processList = list.getLruProcessesLSP();
|
||||
ProcessRecord unknownAdj1 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000);
|
||||
processList.add(unknownAdj1);
|
||||
ProcessRecord unknownAdj2 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
processList.add(used1000);
|
||||
ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000);
|
||||
processList.add(unknownAdj2);
|
||||
ProcessRecord unknownAdj3 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
processList.add(used2000);
|
||||
ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10);
|
||||
processList.add(unknownAdj3);
|
||||
processList.add(used10);
|
||||
ProcessRecord foregroundAdj = nextProcessRecord(ProcessList.FOREGROUND_APP_ADJ,
|
||||
NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20);
|
||||
processList.add(foregroundAdj);
|
||||
@@ -314,17 +327,156 @@ public class CacheOomRankerTest {
|
||||
processList.add(systemAdj);
|
||||
list.setLruProcessServiceStartLSP(processList.size());
|
||||
|
||||
// 6 Processes but only 3 in eligible for cache so no re-ranking.
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
|
||||
// All positions unchanged.
|
||||
assertThat(processList).containsExactly(unknownAdj1, unknownAdj2, unknownAdj3,
|
||||
// 6 processes, only 3 in eligible for cache, so only those are re-ranked.
|
||||
assertThat(processList).containsExactly(used10, used1000, used2000,
|
||||
foregroundAdj, serviceAdj, systemAdj).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reRankLruCachedApps_notEnoughNonServiceProcesses() throws InterruptedException {
|
||||
public void reRankLruCachedApps_fewNonServiceProcesses() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 4,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
|
||||
ProcessList list = new ProcessList();
|
||||
ArrayList<ProcessRecord> processList = list.getLruProcessesLSP();
|
||||
ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000);
|
||||
processList.add(used1000);
|
||||
ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000);
|
||||
processList.add(used2000);
|
||||
ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10);
|
||||
processList.add(used10);
|
||||
ProcessRecord service1 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20);
|
||||
processList.add(service1);
|
||||
ProcessRecord service2 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500);
|
||||
processList.add(service2);
|
||||
ProcessRecord service3 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200);
|
||||
processList.add(service3);
|
||||
list.setLruProcessServiceStartLSP(3);
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
|
||||
// Services unchanged, rest re-ranked.
|
||||
assertThat(processList).containsExactly(used10, used1000, used2000, service1, service2,
|
||||
service3).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reRankLruCachedApps_manyProcessesThenFew() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
|
||||
ProcessList set1List = new ProcessList();
|
||||
ArrayList<ProcessRecord> set1ProcessList = set1List.getLruProcessesLSP();
|
||||
ProcessRecord set1Used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000);
|
||||
set1ProcessList.add(set1Used1000);
|
||||
ProcessRecord set1Used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000);
|
||||
set1ProcessList.add(set1Used2000);
|
||||
ProcessRecord set1Used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10);
|
||||
set1ProcessList.add(set1Used10);
|
||||
ProcessRecord set1Uses20 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20);
|
||||
set1ProcessList.add(set1Uses20);
|
||||
ProcessRecord set1Uses500 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500);
|
||||
set1ProcessList.add(set1Uses500);
|
||||
ProcessRecord set1Uses200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200);
|
||||
set1ProcessList.add(set1Uses200);
|
||||
set1List.setLruProcessServiceStartLSP(set1ProcessList.size());
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(set1ProcessList,
|
||||
set1List.getLruProcessServiceStartLOSP());
|
||||
assertThat(set1ProcessList).containsExactly(set1Used10, set1Uses20, set1Uses200,
|
||||
set1Uses500, set1Used1000, set1Used2000).inOrder();
|
||||
|
||||
ProcessList set2List = new ProcessList();
|
||||
ArrayList<ProcessRecord> set2ProcessList = set2List.getLruProcessesLSP();
|
||||
ProcessRecord set2Used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000);
|
||||
set2ProcessList.add(set2Used1000);
|
||||
ProcessRecord set2Used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000);
|
||||
set2ProcessList.add(set2Used2000);
|
||||
ProcessRecord set2Used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10);
|
||||
set2ProcessList.add(set2Used10);
|
||||
ProcessRecord set2ForegroundAdj = nextProcessRecord(ProcessList.FOREGROUND_APP_ADJ,
|
||||
NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20);
|
||||
set2ProcessList.add(set2ForegroundAdj);
|
||||
ProcessRecord set2ServiceAdj = nextProcessRecord(ProcessList.SERVICE_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500);
|
||||
set2ProcessList.add(set2ServiceAdj);
|
||||
ProcessRecord set2SystemAdj = nextProcessRecord(ProcessList.SYSTEM_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200);
|
||||
set2ProcessList.add(set2SystemAdj);
|
||||
set2List.setLruProcessServiceStartLSP(set2ProcessList.size());
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(set2ProcessList,
|
||||
set2List.getLruProcessServiceStartLOSP());
|
||||
assertThat(set2ProcessList).containsExactly(set2Used10, set2Used1000, set2Used2000,
|
||||
set2ForegroundAdj, set2ServiceAdj, set2SystemAdj).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reRankLruCachedApps_preservesTopNApps() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 3,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
|
||||
ProcessList list = new ProcessList();
|
||||
ArrayList<ProcessRecord> processList = list.getLruProcessesLSP();
|
||||
ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000);
|
||||
processList.add(used1000);
|
||||
ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000);
|
||||
processList.add(used2000);
|
||||
ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10);
|
||||
processList.add(used10);
|
||||
// Preserving the top 3 processes, so these should not be re-ranked.
|
||||
ProcessRecord used20 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20);
|
||||
processList.add(used20);
|
||||
ProcessRecord used500 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500);
|
||||
processList.add(used500);
|
||||
ProcessRecord used200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200);
|
||||
processList.add(used200);
|
||||
list.setLruProcessServiceStartLSP(processList.size());
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
|
||||
// First 3 ordered by uses, then last processes position unchanged.
|
||||
assertThat(processList).containsExactly(used10, used1000, used2000, used20, used500,
|
||||
used200).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reRankLruCachedApps_preservesTopNApps_allAppsUnchanged()
|
||||
throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 100,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -349,22 +501,66 @@ public class CacheOomRankerTest {
|
||||
ProcessRecord used200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200);
|
||||
processList.add(used200);
|
||||
list.setLruProcessServiceStartLSP(3);
|
||||
list.setLruProcessServiceStartLSP(processList.size());
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
|
||||
// All positions unchanged.
|
||||
// Nothing reordered, as we preserve the top 100 apps.
|
||||
assertThat(processList).containsExactly(used1000, used2000, used10, used20, used500,
|
||||
used200).inOrder();
|
||||
}
|
||||
|
||||
private void setConfig(int numberToReRank, float usesWeight, float pssWeight, float lruWeight)
|
||||
@Test
|
||||
public void reRankLruCachedApps_preservesTopNApps_negativeReplacedWithDefault()
|
||||
throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ -100,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
|
||||
ProcessList list = new ProcessList();
|
||||
ArrayList<ProcessRecord> processList = list.getLruProcessesLSP();
|
||||
ProcessRecord used1000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000);
|
||||
processList.add(used1000);
|
||||
ProcessRecord used2000 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000);
|
||||
processList.add(used2000);
|
||||
ProcessRecord used10 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10);
|
||||
processList.add(used10);
|
||||
// Negative preserveTopNApps interpreted as the default (3), so the last three are unranked.
|
||||
ProcessRecord used20 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20);
|
||||
processList.add(used20);
|
||||
ProcessRecord used500 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 500);
|
||||
processList.add(used500);
|
||||
ProcessRecord used200 = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 200);
|
||||
processList.add(used200);
|
||||
list.setLruProcessServiceStartLSP(processList.size());
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
|
||||
// First 3 apps re-ranked, as preserveTopNApps is interpreted as 3.
|
||||
assertThat(processList).containsExactly(used10, used1000, used2000, used20, used500,
|
||||
used200).inOrder();
|
||||
}
|
||||
|
||||
private void setConfig(int numberToReRank, int preserveTopNApps, float usesWeight,
|
||||
float pssWeight, float lruWeight)
|
||||
throws InterruptedException {
|
||||
mExecutor.init(4);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_NUMBER_TO_RE_RANK,
|
||||
Integer.toString(numberToReRank),
|
||||
false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS,
|
||||
Integer.toString(preserveTopNApps),
|
||||
false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_LRU_WEIGHT,
|
||||
Float.toString(lruWeight),
|
||||
|
||||
Reference in New Issue
Block a user