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:
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
Reference in New Issue
Block a user