Merge changes from topic "compaction-improvements"
* changes: Improve compaction to abort when system changes to awake state Improve compaction by skipping bad VMAs instead of fully bailing out Fix for compaction bailing out when MAX_RW_COUNT bytes are sent to compaction
This commit is contained in:
committed by
Android (Google) Code Review
commit
ee7ce221a5
@@ -6681,6 +6681,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
reportCurWakefulnessUsageEvent();
|
||||
mActivityTaskManager.onScreenAwakeChanged(isAwake);
|
||||
mOomAdjProfiler.onWakefulnessChanged(wakefulness);
|
||||
mOomAdjuster.onWakefulnessChanged(wakefulness);
|
||||
}
|
||||
updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.net.Uri;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManagerInternal;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Trace;
|
||||
@@ -1051,6 +1052,15 @@ public final class CachedAppOptimizer {
|
||||
}
|
||||
}
|
||||
|
||||
void onWakefulnessChanged(int wakefulness) {
|
||||
if(wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE) {
|
||||
// Remove any pending compaction we may have scheduled to happen while screen was off
|
||||
Slog.e(TAG_AM, "Cancel pending or running compactions as system is awake");
|
||||
mPendingCompactionProcesses.clear();
|
||||
cancelCompaction();
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy({"mService", "mProcLock"})
|
||||
void onOomAdjustChanged(int oldAdj, int newAdj, ProcessRecord app) {
|
||||
// Cancel any currently executing compactions
|
||||
|
||||
@@ -2470,6 +2470,10 @@ public class OomAdjuster {
|
||||
}
|
||||
}
|
||||
|
||||
void onWakefulnessChanged(int wakefulness) {
|
||||
mCachedAppOptimizer.onWakefulnessChanged(wakefulness);
|
||||
}
|
||||
|
||||
/** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
|
||||
@GuardedBy({"mService", "mProcLock"})
|
||||
private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now,
|
||||
|
||||
@@ -57,6 +57,19 @@ using android::base::unique_fd;
|
||||
#define ASYNC_RECEIVED_WHILE_FROZEN (2)
|
||||
#define TXNS_PENDING_WHILE_FROZEN (4)
|
||||
|
||||
#define MAX_RW_COUNT (INT_MAX & PAGE_MASK)
|
||||
|
||||
// Defines the maximum amount of VMAs we can send per process_madvise syscall.
|
||||
// Currently this is set to UIO_MAXIOV which is the maximum segments allowed by
|
||||
// iovec implementation used by process_madvise syscall
|
||||
#define MAX_VMAS_PER_COMPACTION UIO_MAXIOV
|
||||
|
||||
// Maximum bytes that we can send per process_madvise syscall once this limit
|
||||
// is reached we split the remaining VMAs into another syscall. The MAX_RW_COUNT
|
||||
// limit is imposed by iovec implementation. However, if you want to use a smaller
|
||||
// limit, it has to be a page aligned value, otherwise, compaction would fail.
|
||||
#define MAX_BYTES_PER_COMPACTION MAX_RW_COUNT
|
||||
|
||||
namespace android {
|
||||
|
||||
static bool cancelRunningCompaction;
|
||||
@@ -70,12 +83,12 @@ static inline void compactProcessProcfs(int pid, const std::string& compactionTy
|
||||
}
|
||||
|
||||
// Compacts a set of VMAs for pid using an madviseType accepted by process_madvise syscall
|
||||
// On success returns the total bytes that where compacted. On failure it returns
|
||||
// a negative error code from the standard linux error codes.
|
||||
// Returns the total bytes that where madvised.
|
||||
//
|
||||
// If any VMA fails compaction due to -EINVAL it will be skipped and continue.
|
||||
// However, if it fails for any other reason, it will bail out and forward the error
|
||||
static int64_t compactMemory(const std::vector<Vma>& vmas, int pid, int madviseType) {
|
||||
// UIO_MAXIOV is currently a small value and we might have more addresses
|
||||
// we do multiple syscalls if we exceed its maximum
|
||||
static struct iovec vmasToKernel[UIO_MAXIOV];
|
||||
static struct iovec vmasToKernel[MAX_VMAS_PER_COMPACTION];
|
||||
|
||||
if (vmas.empty()) {
|
||||
return 0;
|
||||
@@ -89,33 +102,72 @@ static int64_t compactMemory(const std::vector<Vma>& vmas, int pid, int madviseT
|
||||
compactionInProgress = true;
|
||||
cancelRunningCompaction = false;
|
||||
|
||||
int64_t totalBytesCompacted = 0;
|
||||
for (int iBase = 0; iBase < vmas.size(); iBase += UIO_MAXIOV) {
|
||||
if (CC_UNLIKELY(cancelRunningCompaction)) {
|
||||
// There could be a significant delay betweenwhen a compaction
|
||||
// is requested and when it is handled during this time
|
||||
// our OOM adjust could have improved.
|
||||
int64_t totalBytesProcessed = 0;
|
||||
|
||||
int64_t vmaOffset = 0;
|
||||
for (int iVma = 0; iVma < vmas.size();) {
|
||||
uint64_t bytesSentToCompact = 0;
|
||||
int iVec = 0;
|
||||
while (iVec < MAX_VMAS_PER_COMPACTION && iVma < vmas.size()) {
|
||||
if (CC_UNLIKELY(cancelRunningCompaction)) {
|
||||
// There could be a significant delay between when a compaction
|
||||
// is requested and when it is handled during this time our
|
||||
// OOM adjust could have improved.
|
||||
LOG(DEBUG) << "Cancelled running compaction for " << pid;
|
||||
break;
|
||||
}
|
||||
|
||||
uint64_t vmaStart = vmas[iVma].start + vmaOffset;
|
||||
uint64_t vmaSize = vmas[iVma].end - vmaStart;
|
||||
if (vmaSize == 0) {
|
||||
goto next_vma;
|
||||
}
|
||||
vmasToKernel[iVec].iov_base = (void*)vmaStart;
|
||||
if (vmaSize > MAX_BYTES_PER_COMPACTION - bytesSentToCompact) {
|
||||
// Exceeded the max bytes that could be sent, so clamp
|
||||
// the end to avoid exceeding limit and issue compaction
|
||||
vmaSize = MAX_BYTES_PER_COMPACTION - bytesSentToCompact;
|
||||
}
|
||||
|
||||
vmasToKernel[iVec].iov_len = vmaSize;
|
||||
bytesSentToCompact += vmaSize;
|
||||
++iVec;
|
||||
if (bytesSentToCompact >= MAX_BYTES_PER_COMPACTION) {
|
||||
// Ran out of bytes within iovec, dispatch compaction.
|
||||
vmaOffset += vmaSize;
|
||||
break;
|
||||
}
|
||||
|
||||
next_vma:
|
||||
// Finished current VMA, and have more bytes remaining
|
||||
vmaOffset = 0;
|
||||
++iVma;
|
||||
}
|
||||
|
||||
if (cancelRunningCompaction) {
|
||||
cancelRunningCompaction = false;
|
||||
break;
|
||||
}
|
||||
int totalVmasToKernel = std::min(UIO_MAXIOV, (int)(vmas.size() - iBase));
|
||||
for (int iVec = 0, iVma = iBase; iVec < totalVmasToKernel; ++iVec, ++iVma) {
|
||||
vmasToKernel[iVec].iov_base = (void*)vmas[iVma].start;
|
||||
vmasToKernel[iVec].iov_len = vmas[iVma].end - vmas[iVma].start;
|
||||
|
||||
auto bytesProcessed = process_madvise(pidfd, vmasToKernel, iVec, madviseType, 0);
|
||||
|
||||
if (CC_UNLIKELY(bytesProcessed == -1)) {
|
||||
if (errno == EINVAL) {
|
||||
// This error is somewhat common due to an unevictable VMA if this is
|
||||
// the case silently skip the bad VMA and continue compacting the rest.
|
||||
continue;
|
||||
} else {
|
||||
// Forward irrecoverable errors and bail out compaction
|
||||
compactionInProgress = false;
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
auto bytesCompacted =
|
||||
process_madvise(pidfd, vmasToKernel, totalVmasToKernel, madviseType, 0);
|
||||
if (CC_UNLIKELY(bytesCompacted == -1)) {
|
||||
compactionInProgress = false;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
totalBytesCompacted += bytesCompacted;
|
||||
totalBytesProcessed += bytesProcessed;
|
||||
}
|
||||
compactionInProgress = false;
|
||||
|
||||
return totalBytesCompacted;
|
||||
return totalBytesProcessed;
|
||||
}
|
||||
|
||||
static int getFilePageAdvice(const Vma& vma) {
|
||||
@@ -138,7 +190,12 @@ static int getAnyPageAdvice(const Vma& vma) {
|
||||
}
|
||||
|
||||
// Perform a full process compaction using process_madvise syscall
|
||||
// reading all filtering VMAs and filtering pages as specified by pageFilter
|
||||
// using the madvise behavior defined by vmaToAdviseFunc per VMA.
|
||||
//
|
||||
// Currently supported behaviors are MADV_COLD and MADV_PAGEOUT.
|
||||
//
|
||||
// Returns the total number of bytes compacted or forwards an
|
||||
// process_madvise error.
|
||||
static int64_t compactProcess(int pid, VmaToAdviseFunc vmaToAdviseFunc) {
|
||||
ProcMemInfo meminfo(pid);
|
||||
std::vector<Vma> pageoutVmas, coldVmas;
|
||||
|
||||
Reference in New Issue
Block a user