summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Rafal Slawik <rslawik@google.com> 2019-09-13 11:50:27 +0100
committer Rafal Slawik <rslawik@google.com> 2019-09-17 09:57:50 +0000
commit196532a01e6f69657d6e8804f1637b82b9698656 (patch)
tree42a155bf8272b4248e9f4c2baad2ccb2ccce8afb
parente33dcad81a4bc5f528f93e675c0319104b66f2e7 (diff)
Move RSS HWM stats reading code under stats
The RSS high-water mark stats are used only by telemetry and should not be a part of am package. Modifications: - avoid null, use empty string instead - use assertThat from Truth Bug: 140986627 Test: atest MemoryStatUtilTest Test: atest ProcfsMemoryUtilTest Test: statsd_testdrive for RSS HWM atom Change-Id: I60140c085f1a47d71505955d79f545f52a4c4423
-rw-r--r--services/core/java/com/android/server/am/MemoryStatUtil.java24
-rw-r--r--services/core/java/com/android/server/stats/ProcfsMemoryUtil.java75
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/stats/ProcfsMemoryUtilTest.java93
5 files changed, 169 insertions, 38 deletions
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index e73abd17cc07..fd64df9e86e0 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -63,8 +63,6 @@ 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 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_ANON_RSS_IN_KILOBYTES =
@@ -113,15 +111,6 @@ public final class MemoryStatUtil {
}
/**
- * Reads RSS high-water mark of a process from procfs. Returns value of the VmHWM field in
- * /proc/PID/status in kilobytes or 0 if not available.
- */
- public static int readRssHighWaterMarkFromProcfs(int pid) {
- final String statusPath = String.format(Locale.US, PROC_STATUS_FILE_FMT, pid);
- return parseVmHWMFromProcfs(readFileContents(statusPath));
- }
-
- /**
* Reads cmdline of a process from procfs.
*
* Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
@@ -204,19 +193,6 @@ public final class MemoryStatUtil {
}
/**
- * Parses RSS high-water mark out from the contents of the /proc/pid/status file in procfs. The
- * returned value is in kilobytes.
- */
- @VisibleForTesting
- static int parseVmHWMFromProcfs(String procStatusContents) {
- if (procStatusContents == null || procStatusContents.isEmpty()) {
- return 0;
- }
- return (int) tryParseLong(RSS_HIGH_WATERMARK_IN_KILOBYTES, procStatusContents);
- }
-
-
- /**
* Parses cmdline out of the contents of the /proc/pid/cmdline file in procfs.
*
* Parsing is required to strip anything after first null byte.
diff --git a/services/core/java/com/android/server/stats/ProcfsMemoryUtil.java b/services/core/java/com/android/server/stats/ProcfsMemoryUtil.java
new file mode 100644
index 000000000000..3076284a80ed
--- /dev/null
+++ b/services/core/java/com/android/server/stats/ProcfsMemoryUtil.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.stats;
+
+import android.os.FileUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+final class ProcfsMemoryUtil {
+ private static final String TAG = "ProcfsMemoryUtil";
+
+ /** Path to procfs status file: /proc/pid/status. */
+ private static final String STATUS_FILE_FMT = "/proc/%d/status";
+
+ private static final Pattern RSS_HIGH_WATER_MARK_IN_KILOBYTES =
+ Pattern.compile("VmHWM:\\s*(\\d+)\\s*kB");
+
+ private ProcfsMemoryUtil() {}
+
+ /**
+ * Reads RSS high-water mark of a process from procfs. Returns value of the VmHWM field in
+ * /proc/PID/status in kilobytes or 0 if not available.
+ */
+ static int readRssHighWaterMarkFromProcfs(int pid) {
+ final String statusPath = String.format(Locale.US, STATUS_FILE_FMT, pid);
+ return parseVmHWMFromStatus(readFile(statusPath));
+ }
+
+ /**
+ * Parses RSS high-water mark out from the contents of the /proc/pid/status file in procfs. The
+ * returned value is in kilobytes.
+ */
+ @VisibleForTesting
+ static int parseVmHWMFromStatus(String contents) {
+ if (contents.isEmpty()) {
+ return 0;
+ }
+ final Matcher matcher = RSS_HIGH_WATER_MARK_IN_KILOBYTES.matcher(contents);
+ try {
+ return matcher.find() ? Integer.parseInt(matcher.group(1)) : 0;
+ } catch (NumberFormatException e) {
+ Slog.e(TAG, "Failed to parse value", e);
+ return 0;
+ }
+ }
+
+ private static String readFile(String path) {
+ try {
+ final File file = new File(path);
+ return FileUtils.readTextFile(file, 0 /* max */, null /* ellipsis */);
+ } catch (IOException e) {
+ return "";
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index e92abfddac8f..19b80556a779 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -27,9 +27,9 @@ 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.am.MemoryStatUtil.readRssHighWaterMarkFromProcfs;
import static com.android.server.stats.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
import static com.android.server.stats.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
+import static com.android.server.stats.ProcfsMemoryUtil.readRssHighWaterMarkFromProcfs;
import android.annotation.NonNull;
import android.annotation.Nullable;
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
index 6a0d7f192adb..9e3b54d1ca96 100644
--- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -22,7 +22,6 @@ import static com.android.server.am.MemoryStatUtil.MemoryStat;
import static com.android.server.am.MemoryStatUtil.parseCmdlineFromProcfs;
import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromMemcg;
import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromProcfs;
-import static com.android.server.am.MemoryStatUtil.parseVmHWMFromProcfs;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -230,18 +229,6 @@ public class MemoryStatUtilTest {
}
@Test
- public void testParseVmHWMFromProcfs_parsesCorrectValue() {
- assertEquals(137668, parseVmHWMFromProcfs(PROC_STATUS_CONTENTS));
- }
-
- @Test
- public void testParseVmHWMFromProcfs_emptyContents() {
- assertEquals(0, parseVmHWMFromProcfs(""));
-
- assertEquals(0, parseVmHWMFromProcfs(null));
- }
-
- @Test
public void testParseCmdlineFromProcfs_invalidValue() {
byte[] nothing = new byte[] {0x00, 0x74, 0x65, 0x73, 0x74}; // \0test
diff --git a/services/tests/servicestests/src/com/android/server/stats/ProcfsMemoryUtilTest.java b/services/tests/servicestests/src/com/android/server/stats/ProcfsMemoryUtilTest.java
new file mode 100644
index 000000000000..4fb533f726b2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/stats/ProcfsMemoryUtilTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.stats;
+
+import static com.android.server.stats.ProcfsMemoryUtil.parseVmHWMFromStatus;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:ProcfsMemoryUtilTest
+ */
+@SmallTest
+public class ProcfsMemoryUtilTest {
+ private static final String STATUS_CONTENTS = "Name:\tandroid.youtube\n"
+ + "State:\tS (sleeping)\n"
+ + "Tgid:\t12088\n"
+ + "Pid:\t12088\n"
+ + "PPid:\t723\n"
+ + "TracerPid:\t0\n"
+ + "Uid:\t10083\t10083\t10083\t10083\n"
+ + "Gid:\t10083\t10083\t10083\t10083\n"
+ + "Ngid:\t0\n"
+ + "FDSize:\t128\n"
+ + "Groups:\t3003 9997 20083 50083 \n"
+ + "VmPeak:\t 4546844 kB\n"
+ + "VmSize:\t 4542636 kB\n"
+ + "VmLck:\t 0 kB\n"
+ + "VmPin:\t 0 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"
+ + "VmData:\t 4125112 kB\n"
+ + "VmStk:\t 8192 kB\n"
+ + "VmExe:\t 24 kB\n"
+ + "VmLib:\t 102432 kB\n"
+ + "VmPTE:\t 1300 kB\n"
+ + "VmPMD:\t 36 kB\n"
+ + "VmSwap:\t 22 kB\n" // Swap
+ + "Threads:\t95\n"
+ + "SigQ:\t0/13641\n"
+ + "SigPnd:\t0000000000000000\n"
+ + "ShdPnd:\t0000000000000000\n"
+ + "SigBlk:\t0000000000001204\n"
+ + "SigIgn:\t0000000000000001\n"
+ + "SigCgt:\t00000006400084f8\n"
+ + "CapInh:\t0000000000000000\n"
+ + "CapPrm:\t0000000000000000\n"
+ + "CapEff:\t0000000000000000\n"
+ + "CapBnd:\t0000000000000000\n"
+ + "CapAmb:\t0000000000000000\n"
+ + "Seccomp:\t2\n"
+ + "Cpus_allowed:\tff\n"
+ + "Cpus_allowed_list:\t0-7\n"
+ + "Mems_allowed:\t1\n"
+ + "Mems_allowed_list:\t0\n"
+ + "voluntary_ctxt_switches:\t903\n"
+ + "nonvoluntary_ctxt_switches:\t104\n";
+
+ @Test
+ public void testParseVmHWMFromStatus_parsesCorrectValue() {
+ assertThat(parseVmHWMFromStatus(STATUS_CONTENTS)).isEqualTo(137668);
+ }
+
+ @Test
+ public void testParseVmHWMFromStatus_invalidValue() {
+ assertThat(parseVmHWMFromStatus("test\nVmHWM: x0x0x\ntest")).isEqualTo(0);
+ }
+
+ @Test
+ public void testParseVmHWMFromStatus_emptyContents() {
+ assertThat(parseVmHWMFromStatus("")).isEqualTo(0);
+ }
+}