diff options
author | Dianne Hackborn <hackbod@google.com> | 2015-11-04 12:32:45 -0800 |
---|---|---|
committer | Thierry Strudel <tstrudel@google.com> | 2015-12-10 15:14:46 -0800 |
commit | 022c748f54626f77f01079595a0100d1d145f383 (patch) | |
tree | 18c7a6b8ce609d5dd0e1f5b3f5978e7657ec7920 /services | |
parent | ba88e68fe47b66f1fc5d10c15f04f20fe662399e (diff) | |
download | frameworks_base-022c748f54626f77f01079595a0100d1d145f383.zip frameworks_base-022c748f54626f77f01079595a0100d1d145f383.tar.gz frameworks_base-022c748f54626f77f01079595a0100d1d145f383.tar.bz2 |
Work on issue #25467052: System lagged out
Add a new mechanism where we retain previously used provided
processes in the "last activity" oom adj state for 20 seconds,
before allowing them to fall down to a regular cached process.
This should help reduce thrashing when something is acquiring
and releasing a provider repeatedly.
Change-Id: I889472de7bb4da574b46f07e36a99978813643cb
Diffstat (limited to 'services')
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 25 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ProcessRecord.java | 6 |
2 files changed, 31 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 8ef8364..ba916ad 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -320,6 +320,11 @@ public final class ActivityManagerService extends ActivityManagerNative // before we decide it must be hung. static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000; + // How long we will retain processes hosting content providers in the "last activity" + // state before allowing them to drop down to the regular cached LRU list. This is + // to avoid thrashing of provider processes under low memory situations. + static final int CONTENT_PROVIDER_RETAIN_TIME = 20*1000; + // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real, when the process was // started with a wrapper for instrumentation (such as Valgrind) because it @@ -9448,6 +9453,14 @@ public final class ActivityManagerService extends ActivityManagerNative if (conn.stableCount == 0 && conn.unstableCount == 0) { cpr.connections.remove(conn); conn.client.conProviders.remove(conn); + if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { + // The client is more important than last activity -- note the time this + // is happening, so we keep the old provider process around a bit as last + // activity to avoid thrashing it. + if (cpr.proc != null) { + cpr.proc.lastProviderTime = SystemClock.uptimeMillis(); + } + } stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.name); return true; } @@ -18203,6 +18216,18 @@ public final class ActivityManagerService extends ActivityManagerNative } } + if (app.lastProviderTime > 0 && (app.lastProviderTime+CONTENT_PROVIDER_RETAIN_TIME) > now) { + if (adj > ProcessList.PREVIOUS_APP_ADJ) { + adj = ProcessList.PREVIOUS_APP_ADJ; + schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; + app.cached = false; + app.adjType = "provider"; + } + if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { + procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; + } + } + if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) { // A client of one of our services or providers is in the top state. We // *may* want to be in the top state, but not if we are already running in diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 697b4e2..4e42c5c 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -136,6 +136,7 @@ final class ProcessRecord { long curCpuTime; // How long proc has run CPU most recently long lastRequestedGc; // When we last asked the app to do a gc long lastLowMemory; // When we last told the app that memory is low + long lastProviderTime; // The last time someone else was using a provider in this process. boolean reportLowMemory; // Set to true when waiting to report low mem boolean empty; // Is this an empty background process? boolean cached; // Is this a cached process? @@ -317,6 +318,11 @@ final class ProcessRecord { pw.print(" foregroundActivities="); pw.print(foregroundActivities); pw.print(" (rep="); pw.print(repForegroundActivities); pw.println(")"); } + if (lastProviderTime > 0) { + pw.print(prefix); pw.print("lastProviderTime="); + TimeUtils.formatDuration(lastProviderTime, now, pw); + pw.println(); + } if (hasStartedServices) { pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices); } |