From ed0a3220ceaf344531a6ac948a7aff9021fc8657 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Tue, 6 Feb 2018 16:01:23 -0800 Subject: [PATCH] Further tuning of PSS collection. We now keep track of a scaling factor of collection for each memory state, and allow that to continually grow as long as the process doesn't come back to it from a new higher memory state. This should allow us to spread out the sample rate for longer-running processes to be much longer, to reduce the frequency of PSS collection. Also moved the decision about when to do a PSS sample of all processes from some internal timing in the activity manager to being tied to procstats data commits. This makes the interval longer, and ensures after each commit we have a good initial sample of memory data for all processes. Bug: 70859548 Test: atest CtsAppTestCases Change-Id: Ia3ea2bc9e2d032d51e46e178e2b86b072af9f1ba --- .../server/am/ActivityManagerService.java | 44 ++++++++------ .../com/android/server/am/ProcessList.java | 60 +++++++++++-------- .../server/am/ProcessStatsService.java | 3 + 3 files changed, 63 insertions(+), 44 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 99f36d0a8b1bd..40d802de82c40 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1854,7 +1854,6 @@ public class ActivityManagerService extends IActivityManager.Stub static final int REPORT_MEM_USAGE_MSG = 33; static final int IMMERSIVE_MODE_LOCK_MSG = 37; static final int PERSIST_URI_GRANTS_MSG = 38; - static final int REQUEST_ALL_PSS_MSG = 39; static final int UPDATE_TIME_PREFERENCE_MSG = 41; static final int ENTER_ANIMATION_COMPLETE_MSG = 44; static final int FINISH_BOOTING_MSG = 45; @@ -2320,12 +2319,6 @@ public class ActivityManagerService extends IActivityManager.Stub writeGrantedUriPermissions(); break; } - case REQUEST_ALL_PSS_MSG: { - synchronized (ActivityManagerService.this) { - requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); - } - break; - } case UPDATE_TIME_PREFERENCE_MSG: { // The user's time format preference might have changed. // For convenience we re-use the Intent extra values. @@ -2615,11 +2608,17 @@ public class ActivityManagerService extends IActivityManager.Stub procState = proc.pssProcState; statType = proc.pssStatType; lastPssTime = proc.lastPssTime; + long now = SystemClock.uptimeMillis(); if (proc.thread != null && procState == proc.setProcState && (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE) - < SystemClock.uptimeMillis()) { + < now) { pid = proc.pid; } else { + ProcessList.abortNextPssTime(proc.procStateMemTracker); + if (DEBUG_PSS) Slog.d(TAG_PSS, "Skipped pss collection of " + pid + + ": still need " + + (lastPssTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE-now) + + "ms until safe"); proc = null; pid = 0; } @@ -14477,9 +14476,6 @@ public class ActivityManagerService extends IActivityManager.Stub mTestPssMode, isSleepingLocked(), now); } } - - mHandler.removeMessages(REQUEST_ALL_PSS_MSG); - mHandler.sendEmptyMessageDelayed(REQUEST_ALL_PSS_MSG, 2*60*1000); } } @@ -19526,6 +19522,7 @@ public class ActivityManagerService extends IActivityManager.Stub mProcessesToGc.remove(app); mPendingPssProcesses.remove(app); + ProcessList.abortNextPssTime(app.procStateMemTracker); // Dismiss any open dialogs. if (app.crashDialog != null && !app.forceCrashReport) { @@ -23290,9 +23287,9 @@ public class ActivityManagerService extends IActivityManager.Stub /** * Schedule PSS collection of a process. */ - void requestPssLocked(ProcessRecord proc, int procState) { + boolean requestPssLocked(ProcessRecord proc, int procState) { if (mPendingPssProcesses.contains(proc)) { - return; + return false; } if (mPendingPssProcesses.size() == 0) { mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG); @@ -23301,6 +23298,7 @@ public class ActivityManagerService extends IActivityManager.Stub proc.pssProcState = procState; proc.pssStatType = ProcessStats.ADD_PSS_INTERNAL_SINGLE; mPendingPssProcesses.add(proc); + return true; } /** @@ -23317,6 +23315,9 @@ public class ActivityManagerService extends IActivityManager.Stub if (DEBUG_PSS) Slog.d(TAG_PSS, "Requesting pss of all procs! memLowered=" + memLowered); mLastFullPssTime = now; mFullPssPending = true; + for (int i = mPendingPssProcesses.size() - 1; i >= 0; i--) { + ProcessList.abortNextPssTime(mPendingPssProcesses.get(i).procStateMemTracker);; + } mPendingPssProcesses.ensureCapacity(mLruProcesses.size()); mPendingPssProcesses.clear(); for (int i = mLruProcesses.size() - 1; i >= 0; i--) { @@ -23325,7 +23326,9 @@ public class ActivityManagerService extends IActivityManager.Stub || app.curProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) { continue; } - if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) { + if (memLowered || (always && now > + app.lastStateTime+ProcessList.PSS_SAFE_TIME_FROM_STATE_CHANGE) + || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) { app.pssProcState = app.setProcState; app.pssStatType = always ? ProcessStats.ADD_PSS_INTERNAL_ALL_POLL : ProcessStats.ADD_PSS_INTERNAL_ALL_MEM; @@ -23334,7 +23337,9 @@ public class ActivityManagerService extends IActivityManager.Stub mPendingPssProcesses.add(app); } } - mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG); + if (!mBgHandler.hasMessages(COLLECT_PSS_BG_MSG)) { + mBgHandler.sendEmptyMessage(COLLECT_PSS_BG_MSG); + } } public void setTestPssMode(boolean enabled) { @@ -23692,7 +23697,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Experimental code to more aggressively collect pss while // running test... the problem is that this tends to collect // the data right when a process is transitioning between process - // states, which well tend to give noisy data. + // states, which will tend to give noisy data. long start = SystemClock.uptimeMillis(); long startTime = SystemClock.currentThreadTimeMillis(); long pss = Debug.getPss(app.pid, mTmpLong, null); @@ -23715,9 +23720,10 @@ public class ActivityManagerService extends IActivityManager.Stub if (now > app.nextPssTime || (now > (app.lastPssTime+ProcessList.PSS_MAX_INTERVAL) && now > (app.lastStateTime+ProcessList.minTimeFromStateChange( mTestPssMode)))) { - requestPssLocked(app, app.setProcState); - app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, - app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now); + if (requestPssLocked(app, app.setProcState)) { + app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, + app.procStateMemTracker, mTestPssMode, isSleepingLocked(), now); + } } else if (false && DEBUG_PSS) Slog.d(TAG_PSS, "Not requesting pss of " + app + ": next=" + (app.nextPssTime-now)); } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 08ee23723df44..bf7aef9ecc65a 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -501,19 +501,19 @@ public final class ProcessList { private static final int PSS_FIRST_CACHED_INTERVAL = 20*1000; // The amount of time until PSS when an important process stays in the same state. - private static final int PSS_SAME_PERSISTENT_INTERVAL = 20*60*1000; + private static final int PSS_SAME_PERSISTENT_INTERVAL = 10*60*1000; // The amount of time until PSS when the top process stays in the same state. - private static final int PSS_SAME_TOP_INTERVAL = 5*60*1000; + private static final int PSS_SAME_TOP_INTERVAL = 1*60*1000; // The amount of time until PSS when an important process stays in the same state. - private static final int PSS_SAME_IMPORTANT_INTERVAL = 15*60*1000; + private static final int PSS_SAME_IMPORTANT_INTERVAL = 10*60*1000; // The amount of time until PSS when a service process stays in the same state. - private static final int PSS_SAME_SERVICE_INTERVAL = 20*60*1000; + private static final int PSS_SAME_SERVICE_INTERVAL = 5*60*1000; // The amount of time until PSS when a cached process stays in the same state. - private static final int PSS_SAME_CACHED_INTERVAL = 20*60*1000; + private static final int PSS_SAME_CACHED_INTERVAL = 10*60*1000; // The amount of time until PSS when a persistent process first appears. private static final int PSS_FIRST_ASLEEP_PERSISTENT_INTERVAL = 1*60*1000; @@ -622,16 +622,17 @@ public final class ProcessList { public static final class ProcStateMemTracker { final int[] mHighestMem = new int[PROC_MEM_NUM]; + final float[] mScalingFactor = new float[PROC_MEM_NUM]; int mTotalHighestMem = PROC_MEM_CACHED; - float mCurFactor = 1.0f; int mPendingMemState; int mPendingHighestMemState; - boolean mPendingSame; + float mPendingScalingFactor; public ProcStateMemTracker() { for (int i = PROC_MEM_PERSISTENT; i < PROC_MEM_NUM; i++) { mHighestMem[i] = PROC_MEM_NUM; + mScalingFactor[i] = 1.0f; } mPendingMemState = -1; } @@ -639,16 +640,22 @@ public final class ProcessList { public void dumpLine(PrintWriter pw) { pw.print("best="); pw.print(mTotalHighestMem); - pw.print(" "); - pw.print(mCurFactor); - pw.print("x ("); + pw.print(" ("); + boolean needSep = false; for (int i = 0; i < PROC_MEM_NUM; i++) { - if (i != 0) { - pw.print(", "); + if (mHighestMem[i] < PROC_MEM_NUM) { + if (needSep) { + pw.print(", "); + needSep = false; + } + pw.print(i); + pw.print("="); + pw.print(mHighestMem[i]); + pw.print(" "); + pw.print(mScalingFactor[i]); + pw.print("x"); + needSep = true; } - pw.print(i); - pw.print("="); - pw.print(mHighestMem[i]); } pw.print(")"); if (mPendingMemState >= 0) { @@ -656,8 +663,9 @@ public final class ProcessList { pw.print(mPendingMemState); pw.print(" highest="); pw.print(mPendingHighestMemState); - pw.print(" same="); - pw.print(mPendingSame); + pw.print(" "); + pw.print(mPendingScalingFactor); + pw.print("x"); } pw.println(); } @@ -674,12 +682,8 @@ public final class ProcessList { public static void commitNextPssTime(ProcStateMemTracker tracker) { if (tracker.mPendingMemState >= 0) { tracker.mHighestMem[tracker.mPendingMemState] = tracker.mPendingHighestMemState; + tracker.mScalingFactor[tracker.mPendingMemState] = tracker.mPendingScalingFactor; tracker.mTotalHighestMem = tracker.mPendingHighestMemState; - if (tracker.mPendingSame) { - tracker.mCurFactor *= 1.5f; - } else { - tracker.mCurFactor = 1; - } tracker.mPendingMemState = -1; } } @@ -691,6 +695,7 @@ public final class ProcessList { public static long computeNextPssTime(int procState, ProcStateMemTracker tracker, boolean test, boolean sleeping, long now) { boolean first; + float scalingFactor; final int memState = sProcStateToProcMem[procState]; if (tracker != null) { final int highestMemState = memState < tracker.mTotalHighestMem @@ -698,9 +703,15 @@ public final class ProcessList { first = highestMemState < tracker.mHighestMem[memState]; tracker.mPendingMemState = memState; tracker.mPendingHighestMemState = highestMemState; - tracker.mPendingSame = !first; + if (first) { + tracker.mPendingScalingFactor = scalingFactor = 1.0f; + } else { + scalingFactor = tracker.mScalingFactor[memState]; + tracker.mPendingScalingFactor = scalingFactor * 1.5f; + } } else { first = true; + scalingFactor = 1.0f; } final long[] table = test ? (first @@ -709,8 +720,7 @@ public final class ProcessList { : (first ? (sleeping ? sFirstAsleepPssTimes : sFirstAwakePssTimes) : (sleeping ? sSameAsleepPssTimes : sSameAwakePssTimes)); - long delay = (long)(table[memState] * (tracker != null && !first - ? tracker.mCurFactor : 1.0f)); + long delay = (long)(table[memState] * scalingFactor); if (delay > PSS_MAX_INTERVAL) { delay = PSS_MAX_INTERVAL; } diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java index 8bf320e0c3879..edf565abd7df3 100644 --- a/services/core/java/com/android/server/am/ProcessStatsService.java +++ b/services/core/java/com/android/server/am/ProcessStatsService.java @@ -237,6 +237,7 @@ public final class ProcessStatsService extends IProcessStats.Stub { if (commit) { mProcessStats.resetSafely(); updateFile(); + mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); } mLastWriteTime = SystemClock.uptimeMillis(); totalTime = SystemClock.uptimeMillis() - now; @@ -784,12 +785,14 @@ public final class ProcessStatsService extends IProcessStats.Stub { } else if ("--reset".equals(arg)) { synchronized (mAm) { mProcessStats.resetSafely(); + mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); pw.println("Process stats reset."); quit = true; } } else if ("--clear".equals(arg)) { synchronized (mAm) { mProcessStats.resetSafely(); + mAm.requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); ArrayList files = getCommittedFiles(0, true, true); if (files != null) { for (int fi=0; fi