Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf3f369e authored by Tim Murray's avatar Tim Murray
Browse files

Compact persistent and BFGS processes.

Persistent and BFGS processes are large contributors to memory consumption,
but they often need a much smaller working set than they have allocated.
Compact them preemptively to prevent LMKs.

Test: boots, works
bug 125346716
bug 119988524

Change-Id: I20af99e1932c262272388e99b79d12e8f10a1e07
parent 53cc8bf1
Loading
Loading
Loading
Loading
+99 −24
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ public final class AppCompactor {
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2";
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3";
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4";
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_5 = "compact_throttle_5";
    @VisibleForTesting static final String KEY_COMPACT_THROTTLE_6 = "compact_throttle_6";
    @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE =
            "compact_statsd_sample_rate";

@@ -73,6 +75,8 @@ public final class AppCompactor {
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000;
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_4 = 10_000;
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_5 = 10 * 60 * 1000;
    @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_6 = 10 * 60 * 1000;
    // The sampling rate to push app compaction events into statsd for upload.
    @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f;

@@ -85,6 +89,8 @@ public final class AppCompactor {
    // Handler constants.
    static final int COMPACT_PROCESS_SOME = 1;
    static final int COMPACT_PROCESS_FULL = 2;
    static final int COMPACT_PROCESS_PERSISTENT = 3;
    static final int COMPACT_PROCESS_BFGS = 4;
    static final int COMPACT_PROCESS_MSG = 1;

    /**
@@ -142,6 +148,10 @@ public final class AppCompactor {
    @GuardedBy("mPhenotypeFlagLock")
    @VisibleForTesting volatile long mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
    @GuardedBy("mPhenotypeFlagLock")
    @VisibleForTesting volatile long mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5;
    @GuardedBy("mPhenotypeFlagLock")
    @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
    @GuardedBy("mPhenotypeFlagLock")
    private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;

    private final Random mRandom = new Random();
@@ -224,6 +234,36 @@ public final class AppCompactor {

    }

    @GuardedBy("mAm")
    void compactAppPersistent(ProcessRecord app) {
        app.reqCompactAction = COMPACT_PROCESS_PERSISTENT;
        mPendingCompactionProcesses.add(app);
        mCompactionHandler.sendMessage(
                mCompactionHandler.obtainMessage(
                    COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
    }

    @GuardedBy("mAm")
    boolean shouldCompactPersistent(ProcessRecord app, long now) {
        return (app.lastCompactTime == 0
                || (now - app.lastCompactTime) > mCompactThrottlePersistent);
    }

    @GuardedBy("mAm")
    void compactAppBfgs(ProcessRecord app) {
        app.reqCompactAction = COMPACT_PROCESS_BFGS;
        mPendingCompactionProcesses.add(app);
        mCompactionHandler.sendMessage(
                mCompactionHandler.obtainMessage(
                    COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
    }

    @GuardedBy("mAm")
    boolean shouldCompactBFGS(ProcessRecord app, long now) {
        return (app.lastCompactTime == 0
                || (now - app.lastCompactTime) > mCompactThrottleBFGS);
    }

    /**
     * Reads the flag value from DeviceConfig to determine whether app compaction
     * should be enabled, and starts/stops the compaction thread as needed.
@@ -265,10 +305,18 @@ public final class AppCompactor {
        String throttleFullFullFlag =
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_COMPACT_THROTTLE_4);
        String throttleBFGSFlag =
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_COMPACT_THROTTLE_5);
        String throttlePersistentFlag =
                DeviceConfig.getProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_COMPACT_THROTTLE_6);

        if (TextUtils.isEmpty(throttleSomeSomeFlag) || TextUtils.isEmpty(throttleSomeFullFlag)
                || TextUtils.isEmpty(throttleFullSomeFlag)
                || TextUtils.isEmpty(throttleFullFullFlag)) {
                || TextUtils.isEmpty(throttleFullFullFlag)
                || TextUtils.isEmpty(throttleBFGSFlag)
                || TextUtils.isEmpty(throttlePersistentFlag)) {
            // Set defaults for all if any are not set.
            useThrottleDefaults = true;
        } else {
@@ -277,6 +325,8 @@ public final class AppCompactor {
                mCompactThrottleSomeFull = Integer.parseInt(throttleSomeFullFlag);
                mCompactThrottleFullSome = Integer.parseInt(throttleFullSomeFlag);
                mCompactThrottleFullFull = Integer.parseInt(throttleFullFullFlag);
                mCompactThrottleBFGS = Integer.parseInt(throttleBFGSFlag);
                mCompactThrottlePersistent = Integer.parseInt(throttlePersistentFlag);
            } catch (NumberFormatException e) {
                useThrottleDefaults = true;
            }
@@ -287,6 +337,8 @@ public final class AppCompactor {
            mCompactThrottleSomeFull = DEFAULT_COMPACT_THROTTLE_2;
            mCompactThrottleFullSome = DEFAULT_COMPACT_THROTTLE_3;
            mCompactThrottleFullFull = DEFAULT_COMPACT_THROTTLE_4;
            mCompactThrottleBFGS = DEFAULT_COMPACT_THROTTLE_5;
            mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
        }
    }

@@ -332,14 +384,19 @@ public final class AppCompactor {
                    synchronized (mAm) {
                        proc = mPendingCompactionProcesses.remove(0);

                        pendingAction = proc.reqCompactAction;

                        // don't compact if the process has returned to perceptible
                        if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                        // and this is only a cached/home/prev compaction
                        if ((pendingAction == COMPACT_PROCESS_SOME
                                || pendingAction == COMPACT_PROCESS_FULL)
                                && (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ)) {
                            return;
                        }

                        pid = proc.pid;
                        name = proc.processName;
                        pendingAction = proc.reqCompactAction;

                        lastCompactAction = proc.lastCompactAction;
                        lastCompactTime = proc.lastCompactTime;
                    }
@@ -356,6 +413,7 @@ public final class AppCompactor {
                    // Note that we explicitly don't take mPhenotypeFlagLock here as the flags
                    // should very seldom change, and taking the risk of using the wrong action is
                    // preferable to taking the lock for every single compaction action.
                    if (lastCompactTime != 0) {
                        if (pendingAction == COMPACT_PROCESS_SOME) {
                            if ((lastCompactAction == COMPACT_PROCESS_SOME
                                    && (start - lastCompactTime < mCompactThrottleSomeSome))
@@ -364,7 +422,7 @@ public final class AppCompactor {
                                                < mCompactThrottleSomeFull))) {
                                return;
                            }
                    } else {
                        } else if (pendingAction == COMPACT_PROCESS_FULL) {
                            if ((lastCompactAction == COMPACT_PROCESS_SOME
                                    && (start - lastCompactTime < mCompactThrottleFullSome))
                                    || (lastCompactAction == COMPACT_PROCESS_FULL
@@ -372,15 +430,32 @@ public final class AppCompactor {
                                                < mCompactThrottleFullFull))) {
                                return;
                            }
                        } else if (pendingAction == COMPACT_PROCESS_PERSISTENT) {
                            if (start - lastCompactTime < mCompactThrottlePersistent) {
                                return;
                            }

                    if (pendingAction == COMPACT_PROCESS_SOME) {
                        } else if (pendingAction == COMPACT_PROCESS_BFGS) {
                            if (start - lastCompactTime < mCompactThrottleBFGS) {
                                return;
                            }
                        }
                    }
                    switch (pendingAction) {
                        case COMPACT_PROCESS_SOME:
                            action = mCompactActionSome;
                    } else {
                            break;
                        // For the time being, treat these as equivalent.
                        case COMPACT_PROCESS_FULL:
                        case COMPACT_PROCESS_PERSISTENT:
                        case COMPACT_PROCESS_BFGS:
                            action = mCompactActionFull;
                            break;
                        default:
                            action = COMPACT_ACTION_NONE;
                            break;
                    }

                    if (action.equals(COMPACT_ACTION_NONE)) {
                    if (COMPACT_ACTION_NONE.equals(action)) {
                        return;
                    }

+20 −3
Original line number Diff line number Diff line
@@ -1686,9 +1686,10 @@ public final class OomAdjuster {

        int changes = 0;

        if (app.curAdj != app.setAdj) {
        // don't compact during bootup
        if (mAppCompact.useCompaction() && mService.mBooted) {
            // Cached and prev/home compaction
            if (app.curAdj != app.setAdj) {
                // Perform a minor compaction when a perceptible app becomes the prev/home app
                // Perform a major compaction when any app enters cached
                // reminder: here, setAdj is previous state, curAdj is upcoming state
@@ -1702,7 +1703,23 @@ public final class OomAdjuster {
                        && app.curAdj <= ProcessList.CACHED_APP_MAX_ADJ) {
                    mAppCompact.compactAppFull(app);
                }
            } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE
                    && app.setAdj < ProcessList.FOREGROUND_APP_ADJ
                    // Because these can fire independent of oom_adj/procstate changes, we need
                    // to throttle the actual dispatch of these requests in addition to the
                    // processing of the requests. As a result, there is throttling both here
                    // and in AppCompactor.
                    && mAppCompact.shouldCompactPersistent(app, now)) {
                mAppCompact.compactAppPersistent(app);
            } else if (mService.mWakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE
                    && app.getCurProcState()
                        == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
                    && mAppCompact.shouldCompactBFGS(app, now)) {
                mAppCompact.compactAppBfgs(app);
            }
        }

        if (app.curAdj != app.setAdj) {
            ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
            if (DEBUG_SWITCH || DEBUG_OOM_ADJ || mService.mCurOomAdjUid == app.info.uid) {
                String msg = "Set " + app.pid + " " + app.processName + " adj "