Allow CacheOomRanker to rerank when there's <8 processes in the cache.
This allows us to increase the number of process we rerank without
losing the impact of the reranking.
This would also mean that the top apps in the cache get reranked more
often, so we also add a flag to prevent the top N processes from being
re-ranked.
Discussed with vvaldes@ offline: this is closer to the logic in the
simulations that decided the weights, so this logic change shouldn't
break any assumptions of the model.
Test: atest FrameworksMockingServicesTests:CacheOomRankerTest
Bug: 191357172
Change-Id: I0533da0a70cfe7ed1b48e4f98be24a46f17f7845
Merged-In: I0533da0a70cfe7ed1b48e4f98be24a46f17f7845
(cherry picked from commit f913ae217a)
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