Use Process.getRss instead of mProfile.getLastRss in CacheOomRanker.
RSS values are cached in ProcessStateRecord, and repopulated when they are >10s old. mProfile.getLastRss values can be 15s-2h stale, which is why we're using this implementation. My understanding is that the best solution would be to populate mProfile.getLastRss more often - but it is currently populated alongside PSS, which is more expensive to calculate. Therefore, rather than the more complex change of splitting up PSS & RSS collection, we opt for this simple (if not optimal) approach as CacheOomRanker is still experimental. Upon successful launch, we can revisit this. When logging the duration of CacheOomRanker calculations, we saw no significant increase in computation time with this change. If we turn off caching RSS values, we see a 10x increase in computation time. Test: atest CacheOomRankerTest Bug: 196031723 Change-Id: I8e80db2aab338df07f07842131a9d4b55bebd054
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.am;
|
||||
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -46,6 +48,14 @@ public class CacheOomRanker {
|
||||
@VisibleForTesting
|
||||
static final int DEFAULT_PRESERVE_TOP_N_APPS = 3;
|
||||
@VisibleForTesting
|
||||
static final String KEY_OOM_RE_RANKING_USE_FREQUENT_RSS = "oom_re_ranking_rss_use_frequent_rss";
|
||||
@VisibleForTesting
|
||||
static final boolean DEFAULT_USE_FREQUENT_RSS = true;
|
||||
@VisibleForTesting
|
||||
static final String KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS = "oom_re_ranking_rss_update_rate_ms";
|
||||
@VisibleForTesting
|
||||
static final long DEFAULT_RSS_UPDATE_RATE_MS = 10_000; // 10 seconds
|
||||
@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;
|
||||
@@ -62,6 +72,8 @@ public class CacheOomRanker {
|
||||
new ScoreComparator();
|
||||
private static final Comparator<RankedProcessRecord> CACHE_USE_COMPARATOR =
|
||||
new CacheUseComparator();
|
||||
private static final Comparator<RankedProcessRecord> RSS_COMPARATOR =
|
||||
new RssComparator();
|
||||
private static final Comparator<RankedProcessRecord> LAST_RSS_COMPARATOR =
|
||||
new LastRssComparator();
|
||||
private static final Comparator<RankedProcessRecord> LAST_ACTIVITY_TIME_COMPARATOR =
|
||||
@@ -70,6 +82,7 @@ public class CacheOomRanker {
|
||||
private final Object mPhenotypeFlagLock = new Object();
|
||||
|
||||
private final ActivityManagerService mService;
|
||||
private final ProcessDependencies mProcessDependencies;
|
||||
private final ActivityManagerGlobalLock mProcLock;
|
||||
private final Object mProfilerLock;
|
||||
|
||||
@@ -78,6 +91,12 @@ public class CacheOomRanker {
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting
|
||||
int mPreserveTopNApps = DEFAULT_PRESERVE_TOP_N_APPS;
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting
|
||||
boolean mUseFrequentRss = DEFAULT_USE_FREQUENT_RSS;
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting
|
||||
long mRssUpdateRateMs = DEFAULT_RSS_UPDATE_RATE_MS;
|
||||
// Weight to apply to the LRU ordering.
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
@VisibleForTesting
|
||||
@@ -110,6 +129,10 @@ public class CacheOomRanker {
|
||||
updateNumberToReRank();
|
||||
} else if (KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS.equals(name)) {
|
||||
updatePreserveTopNApps();
|
||||
} else if (KEY_OOM_RE_RANKING_USE_FREQUENT_RSS.equals(name)) {
|
||||
updateUseFrequentRss();
|
||||
} else if (KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS.equals(name)) {
|
||||
updateRssUpdateRateMs();
|
||||
} else if (KEY_OOM_RE_RANKING_LRU_WEIGHT.equals(name)) {
|
||||
updateLruWeight();
|
||||
} else if (KEY_OOM_RE_RANKING_USES_WEIGHT.equals(name)) {
|
||||
@@ -123,9 +146,15 @@ public class CacheOomRanker {
|
||||
};
|
||||
|
||||
CacheOomRanker(final ActivityManagerService service) {
|
||||
this(service, new ProcessDependenciesImpl());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
CacheOomRanker(final ActivityManagerService service, ProcessDependencies processDependencies) {
|
||||
mService = service;
|
||||
mProcLock = service.mProcLock;
|
||||
mProfilerLock = service.mAppProfiler.mProfilerLock;
|
||||
mProcessDependencies = processDependencies;
|
||||
}
|
||||
|
||||
/** Load settings from device config and register a listener for changes. */
|
||||
@@ -189,6 +218,18 @@ public class CacheOomRanker {
|
||||
mPreserveTopNApps = preserveTopNApps;
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateRssUpdateRateMs() {
|
||||
mRssUpdateRateMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS, DEFAULT_RSS_UPDATE_RATE_MS);
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateUseFrequentRss() {
|
||||
mUseFrequentRss = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
KEY_OOM_RE_RANKING_USE_FREQUENT_RSS, DEFAULT_USE_FREQUENT_RSS);
|
||||
}
|
||||
|
||||
@GuardedBy("mPhenotypeFlagLock")
|
||||
private void updateLruWeight() {
|
||||
mLruWeight = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
@@ -244,6 +285,8 @@ public class CacheOomRanker {
|
||||
float usesWeight;
|
||||
float rssWeight;
|
||||
int preserveTopNApps;
|
||||
boolean useFrequentRss;
|
||||
long rssUpdateRateMs;
|
||||
int[] lruPositions;
|
||||
RankedProcessRecord[] scoredProcessRecords;
|
||||
|
||||
@@ -252,6 +295,8 @@ public class CacheOomRanker {
|
||||
usesWeight = mUsesWeight;
|
||||
rssWeight = mRssWeight;
|
||||
preserveTopNApps = mPreserveTopNApps;
|
||||
useFrequentRss = mUseFrequentRss;
|
||||
rssUpdateRateMs = mRssUpdateRateMs;
|
||||
lruPositions = mLruPositions;
|
||||
scoredProcessRecords = mScoredProcessRecords;
|
||||
}
|
||||
@@ -296,6 +341,32 @@ public class CacheOomRanker {
|
||||
}
|
||||
}
|
||||
|
||||
if (useFrequentRss) {
|
||||
// Update RSS values for re-ranked apps.
|
||||
long nowMs = SystemClock.elapsedRealtime();
|
||||
for (int i = 0; i < numProcessesReRanked; ++i) {
|
||||
RankedProcessRecord scoredProcessRecord = scoredProcessRecords[i];
|
||||
long sinceUpdateMs =
|
||||
nowMs - scoredProcessRecord.proc.mState.getCacheOomRankerRssTimeMs();
|
||||
if (scoredProcessRecord.proc.mState.getCacheOomRankerRss() != 0
|
||||
&& sinceUpdateMs < rssUpdateRateMs) {
|
||||
continue;
|
||||
}
|
||||
|
||||
long[] rss = mProcessDependencies.getRss(scoredProcessRecord.proc.getPid());
|
||||
if (rss == null || rss.length == 0) {
|
||||
Slog.e(
|
||||
OomAdjuster.TAG,
|
||||
"Process.getRss returned bad value, not re-ranking: "
|
||||
+ Arrays.toString(rss));
|
||||
return;
|
||||
}
|
||||
// First element is total RSS:
|
||||
// frameworks/base/core/jni/android_util_Process.cpp:1192
|
||||
scoredProcessRecord.proc.mState.setCacheOomRankerRss(rss[0], nowMs);
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -305,8 +376,12 @@ public class CacheOomRanker {
|
||||
addToScore(scoredProcessRecords, lruWeight);
|
||||
}
|
||||
if (rssWeight > 0.0f) {
|
||||
synchronized (mService.mAppProfiler.mProfilerLock) {
|
||||
Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, LAST_RSS_COMPARATOR);
|
||||
if (useFrequentRss) {
|
||||
Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, RSS_COMPARATOR);
|
||||
} else {
|
||||
synchronized (mService.mAppProfiler.mProfilerLock) {
|
||||
Arrays.sort(scoredProcessRecords, 0, numProcessesReRanked, LAST_RSS_COMPARATOR);
|
||||
}
|
||||
}
|
||||
addToScore(scoredProcessRecords, rssWeight);
|
||||
}
|
||||
@@ -385,6 +460,16 @@ public class CacheOomRanker {
|
||||
}
|
||||
}
|
||||
|
||||
private static class RssComparator implements Comparator<RankedProcessRecord> {
|
||||
@Override
|
||||
public int compare(RankedProcessRecord o1, RankedProcessRecord o2) {
|
||||
// High RSS first to match least recently used.
|
||||
return Long.compare(
|
||||
o2.proc.mState.getCacheOomRankerRss(),
|
||||
o1.proc.mState.getCacheOomRankerRss());
|
||||
}
|
||||
}
|
||||
|
||||
private static class LastRssComparator implements Comparator<RankedProcessRecord> {
|
||||
@Override
|
||||
public int compare(RankedProcessRecord o1, RankedProcessRecord o2) {
|
||||
@@ -397,4 +482,18 @@ public class CacheOomRanker {
|
||||
public ProcessRecord proc;
|
||||
public float score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for mocking {@link Process} static methods.
|
||||
*/
|
||||
interface ProcessDependencies {
|
||||
long[] getRss(int pid);
|
||||
}
|
||||
|
||||
private static class ProcessDependenciesImpl implements ProcessDependencies {
|
||||
@Override
|
||||
public long[] getRss(int pid) {
|
||||
return Process.getRss(pid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,6 +359,20 @@ final class ProcessStateRecord {
|
||||
@GuardedBy("mService")
|
||||
private int mCacheOomRankerUseCount;
|
||||
|
||||
/**
|
||||
* Process memory usage (RSS).
|
||||
*
|
||||
* Periodically populated by {@code CacheOomRanker}, stored in this object to cache the values.
|
||||
*/
|
||||
@GuardedBy("mService")
|
||||
private long mCacheOomRankerRss;
|
||||
|
||||
/**
|
||||
* The last time, in milliseconds since boot, since {@link #mCacheOomRankerRss} was updated.
|
||||
*/
|
||||
@GuardedBy("mService")
|
||||
private long mCacheOomRankerRssTimeMs;
|
||||
|
||||
/**
|
||||
* Whether or not this process is reachable from given process.
|
||||
*/
|
||||
@@ -1266,6 +1280,21 @@ final class ProcessStateRecord {
|
||||
return mLastCanKillOnBgRestrictedAndIdleTime;
|
||||
}
|
||||
|
||||
public void setCacheOomRankerRss(long rss, long rssTimeMs) {
|
||||
mCacheOomRankerRss = rss;
|
||||
mCacheOomRankerRssTimeMs = rssTimeMs;
|
||||
}
|
||||
|
||||
@GuardedBy("mService")
|
||||
public long getCacheOomRankerRss() {
|
||||
return mCacheOomRankerRss;
|
||||
}
|
||||
|
||||
@GuardedBy("mService")
|
||||
public long getCacheOomRankerRssTimeMs() {
|
||||
return mCacheOomRankerRssTimeMs;
|
||||
}
|
||||
|
||||
@GuardedBy({"mService", "mProcLock"})
|
||||
void dump(PrintWriter pw, String prefix, long nowUptime) {
|
||||
if (mReportedInteraction || mFgInteractionTime != 0) {
|
||||
|
||||
@@ -57,6 +57,9 @@ import java.time.LocalDate;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -67,6 +70,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* Build/Install/Run:
|
||||
* atest FrameworksMockingServicesTests:CacheOomRankerTest
|
||||
*/
|
||||
@SuppressWarnings("GuardedBy") // No tests are concurrent, so no need to test locking.
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CacheOomRankerTest {
|
||||
private static final Instant NOW = LocalDate.of(2021, 1, 1).atStartOfDay(
|
||||
@@ -91,6 +95,7 @@ public class CacheOomRankerTest {
|
||||
private int mNextUid = 30000;
|
||||
private int mNextPackageUid = 40000;
|
||||
private int mNextPackageName = 1;
|
||||
private Map<Integer, Long> mPidToRss;
|
||||
|
||||
private TestExecutor mExecutor = new TestExecutor();
|
||||
private CacheOomRanker mCacheOomRanker;
|
||||
@@ -116,7 +121,15 @@ public class CacheOomRankerTest {
|
||||
LocalServices.removeServiceForTest(PackageManagerInternal.class);
|
||||
LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
|
||||
|
||||
mCacheOomRanker = new CacheOomRanker(mAms);
|
||||
mPidToRss = new HashMap<>();
|
||||
mCacheOomRanker = new CacheOomRanker(
|
||||
mAms,
|
||||
pid -> {
|
||||
Long rss = mPidToRss.get(pid);
|
||||
assertThat(rss).isNotNull();
|
||||
return new long[]{rss};
|
||||
}
|
||||
);
|
||||
mCacheOomRanker.init(mExecutor);
|
||||
}
|
||||
|
||||
@@ -184,6 +197,8 @@ public class CacheOomRankerTest {
|
||||
public void reRankLruCachedApps_lruImpactsOrdering() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 5,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 0.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */1.0f);
|
||||
@@ -223,6 +238,8 @@ public class CacheOomRankerTest {
|
||||
public void reRankLruCachedApps_rssImpactsOrdering() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 0.0f,
|
||||
/* pssWeight= */ 1.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -260,10 +277,129 @@ public class CacheOomRankerTest {
|
||||
rss16k).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reRankLruCachedApps_rssImpactsOrdering_cachedRssValues()
|
||||
throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 10000000,
|
||||
/* usesWeight= */ 0.0f,
|
||||
/* pssWeight= */ 1.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
|
||||
ProcessList list = new ProcessList();
|
||||
ArrayList<ProcessRecord> processList = list.getLruProcessesLSP();
|
||||
ProcessRecord rss10k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 10 * 1024L, 1000);
|
||||
processList.add(rss10k);
|
||||
ProcessRecord rss20k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 20 * 1024L, 2000);
|
||||
processList.add(rss20k);
|
||||
ProcessRecord rss1k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(60, ChronoUnit.MINUTES).toEpochMilli(), 1024L, 10000);
|
||||
processList.add(rss1k);
|
||||
ProcessRecord rss100k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 100 * 1024L, 10);
|
||||
processList.add(rss100k);
|
||||
ProcessRecord rss2k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 2 * 1024L, 20);
|
||||
processList.add(rss2k);
|
||||
ProcessRecord rss15k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 20);
|
||||
processList.add(rss15k);
|
||||
// Only re-ranking 6 entries so this should stay in most recent position.
|
||||
ProcessRecord rss16k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 20);
|
||||
processList.add(rss16k);
|
||||
list.setLruProcessServiceStartLSP(processList.size());
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
// First 6 ordered by largest pss, then last processes position unchanged.
|
||||
assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
|
||||
rss16k).inOrder();
|
||||
|
||||
// Clear mPidToRss so that Process.getRss calls fail.
|
||||
mPidToRss.clear();
|
||||
// Mix up the process list to ensure that CacheOomRanker actually re-ranks.
|
||||
Collections.swap(processList, 0, 1);
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
// Re ranking is the same.
|
||||
assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
|
||||
rss16k).inOrder();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reRankLruCachedApps_rssImpactsOrdering_profileRss()
|
||||
throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* useFrequentRss= */ false,
|
||||
/* rssUpdateRateMs= */ 10000000,
|
||||
/* usesWeight= */ 0.0f,
|
||||
/* pssWeight= */ 1.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
|
||||
ProcessList list = new ProcessList();
|
||||
ArrayList<ProcessRecord> processList = list.getLruProcessesLSP();
|
||||
ProcessRecord rss10k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(40, ChronoUnit.MINUTES).toEpochMilli(), 0L, 1000);
|
||||
rss10k.mProfile.setLastRss(10 * 1024L);
|
||||
processList.add(rss10k);
|
||||
ProcessRecord rss20k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(42, ChronoUnit.MINUTES).toEpochMilli(), 0L, 2000);
|
||||
rss20k.mProfile.setLastRss(20 * 1024L);
|
||||
processList.add(rss20k);
|
||||
ProcessRecord rss1k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(60, ChronoUnit.MINUTES).toEpochMilli(), 0L, 10000);
|
||||
rss1k.mProfile.setLastRss(1024L);
|
||||
processList.add(rss1k);
|
||||
ProcessRecord rss100k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(15, ChronoUnit.MINUTES).toEpochMilli(), 0L, 10);
|
||||
rss100k.mProfile.setLastRss(100 * 1024L);
|
||||
processList.add(rss100k);
|
||||
ProcessRecord rss2k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(17, ChronoUnit.MINUTES).toEpochMilli(), 0L, 20);
|
||||
rss2k.mProfile.setLastRss(2 * 1024L);
|
||||
processList.add(rss2k);
|
||||
ProcessRecord rss15k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 15 * 1024L, 20);
|
||||
rss15k.mProfile.setLastRss(15 * 1024L);
|
||||
processList.add(rss15k);
|
||||
// Only re-ranking 6 entries so this should stay in most recent position.
|
||||
ProcessRecord rss16k = nextProcessRecord(ProcessList.UNKNOWN_ADJ,
|
||||
NOW.minus(30, ChronoUnit.MINUTES).toEpochMilli(), 16 * 1024L, 20);
|
||||
rss16k.mProfile.setLastRss(16 * 1024L);
|
||||
processList.add(rss16k);
|
||||
list.setLruProcessServiceStartLSP(processList.size());
|
||||
|
||||
// This should not be used, as RSS values are taken from mProfile.
|
||||
mPidToRss.clear();
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
// First 6 ordered by largest pss, then last processes position unchanged.
|
||||
assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
|
||||
rss16k).inOrder();
|
||||
|
||||
// Clear mPidToRss so that Process.getRss calls fail.
|
||||
mPidToRss.clear();
|
||||
// Mix up the process list to ensure that CacheOomRanker actually re-ranks.
|
||||
Collections.swap(processList, 0, 1);
|
||||
|
||||
mCacheOomRanker.reRankLruCachedAppsLSP(processList, list.getLruProcessServiceStartLOSP());
|
||||
// Re ranking is the same.
|
||||
assertThat(processList).containsExactly(rss100k, rss20k, rss15k, rss10k, rss2k, rss1k,
|
||||
rss16k).inOrder();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void reRankLruCachedApps_usesImpactsOrdering() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 4,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -302,6 +438,8 @@ public class CacheOomRankerTest {
|
||||
public void reRankLruCachedApps_fewProcesses() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 4,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -339,6 +477,8 @@ public class CacheOomRankerTest {
|
||||
public void reRankLruCachedApps_fewNonServiceProcesses() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 4,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -376,6 +516,8 @@ public class CacheOomRankerTest {
|
||||
public void reRankLruCachedApps_manyProcessesThenFew() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 0,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -439,6 +581,8 @@ public class CacheOomRankerTest {
|
||||
public void reRankLruCachedApps_preservesTopNApps() throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 3,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -478,6 +622,8 @@ public class CacheOomRankerTest {
|
||||
throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ 100,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -516,6 +662,8 @@ public class CacheOomRankerTest {
|
||||
throws InterruptedException {
|
||||
setConfig(/* numberToReRank= */ 6,
|
||||
/* preserveTopNApps= */ -100,
|
||||
/* useFrequentRss= */ true,
|
||||
/* rssUpdateRateMs= */ 0,
|
||||
/* usesWeight= */ 1.0f,
|
||||
/* pssWeight= */ 0.0f,
|
||||
/* lruWeight= */ 0.0f);
|
||||
@@ -550,8 +698,8 @@ public class CacheOomRankerTest {
|
||||
used200).inOrder();
|
||||
}
|
||||
|
||||
private void setConfig(int numberToReRank, int preserveTopNApps, float usesWeight,
|
||||
float pssWeight, float lruWeight)
|
||||
private void setConfig(int numberToReRank, int preserveTopNApps, boolean useFrequentRss,
|
||||
long rssUpdateRateMs, float usesWeight, float pssWeight, float lruWeight)
|
||||
throws InterruptedException {
|
||||
mExecutor.init(4);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
@@ -562,6 +710,14 @@ public class CacheOomRankerTest {
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_PRESERVE_TOP_N_APPS,
|
||||
Integer.toString(preserveTopNApps),
|
||||
false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_USE_FREQUENT_RSS,
|
||||
Boolean.toString(useFrequentRss),
|
||||
false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_RSS_UPDATE_RATE_MS,
|
||||
Long.toString(rssUpdateRateMs),
|
||||
false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||
CacheOomRanker.KEY_OOM_RE_RANKING_LRU_WEIGHT,
|
||||
Float.toString(lruWeight),
|
||||
@@ -576,6 +732,8 @@ public class CacheOomRankerTest {
|
||||
false);
|
||||
mExecutor.waitForLatch();
|
||||
assertThat(mCacheOomRanker.getNumberToReRank()).isEqualTo(numberToReRank);
|
||||
assertThat(mCacheOomRanker.mUseFrequentRss).isEqualTo(useFrequentRss);
|
||||
assertThat(mCacheOomRanker.mRssUpdateRateMs).isEqualTo(rssUpdateRateMs);
|
||||
assertThat(mCacheOomRanker.mRssWeight).isEqualTo(pssWeight);
|
||||
assertThat(mCacheOomRanker.mUsesWeight).isEqualTo(usesWeight);
|
||||
assertThat(mCacheOomRanker.mLruWeight).isEqualTo(lruWeight);
|
||||
@@ -592,7 +750,7 @@ public class CacheOomRankerTest {
|
||||
app.mState.setSetProcState(PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
|
||||
app.mState.setCurAdj(setAdj);
|
||||
app.setLastActivityTime(lastActivityTime);
|
||||
app.mProfile.setLastRss(lastRss);
|
||||
mPidToRss.put(app.getPid(), lastRss);
|
||||
app.mState.setCached(false);
|
||||
for (int i = 0; i < wentToForegroundCount; ++i) {
|
||||
app.mState.setSetProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
|
||||
|
||||
Reference in New Issue
Block a user