diff options
author | Maxim Siniavine <siniavine@google.com> | 2014-04-08 12:21:30 -0700 |
---|---|---|
committer | Maxim Siniavine <siniavine@google.com> | 2014-04-17 12:39:46 -0700 |
commit | fa2761ae3a751b4fc7952b1f0046fcd3e912953a (patch) | |
tree | 94513c54c1975f72fdf432c2db7f1ca4a7894e13 | |
parent | 5aa305c38c04a42aaa9fb43905cf111253b7a3a0 (diff) | |
download | loganalysis-fa2761ae3a751b4fc7952b1f0046fcd3e912953a.tar.gz |
Add parsing for compact meminfo
Change-Id: I9ff2677f75bb2b77e07c3a9e391235c3f7004eec
3 files changed, 291 insertions, 0 deletions
diff --git a/src/com/android/loganalysis/item/CompactMemInfoItem.java b/src/com/android/loganalysis/item/CompactMemInfoItem.java new file mode 100644 index 0000000..58c3496 --- /dev/null +++ b/src/com/android/loganalysis/item/CompactMemInfoItem.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2014 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.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Contains a list of processes and how much memory they are using. Generated from parsing + * compact mem info file. Refer to CompactMemInfoParser for more details. + */ +public class CompactMemInfoItem implements IItem { + private Map<Integer, Map<String, Object>> mPids = new HashMap<Integer, Map<String, Object>>(); + + @Override + public IItem merge(IItem other) throws ConflictingItemException { + throw new ConflictingItemException("Compact meminfo items cannot be merged"); + } + + @Override + public boolean isConsistent(IItem other) { + return false; + } + + @Override + public JSONObject toJson() { + JSONObject object = new JSONObject(); + JSONArray processes = new JSONArray(); + for(int pid : getPids()) { + JSONObject proc = new JSONObject(); + try { + proc.put("pid", pid); + proc.put("name", getName(pid)); + proc.put("pss", getPss(pid)); + proc.put("type", getType(pid)); + proc.put("activities", hasActivities(pid)); + processes.put(proc); + } catch (JSONException e) { + // ignore + } + } + try { + object.put("processes", processes); + } catch (JSONException e) { + // ignore + } + return object; + } + + /** + * Get the list of pids of the processes that were added so far. + * @return + */ + public Set<Integer> getPids() { + return mPids.keySet(); + } + + private Map<String, Object> get(int pid) { + return mPids.get(pid); + } + + /** + * Adds a process to the list stored in this item. + */ + public void addPid(int pid, String name, String type, long pss, boolean activities) { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put("name", name); + attributes.put("type", type); + attributes.put("pss", pss); + attributes.put("activities", activities); + mPids.put(pid, attributes); + } + + /** + * Returns the name of the process with a given pid. + */ + public String getName(int pid) { + return (String)get(pid).get("name"); + } + + /** + * Return pss of the process with a given name. + */ + public long getPss(int pid) { + return (Long)get(pid).get("pss"); + } + + /** + * Returns the type of the process with a given pid. Some possible types are native, cached, + * foreground and etc. + */ + public String getType(int pid) { + return (String)get(pid).get("type"); + } + + /** + * Returns true if a process has any activities assosiated with it. False otherwise. + */ + public boolean hasActivities(int pid) { + return (Boolean)get(pid).get("activities"); + } +} diff --git a/src/com/android/loganalysis/parser/CompactMemInfoParser.java b/src/com/android/loganalysis/parser/CompactMemInfoParser.java new file mode 100644 index 0000000..8282731 --- /dev/null +++ b/src/com/android/loganalysis/parser/CompactMemInfoParser.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2014 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.CompactMemInfoItem; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Parser for the compact meminfo output, from the 'dumpsys meminfo -c' command. + * The output is a csv file which contains the information about how processes use memory. + * For now we are only interested in the pss of the processes. So we only parse the lines + * that start with proc and skip everything else. + * + * The format of the line is as follows: + * "proc,[type],[name],[pid],[pss],[activities]. + * + * Type is the type of the process for example native, cached, foreground, etc. + * Name is the name of the process. + * Activities indicates if a process has any activities associated with it. + * + */ +public class CompactMemInfoParser implements IParser { + + private static final Pattern PROC_PREFIX = Pattern.compile( + "proc,(.+),(.+),(\\d+),(\\d+),(.?)"); + + /** + * Parse compact meminfo log. Output a CompactMemInfoItem which contains + * the list of processes, their pids and their pss. + */ + @Override + public CompactMemInfoItem parse(List<String> lines) { + CompactMemInfoItem item = new CompactMemInfoItem(); + for (String line : lines) { + Matcher m = PROC_PREFIX.matcher(line); + if (!m.matches()) continue; + + if (m.groupCount() != 5) continue; + + String type = m.group(1); + String name = m.group(2); + int pid = Integer.parseInt(m.group(3)); + long pss = Long.parseLong(m.group(4)); + boolean activities = "a".equals(m.group(5)); + item.addPid(pid, name, type, pss, activities); + } + return item; + } +} diff --git a/tests/src/com/android/loganalysis/parser/CompactMemInfoTest.java b/tests/src/com/android/loganalysis/parser/CompactMemInfoTest.java new file mode 100644 index 0000000..32c7068 --- /dev/null +++ b/tests/src/com/android/loganalysis/parser/CompactMemInfoTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2014 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.CompactMemInfoItem; + +import junit.framework.TestCase; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Arrays; +import java.util.List; + +public class CompactMemInfoTest extends TestCase { + + public void testSingleLine() { + List<String> input = Arrays.asList("proc,cached,com.google.android.youtube,2964,19345,e"); + + CompactMemInfoItem item = new CompactMemInfoParser().parse(input); + + assertEquals(1, item.getPids().size()); + assertEquals("com.google.android.youtube", item.getName(2964)); + assertEquals(19345, item.getPss(2964)); + assertEquals("cached", item.getType(2964)); + assertEquals(false, item.hasActivities(2964)); + } + + public void testMalformedLine() { + List<String> input = Arrays.asList("proc,cached,com.google.android.youtube,a,b,e"); + + CompactMemInfoItem item = new CompactMemInfoParser().parse(input); + + assertEquals(0, item.getPids().size()); + } + + public void testMultipleLines() { + List<String> input = Arrays.asList( + "proc,cached,com.google.android.youtube,2964,19345,e", + "proc,cached,com.google.android.apps.plus,2877,9604,e", + "proc,cached,com.google.android.apps.magazines,2009,20111,e", + "proc,cached,com.google.android.apps.walletnfcrel,10790,11164,e", + "proc,cached,com.google.android.incallui,3410,9491,e"); + + CompactMemInfoItem item = new CompactMemInfoParser().parse(input); + + assertEquals(5, item.getPids().size()); + assertEquals("com.google.android.youtube", item.getName(2964)); + assertEquals(19345, item.getPss(2964)); + assertEquals("cached", item.getType(2964)); + assertEquals(false, item.hasActivities(2964)); + } + + public void testSkipNonProcLines() { + // Skip lines which does not start with proc + + List<String> input = Arrays.asList( + "oom,cached,141357", + "proc,cached,com.google.android.youtube,2964,19345,e", + "proc,cached,com.google.android.apps.plus,2877,9604,e", + "proc,cached,com.google.android.apps.magazines,2009,20111,e", + "proc,cached,com.google.android.apps.walletnfcrel,10790,11164,e", + "proc,cached,com.google.android.incallui,3410,9491,e", + "cat,Native,63169"); + + CompactMemInfoItem item = new CompactMemInfoParser().parse(input); + + assertEquals(5, item.getPids().size()); + assertEquals("com.google.android.youtube", item.getName(2964)); + assertEquals(19345, item.getPss(2964)); + assertEquals("cached", item.getType(2964)); + assertEquals(false, item.hasActivities(2964)); + } + + public void testJson() throws JSONException { + List<String> input = Arrays.asList( + "oom,cached,141357", + "proc,cached,com.google.android.youtube,2964,19345,e", + "proc,cached,com.google.android.apps.plus,2877,9604,e", + "proc,cached,com.google.android.apps.magazines,2009,20111,e", + "proc,cached,com.google.android.apps.walletnfcrel,10790,11164,e", + "proc,cached,com.google.android.incallui,3410,9491,e", + "cat,Native,63169"); + + CompactMemInfoItem item = new CompactMemInfoParser().parse(input); + JSONObject json = item.toJson(); + assertNotNull(json); + + JSONArray processes = json.getJSONArray("processes"); + assertEquals(5, processes.length()); + } +} |