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

Commit b446ce58 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Handle groups and importance in cached oom_adj distribution.

The code for distributing the oom_adj level across the cached
processes now takes in to account the group and importance as
it goes through them, to keep groups together.

As part of this, increase the number of cached oom_adj slots
we have to 100, allowing more room for distributing regular
processes and space between them for applying importance.  This
gives 5 slots for importance levels; if someone uses more than
5, all of the lower ones will get stuck together at the end.

Test: atest CtsAppTestCases:ServiceTest\#testActivityServiceBindingLru
Bug: 111434506
Change-Id: Ia4ec0552b824a031c2a2d62c9e42ebf446e3e5c3
parent 16171a30
Loading
Loading
Loading
Loading
+59 −32
Original line number Diff line number Diff line
@@ -17532,8 +17532,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        // how many slots we have for background processes; we may want
        // to put multiple processes in a slot of there are enough of
        // them.
        int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
                - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
        final int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
                - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2
                / ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
        int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
        if (numEmptyProcs > cachedProcessLimit) {
            // If there are more empty processes than our limit on cached
@@ -17544,17 +17545,19 @@ public class ActivityManagerService extends IActivityManager.Stub
            // instead of a gazillion empty processes.
            numEmptyProcs = cachedProcessLimit;
        }
        int emptyFactor = numEmptyProcs/numSlots;
        int emptyFactor = (numEmptyProcs + numSlots - 1) / numSlots;
        if (emptyFactor < 1) emptyFactor = 1;
        int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
        int cachedFactor = (mNumCachedHiddenProcs > 0 ? (mNumCachedHiddenProcs + numSlots - 1) : 1)
                / numSlots;
        if (cachedFactor < 1) cachedFactor = 1;
        int stepCached = 0;
        int stepEmpty = 0;
        int stepCached = -1;
        int stepEmpty = -1;
        int numCached = 0;
        int numCachedExtraGroup = 0;
        int numEmpty = 0;
        int numTrimming = 0;
        int lastCachedGroup = 0;
        int lastCachedGroupImportance = 0;
        int lastCachedGroupUid = 0;
        mNumNonCachedProcs = 0;
@@ -17563,9 +17566,10 @@ public class ActivityManagerService extends IActivityManager.Stub
        // First update the OOM adjustment for each of the
        // application processes based on their current state.
        int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
        int nextCachedAdj = curCachedAdj+1;
        int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
        int nextEmptyAdj = curEmptyAdj+2;
        int nextCachedAdj = curCachedAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
        int curCachedImpAdj = 0;
        int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
        int nextEmptyAdj = curEmptyAdj + (ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2);
        boolean retryCycles = false;
@@ -17590,53 +17594,74 @@ public class ActivityManagerService extends IActivityManager.Stub
                        case PROCESS_STATE_CACHED_ACTIVITY:
                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                        case ActivityManager.PROCESS_STATE_CACHED_RECENT:
                            // This process is a cached process holding activities...
                            // assign it the next cached value for that type, and then
                            // step that cached level.
                            app.setCurRawAdj(curCachedAdj);
                            app.curAdj = app.modifyRawOomAdj(curCachedAdj);
                            if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
                                    + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
                                    + ")");
                            if (curCachedAdj != nextCachedAdj) {
                            // Figure out the next cached level, taking into account groups.
                            boolean inGroup = false;
                            if (app.connectionGroup != 0) {
                                if (lastCachedGroupUid == app.uid
                                        && lastCachedGroup == app.connectionGroup) {
                                    // This is in the same group as the last process, just tweak
                                    // adjustment by importance.
                                    if (app.connectionImportance > lastCachedGroupImportance) {
                                        lastCachedGroupImportance = app.connectionImportance;
                                        if (curCachedAdj < nextCachedAdj
                                                && curCachedAdj < ProcessList.CACHED_APP_MAX_ADJ) {
                                            curCachedImpAdj++;
                                        }
                                    }
                                    inGroup = true;
                                } else {
                                    lastCachedGroupUid = app.uid;
                                    lastCachedGroup = app.connectionGroup;
                                    lastCachedGroupImportance = app.connectionImportance;
                                }
                            }
                            if (!inGroup && curCachedAdj != nextCachedAdj) {
                                stepCached++;
                                curCachedImpAdj = 0;
                                if (stepCached >= cachedFactor) {
                                    stepCached = 0;
                                    curCachedAdj = nextCachedAdj;
                                    nextCachedAdj += 2;
                                    nextCachedAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
                                    if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                        nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                    }
                                }
                            }
                            // This process is a cached process holding activities...
                            // assign it the next cached value for that type, and then
                            // step that cached level.
                            app.setCurRawAdj(curCachedAdj + curCachedImpAdj);
                            app.curAdj = app.modifyRawOomAdj(curCachedAdj + curCachedImpAdj);
                            if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
                                    + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
                                    + " curCachedImpAdj=" + curCachedImpAdj + ")");
                            break;
                        default:
                            // For everything else, assign next empty cached process
                            // level and bump that up.  Note that this means that
                            // long-running services that have dropped down to the
                            // cached level will be treated as empty (since their process
                            // state is still as a service), which is what we want.
                            app.setCurRawAdj(curEmptyAdj);
                            app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                            if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
                                    + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
                                    + ")");
                            // Figure out the next cached level.
                            if (curEmptyAdj != nextEmptyAdj) {
                                stepEmpty++;
                                if (stepEmpty >= emptyFactor) {
                                    stepEmpty = 0;
                                    curEmptyAdj = nextEmptyAdj;
                                    nextEmptyAdj += 2;
                                    nextEmptyAdj += ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
                                    if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                        nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                    }
                                }
                            }
                            // For everything else, assign next empty cached process
                            // level and bump that up.  Note that this means that
                            // long-running services that have dropped down to the
                            // cached level will be treated as empty (since their process
                            // state is still as a service), which is what we want.
                            app.setCurRawAdj(curEmptyAdj);
                            app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                            if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
                                    + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
                                    + ")");
                            break;
                    }
                }
            }
        }
@@ -17668,6 +17693,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        lastCachedGroup = lastCachedGroupUid = 0;
        for (int i=N-1; i>=0; i--) {
            ProcessRecord app = mProcessList.mLruProcesses.get(i);
            if (!app.killedByAm && app.thread != null) {
+5 −1
Original line number Diff line number Diff line
@@ -137,9 +137,13 @@ public final class ProcessList {

    // This is a process only hosting activities that are not visible,
    // so it can be killed without any disruption.
    static final int CACHED_APP_MAX_ADJ = 906;
    static final int CACHED_APP_MAX_ADJ = 999;
    static final int CACHED_APP_MIN_ADJ = 900;

    // Number of levels we have available for different service connection group importance
    // levels.
    static final int CACHED_APP_IMPORTANCE_LEVELS = 5;

    // The B list of SERVICE_ADJ -- these are the old and decrepit
    // services that aren't as shiny and interesting as the ones in the A list.
    static final int SERVICE_B_ADJ = 800;