Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f669bf2 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue #122854187: Need to report page fragmentation in procstats protobuf

Add the page fragmentation data to the current protobuf.

Also fix bugs in how it was being collected...  the data in the kernel
didn't match what it was collecting (it was combining node and zone
together in a zone int...  but node is an int, zone is a separate
string).

Example new output:

vailable pages by page size:
Node   0 Zone     DMA       Unmovable      0     1     1     1     0     1     1     0     0     0     0
Node   0 Zone     DMA     Reclaimable      1     1     0     1     1     1     1     1     1     0     0
Node   0 Zone     DMA         Movable      1     1     0     0     1     0     1     0     1     1   291
Node   0 Zone     DMA             CMA      1     1     0     0     0     1     1     1     1     1    35
Node   0 Zone     DMA         Reserve      0     0     0     0     0     0     0     0     0     0     1
Node   0 Zone     DMA         Isolate      0     0     0     0     0     0     0     0     0     0     0
Node   0 Zone  Normal       Unmovable      1     9     3     2     1     0     1     0     1     0     0
Node   0 Zone  Normal     Reclaimable      0    15     3     3     1     0     1     0     1     0     0
Node   0 Zone  Normal         Movable      0     1     1     1     0     0     1     1     0     1   338
Node   0 Zone  Normal             CMA      0     0     0     0     0     0     0     0     0     0     0
Node   0 Zone  Normal         Reserve      0     0     0     0     0     0     0     0     0     0     2
Node   0 Zone  Normal         Isolate      0     0     0     0     0     0     0     0     0     0     0

Change-Id: I029d59b8d088b20fafaea04dde766012c3d448cd
Fixes: 122854187
Test: manual
parent d50bda40
Loading
Loading
Loading
Loading
+40 −13
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.service.procstats.ProcessStatsAvailablePagesProto;
import android.service.procstats.ProcessStatsPackageProto;
import android.service.procstats.ProcessStatsSectionProto;
import android.text.format.DateFormat;
@@ -178,7 +179,7 @@ public final class ProcessStats implements Parcelable {
            {"proc", "pkg-proc", "pkg-svc", "pkg-asc", "pkg-all", "all"};

    // Current version of the parcel format.
    private static final int PARCEL_VERSION = 35;
    private static final int PARCEL_VERSION = 36;
    // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
    private static final int MAGIC = 0x50535454;

@@ -237,10 +238,11 @@ public final class ProcessStats implements Parcelable {
    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[]>();
            "^Node\\s+(\\d+),.* zone\\s+(\\w+),.* type\\s+(\\w+)\\s+([\\s\\d]+?)\\s*$");
    private final ArrayList<Integer> mPageTypeNodes = new ArrayList<>();
    private final ArrayList<String> mPageTypeZones = new ArrayList<>();
    private final ArrayList<String> mPageTypeLabels = new ArrayList<>();
    private final ArrayList<int[]> mPageTypeSizes = new ArrayList<>();

    public ProcessStats(boolean running) {
        mRunning = running;
@@ -621,6 +623,7 @@ public final class ProcessStats implements Parcelable {
        try {
            reader = new BufferedReader(new FileReader("/proc/pagetypeinfo"));
            final Matcher matcher = sPageTypeRegex.matcher("");
            mPageTypeNodes.clear();
            mPageTypeZones.clear();
            mPageTypeLabels.clear();
            mPageTypeSizes.clear();
@@ -631,16 +634,18 @@ public final class ProcessStats implements Parcelable {
                }
                matcher.reset(line);
                if (matcher.matches()) {
                    final Integer zone = Integer.valueOf(matcher.group(1), 10);
                    if (zone == null) {
                    final Integer node = Integer.valueOf(matcher.group(1), 10);
                    if (node == null) {
                        continue;
                    }
                    mPageTypeZones.add(zone);
                    mPageTypeLabels.add(matcher.group(2));
                    mPageTypeSizes.add(splitAndParseNumbers(matcher.group(3)));
                    mPageTypeNodes.add(node);
                    mPageTypeZones.add(matcher.group(2));
                    mPageTypeLabels.add(matcher.group(3));
                    mPageTypeSizes.add(splitAndParseNumbers(matcher.group(4)));
                }
            }
        } catch (IOException ex) {
            mPageTypeNodes.clear();
            mPageTypeZones.clear();
            mPageTypeLabels.clear();
            mPageTypeSizes.clear();
@@ -935,7 +940,8 @@ public final class ProcessStats implements Parcelable {
        final int NPAGETYPES = mPageTypeLabels.size();
        out.writeInt(NPAGETYPES);
        for (int i=0; i<NPAGETYPES; i++) {
            out.writeInt(mPageTypeZones.get(i));
            out.writeInt(mPageTypeNodes.get(i));
            out.writeString(mPageTypeZones.get(i));
            out.writeString(mPageTypeLabels.get(i));
            out.writeIntArray(mPageTypeSizes.get(i));
        }
@@ -1244,6 +1250,8 @@ public final class ProcessStats implements Parcelable {

        // Fragmentation info
        final int NPAGETYPES = in.readInt();
        mPageTypeNodes.clear();
        mPageTypeNodes.ensureCapacity(NPAGETYPES);
        mPageTypeZones.clear();
        mPageTypeZones.ensureCapacity(NPAGETYPES);
        mPageTypeLabels.clear();
@@ -1251,7 +1259,8 @@ public final class ProcessStats implements Parcelable {
        mPageTypeSizes.clear();
        mPageTypeSizes.ensureCapacity(NPAGETYPES);
        for (int i=0; i<NPAGETYPES; i++) {
            mPageTypeZones.add(in.readInt());
            mPageTypeNodes.add(in.readInt());
            mPageTypeZones.add(in.readString());
            mPageTypeLabels.add(in.readString());
            mPageTypeSizes.add(in.createIntArray());
        }
@@ -1764,7 +1773,8 @@ public final class ProcessStats implements Parcelable {
        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));
            pw.format("Node %3d Zone %7s  %14s ", mPageTypeNodes.get(i), 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++) {
@@ -2095,6 +2105,9 @@ public final class ProcessStats implements Parcelable {
            pw.print(",");
            pw.print(mPageTypeZones.get(i));
            pw.print(",");
            // Wasn't included in original output.
            //pw.print(mPageTypeNodes.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++) {
@@ -2135,6 +2148,20 @@ public final class ProcessStats implements Parcelable {
            proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_PARTIAL);
        }

        final int NPAGETYPES = mPageTypeLabels.size();
        for (int i = 0; i < NPAGETYPES; i++) {
            final long token = proto.start(ProcessStatsSectionProto.AVAILABLE_PAGES);
            proto.write(ProcessStatsAvailablePagesProto.NODE, mPageTypeNodes.get(i));
            proto.write(ProcessStatsAvailablePagesProto.ZONE, mPageTypeZones.get(i));
            proto.write(ProcessStatsAvailablePagesProto.LABEL, mPageTypeLabels.get(i));
            final int[] sizes = mPageTypeSizes.get(i);
            final int N = sizes == null ? 0 : sizes.length;
            for (int j = 0; j < N; j++) {
                proto.write(ProcessStatsAvailablePagesProto.PAGES_PER_ORDER, sizes[j]);
            }
            proto.end(token);
        }

        final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
        if ((section & REPORT_PROC_STATS) != 0) {
            for (int ip = 0; ip < procMap.size(); ip++) {
+22 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ message ProcessStatsServiceDumpProto {
 * Data model from /frameworks/base/core/java/com/android/internal/app/procstats/ProcessStats.java
 * This proto is defined based on the writeToParcel method.
 *
 * Next Tag: 10
 * Next Tag: 11
 */
message ProcessStatsSectionProto {
    option (android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -76,6 +76,9 @@ message ProcessStatsSectionProto {
    }
    repeated Status status = 7;

    // Number of pages available of various types and sizes, representation fragmentation.
    repeated ProcessStatsAvailablePagesProto available_pages = 10;

    // Stats for each process.
    repeated ProcessStatsProto process_stats = 8;

@@ -83,6 +86,24 @@ message ProcessStatsSectionProto {
    repeated ProcessStatsPackageProto package_stats = 9;
}

// Next Tag: 5
message ProcessStatsAvailablePagesProto {
    option (android.msg_privacy).dest = DEST_AUTOMATIC;

    // Node these pages are in (as per /proc/pagetypeinfo)
    optional int32 node = 1;

    // Zone these pages are in (as per /proc/pagetypeinfo)
    optional string zone = 2;

    // Label for the type of these pages (as per /proc/pagetypeinfo)
    optional string label = 3;

    // Distribution of number of pages available by order size.  First entry in array is
    // order 0, second is order 1, etc.  Each order increase is a doubling of page size.
    repeated int32 pages_per_order = 4;
}

// Next Tag: 10
message ProcessStatsStateProto {
    option (android.msg_privacy).dest = DEST_AUTOMATIC;