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

Commit 75a4e3f3 authored by Jing Ji's avatar Jing Ji
Browse files

DO NOT MERGE: Don't take the AM lock in cached app compaction handler

A single oomAdjUpdate pass could trigger quite a few app compactions,
each of them would need to acquire the AM lock during the handling,
results in lock contentions. Now use its own lock. Also skip the
scheduling if the given app is pending with compaction already.

Bug: 163297662
Test: atest CachedAppOptimizerTest
Test: Manual - Boot & check the logs
Change-Id: I4618a3ae78838cd9783a431e7364130270ebb4d6
parent 1c9ac73a
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -2124,7 +2124,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                        0,
                        new HostingRecord("system"));
                app.setPersistent(true);
                app.pid = MY_PID;
                app.pid = app.mPidForCompact = MY_PID;
                app.getWindowProcessController().setPid(MY_PID);
                app.maxAdj = ProcessList.SYSTEM_ADJ;
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
@@ -5105,6 +5105,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        EventLogTags.writeAmProcBound(app.userId, app.pid, app.processName);
        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
        synchronized (mOomAdjuster.mCachedAppOptimizer) {
            app.mSetAdjForCompact = ProcessList.INVALID_ADJ;
        }
        mOomAdjuster.setAttachingSchedGroupLocked(app);
        app.forcingToImportant = null;
        updateProcessForegroundLocked(app, false, 0, false);
+54 −29
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ public final class CachedAppOptimizer {
     */
    final ServiceThread mCachedAppOptimizerThread;

    @GuardedBy("this")
    private final ArrayList<ProcessRecord> mPendingCompactionProcesses =
            new ArrayList<ProcessRecord>();
    private final ActivityManagerService mAm;
@@ -348,52 +349,75 @@ public final class CachedAppOptimizer {

    @GuardedBy("mAm")
    void compactAppSome(ProcessRecord app) {
        synchronized (this) {
            app.reqCompactAction = COMPACT_PROCESS_SOME;
            if (!app.mPendingCompact) {
                app.mPendingCompact = true;
                mPendingCompactionProcesses.add(app);
                mCompactionHandler.sendMessage(
                        mCompactionHandler.obtainMessage(
                        COMPACT_PROCESS_MSG, app.setAdj, app.setProcState));
            }
        }
    }

    @GuardedBy("mAm")
    void compactAppFull(ProcessRecord app) {
        synchronized (this) {
            app.reqCompactAction = COMPACT_PROCESS_FULL;
            if (!app.mPendingCompact) {
                app.mPendingCompact = true;
                mPendingCompactionProcesses.add(app);
                mCompactionHandler.sendMessage(
                        mCompactionHandler.obtainMessage(
                        COMPACT_PROCESS_MSG, app.setAdj, app.setProcState));

            }
        }
    }

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

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

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

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

    @GuardedBy("mAm")
    void compactAllSystem() {
@@ -854,18 +878,19 @@ public final class CachedAppOptimizer {
                    LastCompactionStats lastCompactionStats;
                    int lastOomAdj = msg.arg1;
                    int procState = msg.arg2;
                    synchronized (mAm) {
                    synchronized (CachedAppOptimizer.this) {
                        proc = mPendingCompactionProcesses.remove(0);

                        pendingAction = proc.reqCompactAction;
                        pid = proc.pid;
                        pid = proc.mPidForCompact;
                        name = proc.processName;
                        proc.mPendingCompact = false;

                        // don't compact if the process has returned to perceptible
                        // and this is only a cached/home/prev compaction
                        if ((pendingAction == COMPACT_PROCESS_SOME
                                || pendingAction == COMPACT_PROCESS_FULL)
                                && (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ)) {
                                && (proc.mSetAdjForCompact <= ProcessList.PERCEPTIBLE_APP_ADJ)) {
                            if (DEBUG_COMPACTION) {
                                Slog.d(TAG_AM,
                                        "Skipping compaction as process " + name + " is "
@@ -1052,7 +1077,7 @@ public final class CachedAppOptimizer {
                                    lastOomAdj, ActivityManager.processStateAmToProto(procState),
                                    zramFreeKbBefore, zramFreeKbAfter);
                        }
                        synchronized (mAm) {
                        synchronized (CachedAppOptimizer.this) {
                            proc.lastCompactTime = end;
                            proc.lastCompactAction = pendingAction;
                        }
+3 −0
Original line number Diff line number Diff line
@@ -2198,6 +2198,9 @@ public final class OomAdjuster {
            }
            app.setAdj = app.curAdj;
            app.verifiedAdj = ProcessList.INVALID_ADJ;
            synchronized (mCachedAppOptimizer) {
                app.mSetAdjForCompact = app.setAdj;
            }
        }

        final int curSchedGroup = app.getCurrentSchedulingGroup();
+29 −2
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
@@ -162,8 +163,11 @@ class ProcessRecord implements WindowProcessListener {
    int curCapability;          // Current capability flags of this process. For example,
                                // PROCESS_CAPABILITY_FOREGROUND_LOCATION is one capability.
    int setCapability;          // Last set capability flags.
    @GuardedBy("mService.mOomAdjuster.mCachedAppOptimizer")
    long lastCompactTime;       // The last time that this process was compacted
    @GuardedBy("mService.mOomAdjuster.mCachedAppOptimizer")
    int reqCompactAction;       // The most recent compaction action requested for this app.
    @GuardedBy("mService.mOomAdjuster.mCachedAppOptimizer")
    int lastCompactAction;      // The most recent compaction action performed for this app.
    boolean frozen;             // True when the process is frozen.
    long freezeUnfreezeTime;    // Last time the app was (un)frozen, 0 for never
@@ -352,6 +356,24 @@ class ProcessRecord implements WindowProcessListener {

    boolean mReachable; // Whether or not this process is reachable from given process

    /**
     * The snapshot of {@link #setAdj}, meant to be read by {@link CachedAppOptimizer} only.
     */
    @GuardedBy("mService.mOomAdjuster.mCachedAppOptimizer")
    int mSetAdjForCompact;

    /**
     * The snapshot of {@link #pid}, meant to be read by {@link CachedAppOptimizer} only.
     */
    @GuardedBy("mService.mOomAdjuster.mCachedAppOptimizer")
    int mPidForCompact;

    /**
     * This process has been scheduled for a memory compaction.
     */
    @GuardedBy("mService.mOomAdjuster.mCachedAppOptimizer")
    boolean mPendingCompact;

    void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
            long startTime) {
        this.startUid = startUid;
@@ -447,8 +469,10 @@ class ProcessRecord implements WindowProcessListener {
                pw.print(" setRaw="); pw.print(setRawAdj);
                pw.print(" cur="); pw.print(curAdj);
                pw.print(" set="); pw.println(setAdj);
        synchronized (mService.mOomAdjuster.mCachedAppOptimizer) {
            pw.print(prefix); pw.print("lastCompactTime="); pw.print(lastCompactTime);
            pw.print(" lastCompactAction="); pw.println(lastCompactAction);
        }
        pw.print(prefix); pw.print("mCurSchedGroup="); pw.print(mCurSchedGroup);
                pw.print(" setSchedGroup="); pw.print(setSchedGroup);
                pw.print(" systemNoUi="); pw.print(systemNoUi);
@@ -672,6 +696,9 @@ class ProcessRecord implements WindowProcessListener {

    public void setPid(int _pid) {
        pid = _pid;
        synchronized (mService.mOomAdjuster.mCachedAppOptimizer) {
            mPidForCompact = _pid;
        }
        mWindowProcessController.setPid(pid);
        procStatFile = null;
        shortStringName = null;
+2 −2
Original line number Diff line number Diff line
@@ -134,11 +134,11 @@ public final class CachedAppOptimizerTest {
        ApplicationInfo ai = new ApplicationInfo();
        ai.packageName = packageName;
        ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid);
        app.pid = pid;
        app.pid = app.mPidForCompact = pid;
        app.info.uid = packageUid;
        // Exact value does not mater, it can be any state for which compaction is allowed.
        app.setProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
        app.setAdj = 905;
        app.setAdj = app.mSetAdjForCompact = 905;
        return app;
    }