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

Commit 532e4944 authored by Rafal Slawik's avatar Rafal Slawik Committed by Android (Google) Code Review
Browse files

Merge "Monitor swap"

parents 6921be04 65a9b712
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -3801,7 +3801,7 @@ message ProcessMemoryState {

    // SWAP
    // Value is read from memory.stat, field total_swap if per-app memory
    // cgroups are enabled. Otherwise, 0.
    // cgroups are enabled. Otherwise, VmSwap from /proc/PID/status.
    optional int64 swap_in_bytes = 8;

    // Deprecated: use ProcessMemoryHighWaterMark atom instead. Always 0.
@@ -3841,6 +3841,10 @@ message NativeProcessMemoryState {
    // Elapsed real time when the process started.
    // Value is read from /proc/PID/stat, field 22.
    optional int64 start_time_nanos = 7;

    // SWAP
    // Value read from /proc/PID/status, field VmSwap.
    optional int64 swap_in_bytes = 8;
}

/*
+1 −1
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
          .puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
        // native_process_memory_state
        {android::util::NATIVE_PROCESS_MEMORY_STATE,
         {.additiveFields = {3, 4, 5, 6},
         {.additiveFields = {3, 4, 5, 6, 8},
          .puller = new StatsCompanionServicePuller(android::util::NATIVE_PROCESS_MEMORY_STATE)}},
        // process_memory_high_water_mark
        {android::util::PROCESS_MEMORY_HIGH_WATER_MARK,
+20 −7
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ import java.util.regex.Pattern;
 */
public final class MemoryStatUtil {
    static final int BYTES_IN_KILOBYTE = 1024;
    static final int PAGE_SIZE = 4096;
    static final long JIFFY_NANOS = 1_000_000_000 / Os.sysconf(OsConstants._SC_CLK_TCK);

    private static final String TAG = TAG_WITH_CLASS_NAME ? "MemoryStatUtil" : TAG_AM;
@@ -65,15 +64,20 @@ public final class MemoryStatUtil {
    private static final Pattern RSS_IN_BYTES = Pattern.compile("total_rss (\\d+)");
    private static final Pattern CACHE_IN_BYTES = Pattern.compile("total_cache (\\d+)");
    private static final Pattern SWAP_IN_BYTES = Pattern.compile("total_swap (\\d+)");
    private static final Pattern RSS_HIGH_WATERMARK_IN_BYTES =

    private static final Pattern RSS_HIGH_WATERMARK_IN_KILOBYTES =
            Pattern.compile("VmHWM:\\s*(\\d+)\\s*kB");
    private static final Pattern PROCFS_RSS_IN_KILOBYTES =
            Pattern.compile("VmRSS:\\s*(\\d+)\\s*kB");
    private static final Pattern PROCFS_SWAP_IN_KILOBYTES =
            Pattern.compile("VmSwap:\\s*(\\d+)\\s*kB");

    private static final Pattern ION_HEAP_SIZE_IN_BYTES =
            Pattern.compile("\n\\s*total\\s*(\\d+)\\s*\n");

    private static final int PGFAULT_INDEX = 9;
    private static final int PGMAJFAULT_INDEX = 11;
    private static final int START_TIME_INDEX = 21;
    private static final int RSS_IN_PAGES_INDEX = 23;

    private MemoryStatUtil() {}

@@ -107,7 +111,8 @@ public final class MemoryStatUtil {
    @Nullable
    public static MemoryStat readMemoryStatFromProcfs(int pid) {
        final String statPath = String.format(Locale.US, PROC_STAT_FILE_FMT, pid);
        return parseMemoryStatFromProcfs(readFileContents(statPath));
        final String statusPath = String.format(Locale.US, PROC_STATUS_FILE_FMT, pid);
        return parseMemoryStatFromProcfs(readFileContents(statPath), readFileContents(statusPath));
    }

    /**
@@ -179,10 +184,14 @@ public final class MemoryStatUtil {
     */
    @VisibleForTesting
    @Nullable
    static MemoryStat parseMemoryStatFromProcfs(String procStatContents) {
    static MemoryStat parseMemoryStatFromProcfs(
            String procStatContents, String procStatusContents) {
        if (procStatContents == null || procStatContents.isEmpty()) {
            return null;
        }
        if (procStatusContents == null || procStatusContents.isEmpty()) {
            return null;
        }

        final String[] splits = procStatContents.split(" ");
        if (splits.length < 24) {
@@ -193,7 +202,10 @@ public final class MemoryStatUtil {
            final MemoryStat memoryStat = new MemoryStat();
            memoryStat.pgfault = Long.parseLong(splits[PGFAULT_INDEX]);
            memoryStat.pgmajfault = Long.parseLong(splits[PGMAJFAULT_INDEX]);
            memoryStat.rssInBytes = Long.parseLong(splits[RSS_IN_PAGES_INDEX]) * PAGE_SIZE;
            memoryStat.rssInBytes =
                tryParseLong(PROCFS_RSS_IN_KILOBYTES, procStatusContents) * BYTES_IN_KILOBYTE;
            memoryStat.swapInBytes =
                tryParseLong(PROCFS_SWAP_IN_KILOBYTES, procStatusContents) * BYTES_IN_KILOBYTE;
            memoryStat.startTimeNanos = Long.parseLong(splits[START_TIME_INDEX]) * JIFFY_NANOS;
            return memoryStat;
        } catch (NumberFormatException e) {
@@ -212,7 +224,8 @@ public final class MemoryStatUtil {
            return 0;
        }
        // Convert value read from /proc/pid/status from kilobytes to bytes.
        return tryParseLong(RSS_HIGH_WATERMARK_IN_BYTES, procStatusContents) * BYTES_IN_KILOBYTE;
        return tryParseLong(RSS_HIGH_WATERMARK_IN_KILOBYTES, procStatusContents)
                * BYTES_IN_KILOBYTE;
    }


+1 −0
Original line number Diff line number Diff line
@@ -1159,6 +1159,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
            e.writeLong(memoryStat.rssInBytes);
            e.writeLong(0);  // unused
            e.writeLong(memoryStat.startTimeNanos);
            e.writeLong(memoryStat.swapInBytes);
            pulledData.add(e);
        }
    }
+16 −11
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server.am;
import static com.android.server.am.MemoryStatUtil.BYTES_IN_KILOBYTE;
import static com.android.server.am.MemoryStatUtil.JIFFY_NANOS;
import static com.android.server.am.MemoryStatUtil.MemoryStat;
import static com.android.server.am.MemoryStatUtil.PAGE_SIZE;
import static com.android.server.am.MemoryStatUtil.parseCmdlineFromProcfs;
import static com.android.server.am.MemoryStatUtil.parseIonHeapSizeFromDebugfs;
import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromMemcg;
@@ -102,7 +101,7 @@ public class MemoryStatUtilTest {
            "0",
            "2222", // this in start time (in ticks per second)
            "1257177088",
            "3", // this is RSS (number of pages)
            "3",
            "4294967295",
            "2936971264",
            "2936991289",
@@ -147,8 +146,8 @@ public class MemoryStatUtilTest {
            + "VmSize:\t 4542636 kB\n"
            + "VmLck:\t       0 kB\n"
            + "VmPin:\t       0 kB\n"
            + "VmHWM:\t  137668 kB\n" // RSS high watermark
            + "VmRSS:\t  126776 kB\n"
            + "VmHWM:\t  137668 kB\n" // RSS high-water mark
            + "VmRSS:\t  126776 kB\n" // RSS
            + "RssAnon:\t   37860 kB\n"
            + "RssFile:\t   88764 kB\n"
            + "RssShmem:\t     152 kB\n"
@@ -158,7 +157,7 @@ public class MemoryStatUtilTest {
            + "VmLib:\t  102432 kB\n"
            + "VmPTE:\t    1300 kB\n"
            + "VmPMD:\t      36 kB\n"
            + "VmSwap:\t       0 kB\n"
            + "VmSwap:\t      22 kB\n" // Swap
            + "Threads:\t95\n"
            + "SigQ:\t0/13641\n"
            + "SigPnd:\t0000000000000000\n"
@@ -227,28 +226,34 @@ public class MemoryStatUtilTest {

    @Test
    public void testParseMemoryStatFromProcfs_parsesCorrectValues() {
        MemoryStat stat = parseMemoryStatFromProcfs(PROC_STAT_CONTENTS);
        MemoryStat stat = parseMemoryStatFromProcfs(PROC_STAT_CONTENTS, PROC_STATUS_CONTENTS);
        assertEquals(1, stat.pgfault);
        assertEquals(2, stat.pgmajfault);
        assertEquals(3 * PAGE_SIZE, stat.rssInBytes);
        assertEquals(126776 * BYTES_IN_KILOBYTE, stat.rssInBytes);
        assertEquals(0, stat.cacheInBytes);
        assertEquals(0, stat.swapInBytes);
        assertEquals(22 * BYTES_IN_KILOBYTE, stat.swapInBytes);
        assertEquals(2222 * JIFFY_NANOS, stat.startTimeNanos);
    }

    @Test
    public void testParseMemoryStatFromProcfs_emptyContents() {
        MemoryStat stat = parseMemoryStatFromProcfs("");
        MemoryStat stat = parseMemoryStatFromProcfs("", PROC_STATUS_CONTENTS);
        assertNull(stat);

        stat = parseMemoryStatFromProcfs(null);
        stat = parseMemoryStatFromProcfs(null, PROC_STATUS_CONTENTS);
        assertNull(stat);

        stat = parseMemoryStatFromProcfs(PROC_STAT_CONTENTS, "");
        assertNull(stat);

        stat = parseMemoryStatFromProcfs(PROC_STAT_CONTENTS, null);
        assertNull(stat);
    }

    @Test
    public void testParseMemoryStatFromProcfs_invalidValue() {
        String contents = String.join(" ", Collections.nCopies(24, "memory"));
        assertNull(parseMemoryStatFromProcfs(contents));
        assertNull(parseMemoryStatFromProcfs(contents, PROC_STATUS_CONTENTS));
    }

    @Test