summaryrefslogtreecommitdiff
path: root/src/com/android
diff options
context:
space:
mode:
authorSteven Timotius <stimo@google.com>2018-01-24 17:09:43 -0800
committerSteven Timotius <stimo@google.com>2018-01-26 15:26:58 -0800
commit39ba7c3412c56fffbb64d47a7c506cb6f47c062a (patch)
tree1e4dcafe9228b036e329d3acea20945e2625bd50 /src/com/android
parentf2ff76c17ed4de2cb44088a9f4653cbc010884e0 (diff)
downloadloganalysis-39ba7c3412c56fffbb64d47a7c506cb6f47c062a.tar.gz
Add parser for dumpsys meminfo --checkin PROCESS
Parser will be used to obtain process memory usage data Test: tools/tradefederation/core/tests/run_tradefed_tests.sh --class com.android.loganalysis.parser.DumpsysProcessMeminfoParserTest Bug: 72409230 Change-Id: I0035a32550372c4e8ee7cd049e43524b3700101b
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/loganalysis/item/DumpsysProcessMeminfoItem.java119
-rw-r--r--src/com/android/loganalysis/parser/DumpsysProcessMeminfoParser.java100
2 files changed, 219 insertions, 0 deletions
diff --git a/src/com/android/loganalysis/item/DumpsysProcessMeminfoItem.java b/src/com/android/loganalysis/item/DumpsysProcessMeminfoItem.java
new file mode 100644
index 0000000..3abfd40
--- /dev/null
+++ b/src/com/android/loganalysis/item/DumpsysProcessMeminfoItem.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 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.loganalysis.item;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An {@link IItem} used to store output from `dumpsys meminfo --checkin PROCESS` where PROCESS is
+ * from the output of `dumpsys meminfo`. Data is stored as a map of categories to a map of
+ * measurement types to values.
+ */
+public class DumpsysProcessMeminfoItem extends GenericMapItem<Map<String, Long>> {
+ // Should match value from ActivityThread
+ public static final int ACTIVITY_THREAD_CHECKIN_VERSION = 4;
+
+ // Default Categories
+ public static final String NATIVE = "NATIVE";
+ public static final String DALVIK = "DALVIK";
+ public static final String OTHER = "OTHER";
+ public static final String TOTAL = "TOTAL";
+
+ // Memory Measurement Types
+ public static final String PSS = "PSS";
+ public static final String SWAPPABLE_PSS = "SWAPPABLE_PSS";
+ public static final String SHARED_DIRTY = "SHARED_DIRTY";
+ public static final String SHARED_CLEAN = "SHARED_CLEAN";
+ public static final String PRIVATE_DIRTY = "PRIVATE_DIRTY";
+ public static final String PRIVATE_CLEAN = "PRIVATE_CLEAN";
+ public static final String SWAPPED_OUT = "SWAPPED_OUT";
+ public static final String SWAPPED_OUT_PSS = "SWAPPED_OUT_PSS";
+ // NATIVE, DALVIK, TOTAL only
+ public static final String MAX = "MAX";
+ public static final String ALLOCATED = "ALLOCATED";
+ public static final String FREE = "FREE";
+
+ public static final String[] MAIN_OUTPUT_ORDER = {
+ MAX,
+ ALLOCATED,
+ FREE,
+ PSS,
+ SWAPPABLE_PSS,
+ SHARED_DIRTY,
+ SHARED_CLEAN,
+ PRIVATE_DIRTY,
+ PRIVATE_CLEAN,
+ SWAPPED_OUT,
+ SWAPPED_OUT_PSS
+ };
+ public static final String[] OTHER_OUTPUT_ORDER = {
+ PSS,
+ SWAPPABLE_PSS,
+ SHARED_DIRTY,
+ SHARED_CLEAN,
+ PRIVATE_DIRTY,
+ PRIVATE_CLEAN,
+ SWAPPED_OUT,
+ SWAPPED_OUT_PSS
+ };
+
+ private int mPid;
+ private String mProcessName;
+
+ public DumpsysProcessMeminfoItem() {
+ this.put(NATIVE, new HashMap<>());
+ this.put(DALVIK, new HashMap<>());
+ this.put(OTHER, new HashMap<>());
+ this.put(TOTAL, new HashMap<>());
+ }
+
+ /** Get the pid */
+ public int getPid() {
+ return mPid;
+ }
+
+ /** Set the pid */
+ public void setPid(int pid) {
+ mPid = pid;
+ }
+
+ /** Get the process name */
+ public String getProcessName() {
+ return mProcessName;
+ }
+
+ /** Set the process name */
+ public void setProcessName(String processName) {
+ mProcessName = processName;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public JSONObject toJson() {
+ JSONObject result = super.toJson();
+ try {
+ result.put("pid", mPid);
+ result.put("process_name", mProcessName);
+ } catch (JSONException e) {
+ //ignore
+ }
+ return result;
+ }
+}
diff --git a/src/com/android/loganalysis/parser/DumpsysProcessMeminfoParser.java b/src/com/android/loganalysis/parser/DumpsysProcessMeminfoParser.java
new file mode 100644
index 0000000..119bab6
--- /dev/null
+++ b/src/com/android/loganalysis/parser/DumpsysProcessMeminfoParser.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 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.loganalysis.parser;
+
+import com.android.loganalysis.item.DumpsysProcessMeminfoItem;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * An {@link IParser} used to parse output from `dumpsys meminfo --checkin PROCESS` where PROCESS is
+ * from the output of `dumpsys meminfo`. Data is stored as a map of categories to a map of
+ * measurement types to values. Format is from {@link android.app.ActivityThread#dumpMemInfoTable}.
+ */
+public class DumpsysProcessMeminfoParser implements IParser {
+
+ // Order is VERSION,PID,NAME,[native,dalvik,other,total]{11},[name,val{8}]*
+ private static final Pattern MEMINFO_OUTPUT =
+ Pattern.compile("(\\d+),(\\d+),([^,]+),((?:(?:N/A|\\d+),){44})(.*)");
+ // Matches the ending [name,val{8}]
+ private static final Pattern MEMINFO_ADDITIONAL_OUTPUT =
+ Pattern.compile("([^,]+),((?:(?:N/A|\\d+),){8})");
+ // Matches a value with comma
+ private static final Pattern MEMINFO_VALUE = Pattern.compile("(N/A|\\d+),");
+
+ @Override
+ public DumpsysProcessMeminfoItem parse(List<String> lines) {
+ DumpsysProcessMeminfoItem item = new DumpsysProcessMeminfoItem();
+ for (String line : lines) {
+ Matcher m = MEMINFO_OUTPUT.matcher(line);
+ if (!m.matches()) continue;
+ try {
+ item.setPid(Integer.parseInt(m.group(2)));
+ } catch (NumberFormatException e) {
+ // skip
+ }
+ item.setProcessName(m.group(3));
+ // parse memory info main areas
+ String mainValues = m.group(4);
+ Matcher mainMatcher = MEMINFO_VALUE.matcher(mainValues);
+ Map<String, Long> nativeData = item.get(DumpsysProcessMeminfoItem.NATIVE);
+ Map<String, Long> dalvikData = item.get(DumpsysProcessMeminfoItem.DALVIK);
+ Map<String, Long> otherData = item.get(DumpsysProcessMeminfoItem.OTHER);
+ Map<String, Long> totalData = item.get(DumpsysProcessMeminfoItem.TOTAL);
+ for (int i = 0; i < DumpsysProcessMeminfoItem.MAIN_OUTPUT_ORDER.length; i++) {
+ String curMeasurement = DumpsysProcessMeminfoItem.MAIN_OUTPUT_ORDER[i];
+ parseNextValue(mainMatcher, nativeData, curMeasurement);
+ parseNextValue(mainMatcher, dalvikData, curMeasurement);
+ parseNextValue(mainMatcher, otherData, curMeasurement);
+ parseNextValue(mainMatcher, totalData, curMeasurement);
+ }
+ String additionalData = m.group(5);
+ Matcher additionalMatcher = MEMINFO_ADDITIONAL_OUTPUT.matcher(additionalData);
+ // parse memory info other areas
+ while (additionalMatcher.find()) {
+ try {
+ String curLabel = additionalMatcher.group(1);
+ Matcher additionalValueMatcher =
+ MEMINFO_VALUE.matcher(additionalMatcher.group(2));
+ Map<String, Long> curData = new HashMap<>();
+ for (int i = 0; i < DumpsysProcessMeminfoItem.OTHER_OUTPUT_ORDER.length; i++) {
+ String curMeasurement = DumpsysProcessMeminfoItem.OTHER_OUTPUT_ORDER[i];
+ parseNextValue(additionalValueMatcher, curData, curMeasurement);
+ }
+ item.put(curLabel, curData);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ break;
+ }
+ }
+ }
+ return item;
+ }
+
+ private void parseNextValue(Matcher m, Map<String, Long> output, String key) {
+ if (!m.find()) return;
+ String value = m.group(1);
+ if ("N/A".equals(value)) return;
+ try {
+ output.put(key, Long.parseLong(value));
+ } catch (NumberFormatException e) {
+ // skip
+ }
+ }
+}