diff options
| author | 2016-05-19 15:46:00 -0700 | |
|---|---|---|
| committer | 2016-05-23 11:33:11 -0700 | |
| commit | c23befa183a53af54ea1c4f6c6f0168e38c2636b (patch) | |
| tree | 26ba02c3cd288836622742e37b63aafa084b219e | |
| parent | 6a983faab35cc4f22611b0cb8041f4dcbac545dc (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.java | 166 |
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(); + } } |