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
This commit is contained in:
Dianne Hackborn
2018-02-06 16:01:23 -08:00
parent 27a6db482e
commit ed0a3220ce
3 changed files with 63 additions and 44 deletions

View File

@@ -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));
}

View File

@@ -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;
}

View File

@@ -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<String> files = getCommittedFiles(0, true, true);
if (files != null) {
for (int fi=0; fi<files.size(); fi++) {