summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Joe Onorato <joeo@google.com> 2016-05-19 15:46:00 -0700
committer Joe Onorato <joeo@google.com> 2016-05-23 11:33:11 -0700
commitc23befa183a53af54ea1c4f6c6f0168e38c2636b (patch)
tree26ba02c3cd288836622742e37b63aafa084b219e
parent6a983faab35cc4f22611b0cb8041f4dcbac545dc (diff)
Add data from /proc/pagetypeinfo to procstats.
This data tells us the number of pages of each type that are available by page size. It is collected each time the procstats snapshot is taken, and printed in the checkin and verbose (dumpsys procstats -a) modes. Change-Id: I14562eac15833617391c560638a9e7d239ef8db6
-rw-r--r--core/java/com/android/internal/app/procstats/ProcessStats.java166
1 files changed, 165 insertions, 1 deletions
diff --git a/core/java/com/android/internal/app/procstats/ProcessStats.java b/core/java/com/android/internal/app/procstats/ProcessStats.java
index fb2337e447e4..35b53c2298bb 100644
--- a/core/java/com/android/internal/app/procstats/ProcessStats.java
+++ b/core/java/com/android/internal/app/procstats/ProcessStats.java
@@ -43,6 +43,8 @@ import com.android.internal.app.procstats.DumpUtils.*;
import dalvik.system.VMRuntime;
import libcore.util.EmptyArray;
+import java.io.BufferedReader;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -51,6 +53,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Objects;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
public final class ProcessStats implements Parcelable {
public static final String TAG = "ProcessStats";
@@ -151,7 +155,7 @@ public final class ProcessStats implements Parcelable {
};
// Current version of the parcel format.
- private static final int PARCEL_VERSION = 20;
+ private static final int PARCEL_VERSION = 21;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0x50535454;
@@ -188,6 +192,12 @@ public final class ProcessStats implements Parcelable {
// For reading parcels.
ArrayList<String> mIndexToCommonString;
+ private static final Pattern sPageTypeRegex = Pattern.compile(
+ "^Node\\s+(\\d+),.*. type\\s+(\\w+)\\s+([\\s\\d]+?)\\s*$");
+ private final ArrayList<Integer> mPageTypeZones = new ArrayList<Integer>();
+ private final ArrayList<String> mPageTypeLabels = new ArrayList<String>();
+ private final ArrayList<int[]> mPageTypeSizes = new ArrayList<int[]>();
+
public ProcessStats(boolean running) {
mRunning = running;
reset();
@@ -493,6 +503,7 @@ public final class ProcessStats implements Parcelable {
mReadError = null;
mFlags = 0;
evaluateSystemProperties(true);
+ updateFragmentation();
}
public boolean evaluateSystemProperties(boolean update) {
@@ -515,6 +526,101 @@ public final class ProcessStats implements Parcelable {
static final int[] BAD_TABLE = new int[0];
+
+ /**
+ * Load the system's memory fragmentation info.
+ */
+ public void updateFragmentation() {
+ // Parse /proc/pagetypeinfo and store the values.
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader("/proc/pagetypeinfo"));
+ final Matcher matcher = sPageTypeRegex.matcher("");
+ mPageTypeZones.clear();
+ mPageTypeLabels.clear();
+ mPageTypeSizes.clear();
+ while (true) {
+ final String line = reader.readLine();
+ if (line == null) {
+ break;
+ }
+ matcher.reset(line);
+ if (matcher.matches()) {
+ final Integer zone = Integer.valueOf(matcher.group(1), 10);
+ if (zone == null) {
+ continue;
+ }
+ mPageTypeZones.add(zone);
+ mPageTypeLabels.add(matcher.group(2));
+ mPageTypeSizes.add(splitAndParseNumbers(matcher.group(3)));
+ }
+ }
+ } catch (IOException ex) {
+ mPageTypeZones.clear();
+ mPageTypeLabels.clear();
+ mPageTypeSizes.clear();
+ return;
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException allHopeIsLost) {
+ }
+ }
+ }
+ }
+
+ /**
+ * Split the string of digits separaed by spaces. There must be no
+ * leading or trailing spaces. The format is ensured by the regex
+ * above.
+ */
+ private static int[] splitAndParseNumbers(String s) {
+ // These are always positive and the numbers can't be so big that we'll overflow
+ // so just do the parsing inline.
+ boolean digit = false;
+ int count = 0;
+ final int N = s.length();
+ // Count the numbers
+ for (int i=0; i<N; i++) {
+ final char c = s.charAt(i);
+ if (c >= '0' && c <= '9') {
+ if (!digit) {
+ digit = true;
+ count++;
+ }
+ } else {
+ digit = false;
+ }
+ }
+ // Parse the numbers
+ final int[] result = new int[count];
+ int p = 0;
+ int val = 0;
+ for (int i=0; i<N; i++) {
+ final char c = s.charAt(i);
+ if (c >= '0' && c <= '9') {
+ if (!digit) {
+ digit = true;
+ val = c - '0';
+ } else {
+ val *= 10;
+ val += c - '0';
+ }
+ } else {
+ if (digit) {
+ digit = false;
+ result[p++] = val;
+ }
+ }
+ }
+ if (count > 0) {
+ result[count-1] = val;
+ }
+ return result;
+ }
+
+
private void writeCompactedLongArray(Parcel out, long[] array, int num) {
for (int i=0; i<num; i++) {
long val = array[i];
@@ -717,6 +823,15 @@ public final class ProcessStats implements Parcelable {
}
}
+ // Fragmentation info (/proc/pagetypeinfo)
+ final int NPAGETYPES = mPageTypeLabels.size();
+ out.writeInt(NPAGETYPES);
+ for (int i=0; i<NPAGETYPES; i++) {
+ out.writeInt(mPageTypeZones.get(i));
+ out.writeString(mPageTypeLabels.get(i));
+ out.writeIntArray(mPageTypeSizes.get(i));
+ }
+
mCommonStringToIndex = null;
}
@@ -981,6 +1096,20 @@ public final class ProcessStats implements Parcelable {
}
}
+ // Fragmentation info
+ final int NPAGETYPES = in.readInt();
+ mPageTypeZones.clear();
+ mPageTypeZones.ensureCapacity(NPAGETYPES);
+ mPageTypeLabels.clear();
+ mPageTypeLabels.ensureCapacity(NPAGETYPES);
+ mPageTypeSizes.clear();
+ mPageTypeSizes.ensureCapacity(NPAGETYPES);
+ for (int i=0; i<NPAGETYPES; i++) {
+ mPageTypeZones.add(in.readInt());
+ mPageTypeLabels.add(in.readString());
+ mPageTypeSizes.add(in.createIntArray());
+ }
+
mIndexToCommonString = null;
if (DEBUG_PARCEL) Slog.d(TAG, "Successfully read procstats!");
@@ -1271,6 +1400,8 @@ public final class ProcessStats implements Parcelable {
*/
pw.print(" mRunning="); pw.println(mRunning);
}
+
+ dumpFragmentationLocked(pw);
}
public void dumpSummaryLocked(PrintWriter pw, String reqPackage, long now, boolean activeOnly) {
@@ -1282,6 +1413,21 @@ public final class ProcessStats implements Parcelable {
dumpTotalsLocked(pw, now);
}
+ private void dumpFragmentationLocked(PrintWriter pw) {
+ pw.println();
+ pw.println("Available pages by page size:");
+ final int NPAGETYPES = mPageTypeLabels.size();
+ for (int i=0; i<NPAGETYPES; i++) {
+ pw.format("Zone %3d %14s ", mPageTypeZones.get(i), mPageTypeLabels.get(i));
+ final int[] sizes = mPageTypeSizes.get(i);
+ final int N = sizes == null ? 0 : sizes.length;
+ for (int j=0; j<N; j++) {
+ pw.format("%6d", sizes[j]);
+ }
+ pw.println();
+ }
+ }
+
long printMemoryCategory(PrintWriter pw, String prefix, String label, double memWeight,
long totalTime, long curTotalMem, int samples) {
if (memWeight != 0) {
@@ -1540,6 +1686,24 @@ public final class ProcessStats implements Parcelable {
pw.print(totalMem.processStateSamples[i]);
}
pw.println();
+
+ final int NPAGETYPES = mPageTypeLabels.size();
+ for (int i=0; i<NPAGETYPES; i++) {
+ pw.print("availablepages,");
+ pw.print(mPageTypeLabels.get(i));
+ pw.print(",");
+ pw.print(mPageTypeZones.get(i));
+ pw.print(",");
+ final int[] sizes = mPageTypeSizes.get(i);
+ final int N = sizes == null ? 0 : sizes.length;
+ for (int j=0; j<N; j++) {
+ if (j != 0) {
+ pw.print(",");
+ }
+ pw.print(sizes[j]);
+ }
+ pw.println();
+ }
}