From b1c1634325eb4db274f534275f88c5e4831962e1 Mon Sep 17 00:00:00 2001 From: Jeffrey Huang Date: Wed, 15 Jan 2020 15:36:42 -0800 Subject: [PATCH] Migrate ProcessMemory pullers Test: atest UidAtomTests#testProcessMemoryState Test: atest UidAtomTests#testProcessMemoryHighWaterMark Test: atest UidAtomTests#testProcessMemorySnapshot Test: adb shell cmd stats pull-source 10013 Test: adb shell cmd stats pull-source 10042 Test: adb shell cmd stats pull-source 10064 Change-Id: I0ce870a3fec668e380a6b6412f278033d6734f35 --- .../server/stats/StatsCompanionService.java | 141 ------------- .../src/external/StatsPullerManager.cpp | 14 -- .../stats/pull/StatsPullAtomService.java | 198 +++++++++++++++++- 3 files changed, 189 insertions(+), 164 deletions(-) diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java index c8a83f7ab4fc2..6462ceb464369 100644 --- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java +++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java @@ -722,132 +722,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { pulledData.add(e); } - private void pullProcessMemoryState( - int tagId, long elapsedNanos, long wallClockNanos, - List pulledData) { - List processMemoryStates = - LocalServices.getService( - ActivityManagerInternal.class).getMemoryStateForProcesses(); - for (ProcessMemoryState processMemoryState : processMemoryStates) { - final MemoryStat memoryStat = readMemoryStatFromFilesystem(processMemoryState.uid, - processMemoryState.pid); - if (memoryStat == null) { - continue; - } - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(processMemoryState.uid); - e.writeString(processMemoryState.processName); - e.writeInt(processMemoryState.oomScore); - e.writeLong(memoryStat.pgfault); - e.writeLong(memoryStat.pgmajfault); - e.writeLong(memoryStat.rssInBytes); - e.writeLong(memoryStat.cacheInBytes); - e.writeLong(memoryStat.swapInBytes); - e.writeLong(-1); // unused - e.writeLong(-1); // unused - e.writeInt(-1); // unsed - pulledData.add(e); - } - } - - private void pullProcessMemoryHighWaterMark( - int tagId, long elapsedNanos, long wallClockNanos, - List pulledData) { - List managedProcessList = - LocalServices.getService( - ActivityManagerInternal.class).getMemoryStateForProcesses(); - for (ProcessMemoryState managedProcess : managedProcessList) { - final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid); - if (snapshot == null) { - continue; - } - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(managedProcess.uid); - e.writeString(managedProcess.processName); - // RSS high-water mark in bytes. - e.writeLong((long) snapshot.rssHighWaterMarkInKilobytes * 1024L); - e.writeInt(snapshot.rssHighWaterMarkInKilobytes); - pulledData.add(e); - } - forEachPid((pid, cmdLine) -> { - if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) { - return; - } - final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid); - if (snapshot == null) { - return; - } - // 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(snapshot.uid)) { - return; - } - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(snapshot.uid); - e.writeString(cmdLine); - // RSS high-water mark in bytes. - e.writeLong((long) snapshot.rssHighWaterMarkInKilobytes * 1024L); - e.writeInt(snapshot.rssHighWaterMarkInKilobytes); - pulledData.add(e); - }); - // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes. - SystemProperties.set("sys.rss_hwm_reset.on", "1"); - } - - private void pullProcessMemorySnapshot( - int tagId, long elapsedNanos, long wallClockNanos, - List pulledData) { - List managedProcessList = - LocalServices.getService( - ActivityManagerInternal.class).getMemoryStateForProcesses(); - for (ProcessMemoryState managedProcess : managedProcessList) { - final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid); - if (snapshot == null) { - continue; - } - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(managedProcess.uid); - e.writeString(managedProcess.processName); - e.writeInt(managedProcess.pid); - e.writeInt(managedProcess.oomScore); - e.writeInt(snapshot.rssInKilobytes); - e.writeInt(snapshot.anonRssInKilobytes); - e.writeInt(snapshot.swapInKilobytes); - e.writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes); - pulledData.add(e); - } - forEachPid((pid, cmdLine) -> { - if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) { - return; - } - final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid); - if (snapshot == null) { - return; - } - // 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(snapshot.uid)) { - return; - } - StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos); - e.writeInt(snapshot.uid); - e.writeString(cmdLine); - e.writeInt(pid); - e.writeInt(-1001); // Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1. - e.writeInt(snapshot.rssInKilobytes); - e.writeInt(snapshot.anonRssInKilobytes); - e.writeInt(snapshot.swapInKilobytes); - e.writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes); - pulledData.add(e); - }); - } - - private static boolean isAppUid(int uid) { - return uid >= MIN_APP_UID; - } - private void pullSystemIonHeapSize( int tagId, long elapsedNanos, long wallClockNanos, List pulledData) { @@ -1823,21 +1697,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { break; } - case StatsLog.PROCESS_MEMORY_STATE: { - pullProcessMemoryState(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK: { - pullProcessMemoryHighWaterMark(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - - case StatsLog.PROCESS_MEMORY_SNAPSHOT: { - pullProcessMemorySnapshot(tagId, elapsedNanos, wallClockNanos, ret); - break; - } - case StatsLog.SYSTEM_ION_HEAP_SIZE: { pullSystemIonHeapSize(tagId, elapsedNanos, wallClockNanos, ret); break; diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 591d7277b299d..fecc52e3800fb 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -95,20 +95,6 @@ std::map StatsPullerManager::kAllPullAtomInfo = { {{.atomTag = android::util::BATTERY_CYCLE_COUNT}, {.puller = new ResourceHealthManagerPuller(android::util::BATTERY_CYCLE_COUNT)}}, - // process_memory_state - {{.atomTag = android::util::PROCESS_MEMORY_STATE}, - {.additiveFields = {4, 5, 6, 7, 8}, - .puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}}, - - // process_memory_high_water_mark - {{.atomTag = android::util::PROCESS_MEMORY_HIGH_WATER_MARK}, - {.puller = - new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}}, - - // process_memory_snapshot - {{.atomTag = android::util::PROCESS_MEMORY_SNAPSHOT}, - {.puller = new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_SNAPSHOT)}}, - // system_ion_heap_size {{.atomTag = android::util::SYSTEM_ION_HEAP_SIZE}, {.puller = new StatsCompanionServicePuller(android::util::SYSTEM_ION_HEAP_SIZE)}}, diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index 96173e0d86d96..79dbd9baeac9e 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -1004,27 +1004,207 @@ public class StatsPullAtomService extends SystemService { } private void registerProcessMemoryState() { - // No op. + int tagId = StatsLog.PROCESS_MEMORY_STATE; + PullAtomMetadata metadata = PullAtomMetadata.newBuilder() + .setAdditiveFields(new int[] {4, 5, 6, 7, 8}) + .build(); + mStatsManager.registerPullAtomCallback( + tagId, + metadata, + (atomTag, data) -> pullProcessMemoryState(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullProcessMemoryState() { - // No op. + private int pullProcessMemoryState(int atomTag, List pulledData) { + List processMemoryStates = + LocalServices.getService(ActivityManagerInternal.class) + .getMemoryStateForProcesses(); + for (ProcessMemoryState processMemoryState : processMemoryStates) { + final MemoryStat memoryStat = readMemoryStatFromFilesystem(processMemoryState.uid, + processMemoryState.pid); + if (memoryStat == null) { + continue; + } + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(processMemoryState.uid) + .writeString(processMemoryState.processName) + .writeInt(processMemoryState.oomScore) + .writeLong(memoryStat.pgfault) + .writeLong(memoryStat.pgmajfault) + .writeLong(memoryStat.rssInBytes) + .writeLong(memoryStat.cacheInBytes) + .writeLong(memoryStat.swapInBytes) + .writeLong(-1) // unused + .writeLong(-1) // unused + .writeInt(-1) // unused + .build(); + pulledData.add(e); + } + return StatsManager.PULL_SUCCESS; + } + + /** + * Which native processes to snapshot memory for. + * + *

Processes are matched by their cmdline in procfs. Example: cat /proc/pid/cmdline returns + * /system/bin/statsd for the stats daemon. + */ + private static final Set MEMORY_INTERESTING_NATIVE_PROCESSES = Sets.newHashSet( + "/system/bin/statsd", // Stats daemon. + "/system/bin/surfaceflinger", + "/system/bin/apexd", // APEX daemon. + "/system/bin/audioserver", + "/system/bin/cameraserver", + "/system/bin/drmserver", + "/system/bin/healthd", + "/system/bin/incidentd", + "/system/bin/installd", + "/system/bin/lmkd", // Low memory killer daemon. + "/system/bin/logd", + "media.codec", + "media.extractor", + "media.metrics", + "/system/bin/mediadrmserver", + "/system/bin/mediaserver", + "/system/bin/performanced", + "/system/bin/tombstoned", + "/system/bin/traced", // Perfetto. + "/system/bin/traced_probes", // Perfetto. + "webview_zygote", + "zygote", + "zygote64"); + + /** + * Lowest available uid for apps. + * + *

Used to quickly discard memory snapshots of the zygote forks from native process + * measurements. + */ + private static final int MIN_APP_UID = 10_000; + + private static boolean isAppUid(int uid) { + return uid >= MIN_APP_UID; } private void registerProcessMemoryHighWaterMark() { - // No op. + int tagId = StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullProcessMemoryHighWaterMark(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullProcessMemoryHighWaterMark() { - // No op. + private int pullProcessMemoryHighWaterMark(int atomTag, List pulledData) { + List managedProcessList = + LocalServices.getService(ActivityManagerInternal.class) + .getMemoryStateForProcesses(); + for (ProcessMemoryState managedProcess : managedProcessList) { + final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid); + if (snapshot == null) { + continue; + } + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(managedProcess.uid) + .writeString(managedProcess.processName) + // RSS high-water mark in bytes. + .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L) + .writeInt(snapshot.rssHighWaterMarkInKilobytes) + .build(); + pulledData.add(e); + } + forEachPid((pid, cmdLine) -> { + if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) { + return; + } + final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid); + if (snapshot == null) { + return; + } + // 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(snapshot.uid)) { + return; + } + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(snapshot.uid) + .writeString(cmdLine) + // RSS high-water mark in bytes. + .writeLong(snapshot.rssHighWaterMarkInKilobytes * 1024L) + .writeInt(snapshot.rssHighWaterMarkInKilobytes) + .build(); + pulledData.add(e); + }); + // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes. + SystemProperties.set("sys.rss_hwm_reset.on", "1"); + return StatsManager.PULL_SUCCESS; } private void registerProcessMemorySnapshot() { - // No op. + int tagId = StatsLog.PROCESS_MEMORY_SNAPSHOT; + mStatsManager.registerPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + (atomTag, data) -> pullProcessMemorySnapshot(atomTag, data), + BackgroundThread.getExecutor() + ); } - private void pullProcessMemorySnapshot() { - // No op. + private int pullProcessMemorySnapshot(int atomTag, List pulledData) { + List managedProcessList = + LocalServices.getService(ActivityManagerInternal.class) + .getMemoryStateForProcesses(); + for (ProcessMemoryState managedProcess : managedProcessList) { + final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(managedProcess.pid); + if (snapshot == null) { + continue; + } + StatsEvent e = StatsEvent.newBuilder() + .writeInt(managedProcess.uid) + .writeString(managedProcess.processName) + .writeInt(managedProcess.pid) + .writeInt(managedProcess.oomScore) + .writeInt(snapshot.rssInKilobytes) + .writeInt(snapshot.anonRssInKilobytes) + .writeInt(snapshot.swapInKilobytes) + .writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes) + .build(); + pulledData.add(e); + } + forEachPid((pid, cmdLine) -> { + if (!MEMORY_INTERESTING_NATIVE_PROCESSES.contains(cmdLine)) { + return; + } + final MemorySnapshot snapshot = readMemorySnapshotFromProcfs(pid); + if (snapshot == null) { + return; + } + // 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(snapshot.uid)) { + return; + } + StatsEvent e = StatsEvent.newBuilder() + .setAtomId(atomTag) + .writeInt(snapshot.uid) + .writeString(cmdLine) + .writeInt(pid) + .writeInt(-1001) // Placeholder for native processes, OOM_SCORE_ADJ_MIN - 1. + .writeInt(snapshot.rssInKilobytes) + .writeInt(snapshot.anonRssInKilobytes) + .writeInt(snapshot.swapInKilobytes) + .writeInt(snapshot.anonRssInKilobytes + snapshot.swapInKilobytes) + .build(); + pulledData.add(e); + }); + return StatsManager.PULL_SUCCESS; } private void registerSystemIonHeapSize() {