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

Commit 203c3dbd authored by Rafal Slawik's avatar Rafal Slawik
Browse files

Cleanup: remove old memory atoms

Memory stats has been migrated to ProcessMemorySnapshot. This CL cleans
up the old atoms:
- remove telemetry-specific additions to ProcessMemoryState
- remove NativeProcessMemoryState atom
- move reading process cmdline under stats

Bug: 140986627
Test: atest MemoryStatUtilTest
Test: atest ProcfsMemoryUtilTest
Test: atest UidAtomTests#testProcessMemoryState
Change-Id: I5339577184d17e5cef6d657cf9b08a2fb8e75fca
parent 64247a16
Loading
Loading
Loading
Loading
+10 −48
Original line number Diff line number Diff line
@@ -378,7 +378,6 @@ message Atom {
        PowerProfile power_profile = 10033;
        ProcStatsPkgProc proc_stats_pkg_proc = 10034;
        ProcessCpuTime process_cpu_time = 10035;
        NativeProcessMemoryState native_process_memory_state = 10036;
        CpuTimePerThreadFreq cpu_time_per_thread_freq = 10037;
        OnDevicePowerMeasurement on_device_power_measurement = 10038;
        DeviceCalculatedPowerUse device_calculated_power_use = 10039;
@@ -412,6 +411,8 @@ message Atom {
    // DO NOT USE field numbers above 100,000 in AOSP.
    // Field numbers 100,000 - 199,999 are reserved for non-AOSP (e.g. OEMs) to use.
    // Field numbers 200,000 and above are reserved for future use; do not use them at all.

    reserved 10036;
}

/**
@@ -4019,8 +4020,8 @@ message ProcessMemoryState {
    optional int64 page_major_fault = 5;

    // RSS
    // Value is read from /proc/PID/status. Or from memory.stat, field
    // total_rss if per-app memory cgroups are enabled.
    // Value is read from memory.stat, field total_rss if per-app memory
    // cgroups are enabled. Otherwise, value from /proc/pid/stat.
    optional int64 rss_in_bytes = 6;

    // CACHE
@@ -4030,56 +4031,17 @@ message ProcessMemoryState {

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

    // Deprecated: use ProcessMemoryHighWaterMark atom instead. Always 0.
    // Deprecated: use ProcessMemoryHighWaterMark atom instead. Always -1.
    optional int64 rss_high_watermark_in_bytes = 9 [deprecated = true];

    // Elapsed real time when the process started.
    // Value is read from /proc/PID/stat, field 22. 0 if read from per-app memory cgroups.
    optional int64 start_time_nanos = 10;

    // Anonymous page size plus swap size. Values are read from /proc/PID/status.
    optional int32 anon_rss_and_swap_in_kilobytes = 11;
}

/*
 * Logs the memory stats for a native process (from procfs).
 *
 * Pulled from StatsCompanionService for selected native processes.
 */
message NativeProcessMemoryState {
    // The uid if available. -1 means not available.
    optional int32 uid = 1 [(is_uid) = true];

    // The process name.
    // Value read from /proc/PID/cmdline.
    optional string process_name = 2;

    // # of page-faults
    optional int64 page_fault = 3;

    // # of major page-faults
    optional int64 page_major_fault = 4;

    // RSS
    // Value read from /proc/PID/status.
    optional int64 rss_in_bytes = 5;

    // Deprecated: use ProcessMemoryHighWaterMark atom instead. Always 0.
    optional int64 rss_high_watermark_in_bytes = 6 [deprecated = true];

    // 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;
    // Deprecated: use ProcessMemorySnapshot atom instead. Always -1.
    optional int64 start_time_nanos = 10 [deprecated = true];

    // Anonymous page size plus swap size. Values are read from /proc/PID/status.
    optional int32 anon_rss_and_swap_in_kilobytes = 9;
    // Deprecated: use ProcessMemorySnapshot atom instead. Always -1.
    optional int32 anon_rss_and_swap_in_kilobytes = 11 [deprecated = true];
}

/*
+2 −7
Original line number Diff line number Diff line
@@ -145,16 +145,11 @@ std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
         {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}},
        // process_memory_state
        {android::util::PROCESS_MEMORY_STATE,
         {.additiveFields = {4, 5, 6, 7, 8, 9},
         {.additiveFields = {4, 5, 6, 7, 8},
          .puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
        // native_process_memory_state
        {android::util::NATIVE_PROCESS_MEMORY_STATE,
         {.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,
         {.additiveFields = {3},
          .puller =
         {.puller =
                  new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},
        // process_memory_snapshot
        {android::util::PROCESS_MEMORY_SNAPSHOT,
+5 −62
Original line number Diff line number Diff line
@@ -39,8 +39,7 @@ import java.util.regex.Pattern;
 * Static utility methods related to {@link MemoryStat}.
 */
public final class MemoryStatUtil {
    static final int BYTES_IN_KILOBYTE = 1024;
    static final long JIFFY_NANOS = 1_000_000_000 / Os.sysconf(OsConstants._SC_CLK_TCK);
    static final int PAGE_SIZE = (int) Os.sysconf(OsConstants._SC_PAGESIZE);

    private static final String TAG = TAG_WITH_CLASS_NAME ? "MemoryStatUtil" : TAG_AM;

@@ -52,10 +51,6 @@ public final class MemoryStatUtil {
    private static final String MEMORY_STAT_FILE_FMT = "/dev/memcg/apps/uid_%d/pid_%d/memory.stat";
    /** Path to procfs stat file for logging app start memory state */
    private static final String PROC_STAT_FILE_FMT = "/proc/%d/stat";
    /** Path to procfs status file for logging app memory state */
    private static final String PROC_STATUS_FILE_FMT = "/proc/%d/status";
    /** Path to procfs cmdline file. Used with pid: /proc/pid/cmdline. */
    private static final String PROC_CMDLINE_FILE_FMT = "/proc/%d/cmdline";

    private static final Pattern PGFAULT = Pattern.compile("total_pgfault (\\d+)");
    private static final Pattern PGMAJFAULT = Pattern.compile("total_pgmajfault (\\d+)");
@@ -63,16 +58,9 @@ public final class MemoryStatUtil {
    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 PROCFS_RSS_IN_KILOBYTES =
            Pattern.compile("VmRSS:\\s*(\\d+)\\s*kB");
    private static final Pattern PROCFS_ANON_RSS_IN_KILOBYTES =
            Pattern.compile("RssAnon:\\s*(\\d+)\\s*kB");
    private static final Pattern PROCFS_SWAP_IN_KILOBYTES =
            Pattern.compile("VmSwap:\\s*(\\d+)\\s*kB");

    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() {}

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

    /**
     * Reads cmdline of a process from procfs.
     *
     * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
     * if the file is not available.
     */
    public static String readCmdlineFromProcfs(int pid) {
        final String path = String.format(Locale.US, PROC_CMDLINE_FILE_FMT, pid);
        return parseCmdlineFromProcfs(readFileContents(path));
        return parseMemoryStatFromProcfs(readFileContents(statPath));
    }

    private static String readFileContents(String path) {
@@ -160,31 +136,19 @@ public final class MemoryStatUtil {
     */
    @VisibleForTesting
    @Nullable
    static MemoryStat parseMemoryStatFromProcfs(
            String procStatContents, String procStatusContents) {
    static MemoryStat parseMemoryStatFromProcfs(String procStatContents) {
        if (procStatContents == null || procStatContents.isEmpty()) {
            return null;
        }
        if (procStatusContents == null || procStatusContents.isEmpty()) {
            return null;
        }

        final String[] splits = procStatContents.split(" ");
        if (splits.length < 24) {
            return null;
        }

        try {
            final MemoryStat memoryStat = new MemoryStat();
            memoryStat.pgfault = Long.parseLong(splits[PGFAULT_INDEX]);
            memoryStat.pgmajfault = Long.parseLong(splits[PGMAJFAULT_INDEX]);
            memoryStat.rssInBytes =
                tryParseLong(PROCFS_RSS_IN_KILOBYTES, procStatusContents) * BYTES_IN_KILOBYTE;
            memoryStat.anonRssInBytes =
                tryParseLong(PROCFS_ANON_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;
            memoryStat.rssInBytes = Long.parseLong(splits[RSS_IN_PAGES_INDEX]) * PAGE_SIZE;
            return memoryStat;
        } catch (NumberFormatException e) {
            Slog.e(TAG, "Failed to parse value", e);
@@ -192,23 +156,6 @@ public final class MemoryStatUtil {
        }
    }

    /**
     * Parses cmdline out of the contents of the /proc/pid/cmdline file in procfs.
     *
     * Parsing is required to strip anything after first null byte.
     */
    @VisibleForTesting
    static String parseCmdlineFromProcfs(String cmdline) {
        if (cmdline == null) {
            return "";
        }
        int firstNullByte = cmdline.indexOf("\0");
        if (firstNullByte == -1) {
            return cmdline;
        }
        return cmdline.substring(0, firstNullByte);
    }

    /**
     * Returns whether per-app memcg is available on device.
     */
@@ -237,13 +184,9 @@ public final class MemoryStatUtil {
        public long pgmajfault;
        /** For memcg stats, the anon rss + swap cache size. Otherwise total RSS. */
        public long rssInBytes;
        /** Number of bytes of the anonymous RSS. Only present for non-memcg stats. */
        public long anonRssInBytes;
        /** Number of bytes of page cache memory. Only present for memcg stats. */
        public long cacheInBytes;
        /** Number of bytes of swap usage */
        public long swapInBytes;
        /** Device time when the processes started. */
        public long startTimeNanos;
    }
}
+24 −0
Original line number Diff line number Diff line
@@ -72,6 +72,30 @@ final class ProcfsMemoryUtil {
        return null;
    }

    /**
     * Reads cmdline of a process from procfs.
     *
     * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
     * if the file is not available.
     */
    public static String readCmdlineFromProcfs(int pid) {
        return parseCmdline(readFile("/proc/" + pid + "/cmdline"));
    }

    /**
     * Parses cmdline out of the contents of the /proc/pid/cmdline file in procfs.
     *
     * Parsing is required to strip anything after the first null byte.
     */
    @VisibleForTesting
    static String parseCmdline(String contents) {
        int firstNullByte = contents.indexOf("\0");
        if (firstNullByte == -1) {
            return contents;
        }
        return contents.substring(0, firstNullByte);
    }

    private static String readFile(String path) {
        try {
            final File file = new File(path);
+4 −44
Original line number Diff line number Diff line
@@ -24,11 +24,10 @@ import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
import static android.os.storage.VolumeInfo.TYPE_PUBLIC;

import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs;
import static com.android.server.stats.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
import static com.android.server.stats.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
import static com.android.server.stats.ProcfsMemoryUtil.readCmdlineFromProcfs;
import static com.android.server.stats.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;

import android.annotation.NonNull;
@@ -1193,48 +1192,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
            e.writeLong(memoryStat.rssInBytes);
            e.writeLong(memoryStat.cacheInBytes);
            e.writeLong(memoryStat.swapInBytes);
            e.writeLong(0);  // unused
            e.writeLong(memoryStat.startTimeNanos);
            e.writeInt(anonAndSwapInKilobytes(memoryStat));
            e.writeLong(-1);  // unused
            e.writeLong(-1);  // unused
            e.writeInt(-1);  // unsed
            pulledData.add(e);
        }
    }

    private void pullNativeProcessMemoryState(
            int tagId, long elapsedNanos, long wallClockNanos,
            List<StatsLogEventWrapper> pulledData) {
        int[] pids = getPidsForCommands(MEMORY_INTERESTING_NATIVE_PROCESSES);
        for (int pid : pids) {
            String processName = readCmdlineFromProcfs(pid);
            MemoryStat memoryStat = readMemoryStatFromProcfs(pid);
            if (memoryStat == null) {
                continue;
            }
            int uid = getUidForPid(pid);
            // Sometimes we get here a process that is not included in the whitelist. It comes
            // from forking the zygote for an app. We can ignore that sample because this process
            // is collected by ProcessMemoryState.
            if (isAppUid(uid)) {
                continue;
            }
            StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
            e.writeInt(uid);
            e.writeString(processName);
            e.writeLong(memoryStat.pgfault);
            e.writeLong(memoryStat.pgmajfault);
            e.writeLong(memoryStat.rssInBytes);
            e.writeLong(0);  // unused
            e.writeLong(memoryStat.startTimeNanos);
            e.writeLong(memoryStat.swapInBytes);
            e.writeInt(anonAndSwapInKilobytes(memoryStat));
            pulledData.add(e);
        }
    }

    private static int anonAndSwapInKilobytes(MemoryStat memoryStat) {
        return (int) ((memoryStat.anonRssInBytes + memoryStat.swapInBytes) / 1024);
    }

    private void pullProcessMemoryHighWaterMark(
            int tagId, long elapsedNanos, long wallClockNanos,
            List<StatsLogEventWrapper> pulledData) {
@@ -2405,10 +2369,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
                pullProcessMemoryState(tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }
            case StatsLog.NATIVE_PROCESS_MEMORY_STATE: {
                pullNativeProcessMemoryState(tagId, elapsedNanos, wallClockNanos, ret);
                break;
            }
            case StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK: {
                pullProcessMemoryHighWaterMark(tagId, elapsedNanos, wallClockNanos, ret);
                break;
Loading