Add stats puller for aggregated procstats

Implement puller code in StatsPullAtomService & ProcessStats that will
output new pre-aggregated proto form of ProcStats data.

Change-Id: Id3d28b0ec135b1b25f3b70a5eb29bec67d71805d
Test: local debugging, see b/152397079
Bug: b/152397079
Bug: b/145203981
This commit is contained in:
Richard Gaywood
2020-03-16 17:49:54 +00:00
parent 7a003a8b1b
commit 3b428af57f
4 changed files with 86 additions and 46 deletions

View File

@@ -534,16 +534,31 @@ public final class DumpUtils {
int procStateIndex = curState % STATE_COUNT;
// Remap process state per array above.
procStateIndex = PROCESS_STATS_STATE_TO_AGGREGATED_STATE[procStateIndex];
try {
procStateIndex = PROCESS_STATS_STATE_TO_AGGREGATED_STATE[procStateIndex];
} catch (IndexOutOfBoundsException e) {
procStateIndex = ProcessStatsEnums.AGGREGATED_PROCESS_STATE_UNKNOWN;
}
// Pack screen & process state using bit shifting
return (procStateIndex << 8) | screenStateIndex;
return (procStateIndex << 0xf) | screenStateIndex;
}
/** Print aggregated tags generated via {@code #aggregateCurrentProcessState}. */
public static void printAggregatedProcStateTagProto(ProtoOutputStream proto, long screenId,
long stateId, int state) {
proto.write(screenId, ADJ_SCREEN_PROTO_ENUMS[state >> 8]);
proto.write(stateId, STATE_PROTO_ENUMS[state]);
// screen state is in lowest 0xf bits, process state is in next 0xf bits up
try {
proto.write(stateId, STATE_PROTO_ENUMS[state >> 0xf]);
} catch (IndexOutOfBoundsException e) {
proto.write(stateId, ProcessStatsEnums.PROCESS_STATE_UNKNOWN);
}
try {
proto.write(screenId, ADJ_SCREEN_PROTO_ENUMS[state & 0xf]);
} catch (IndexOutOfBoundsException e) {
proto.write(screenId, ProcessStatsEnums.SCREEN_STATE_UNKNOWN);
}
}
}

View File

@@ -1436,7 +1436,7 @@ public final class ProcessState {
}
int index = durationByState.indexOfKey(aggregatedType);
if (index >= 0) {
durationByState.put(aggregatedType, time + durationByState.valueAt(aggregatedType));
durationByState.put(aggregatedType, time + durationByState.valueAt(index));
} else {
durationByState.put(aggregatedType, time);
}
@@ -1502,14 +1502,15 @@ public final class ProcessState {
proto.write(ProcessStatsProto.UID, uid);
for (int i = 0; i < durationByState.size(); i++) {
final int aggregatedKey = mPssTable.getKeyAt(i);
final long stateToken = proto.start(ProcessStatsProto.STATES);
final int aggregatedKey = durationByState.keyAt(i);
DumpUtils.printAggregatedProcStateTagProto(proto,
ProcessStatsStateProto.SCREEN_STATE,
ProcessStatsStateProto.PROCESS_STATE,
durationByState.keyAt(i));
proto.write(ProcessStatsStateProto.DURATION_MS, durationByState.valueAt(i));
aggregatedKey);
proto.write(ProcessStatsStateProto.DURATION_MS, durationByState.get(aggregatedKey));
ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.RSS,
0, /* do not output a minimum value */

View File

@@ -2178,29 +2178,7 @@ public final class ProcessStats implements Parcelable {
* Writes to ProtoOutputStream.
*/
public void dumpDebug(ProtoOutputStream proto, long now, int section) {
proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
proto.write(ProcessStatsSectionProto.START_UPTIME_MS, mTimePeriodStartUptime);
proto.write(ProcessStatsSectionProto.END_UPTIME_MS, mTimePeriodEndUptime);
proto.write(ProcessStatsSectionProto.RUNTIME, mRuntime);
proto.write(ProcessStatsSectionProto.HAS_SWAPPED_PSS, mHasSwappedOutPss);
boolean partial = true;
if ((mFlags & FLAG_SHUTDOWN) != 0) {
proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SHUTDOWN);
partial = false;
}
if ((mFlags & FLAG_SYSPROPS) != 0) {
proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SYSPROPS);
partial = false;
}
if ((mFlags & FLAG_COMPLETE) != 0) {
proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_COMPLETE);
partial = false;
}
if (partial) {
proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_PARTIAL);
}
dumpProtoPreamble(proto);
final int NPAGETYPES = mPageTypeLabels.size();
for (int i = 0; i < NPAGETYPES; i++) {
@@ -2247,6 +2225,49 @@ public final class ProcessStats implements Parcelable {
}
}
/** Similar to {@code #dumpDebug}, but with a reduced/aggregated subset of states. */
public void dumpAggregatedProtoForStatsd(ProtoOutputStream proto) {
dumpProtoPreamble(proto);
final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
for (int ip = 0; ip < procMap.size(); ip++) {
final String procName = procMap.keyAt(ip);
final SparseArray<ProcessState> uids = procMap.valueAt(ip);
for (int iu = 0; iu < uids.size(); iu++) {
final int uid = uids.keyAt(iu);
final ProcessState procState = uids.valueAt(iu);
procState.dumpAggregatedProtoForStatsd(proto,
ProcessStatsSectionProto.PROCESS_STATS,
procName, uid, mTimePeriodEndRealtime);
}
}
}
private void dumpProtoPreamble(ProtoOutputStream proto) {
proto.write(ProcessStatsSectionProto.START_REALTIME_MS, mTimePeriodStartRealtime);
proto.write(ProcessStatsSectionProto.END_REALTIME_MS,
mRunning ? SystemClock.elapsedRealtime() : mTimePeriodEndRealtime);
proto.write(ProcessStatsSectionProto.START_UPTIME_MS, mTimePeriodStartUptime);
proto.write(ProcessStatsSectionProto.END_UPTIME_MS, mTimePeriodEndUptime);
proto.write(ProcessStatsSectionProto.RUNTIME, mRuntime);
proto.write(ProcessStatsSectionProto.HAS_SWAPPED_PSS, mHasSwappedOutPss);
boolean partial = true;
if ((mFlags & FLAG_SHUTDOWN) != 0) {
proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SHUTDOWN);
partial = false;
}
if ((mFlags & FLAG_SYSPROPS) != 0) {
proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_SYSPROPS);
partial = false;
}
if ((mFlags & FLAG_COMPLETE) != 0) {
proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_COMPLETE);
partial = false;
}
if (partial) {
proto.write(ProcessStatsSectionProto.STATUS, ProcessStatsSectionProto.STATUS_PARTIAL);
}
}
final public static class ProcessStateHolder {
public final long appVersion;
public ProcessState state;

View File

@@ -2041,32 +2041,35 @@ public class StatsPullAtomService extends SystemService {
synchronized (mProcessStatsLock) {
final long token = Binder.clearCallingIdentity();
try {
// force procstats to flush & combine old files into one store
long lastHighWaterMark = readProcStatsHighWaterMark(section);
List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
long highWaterMark = processStatsService.getCommittedStats(
lastHighWaterMark, section, true, statsFiles);
if (statsFiles.size() != 1) {
return StatsManager.PULL_SKIP;
}
unpackStreamedData(atomTag, pulledData, statsFiles);
ProcessStats procStats = new ProcessStats(false);
long highWaterMark = processStatsService.getCommittedStatsMerged(
lastHighWaterMark, section, true, statsFiles, procStats);
// aggregate the data together for westworld consumption
ProtoOutputStream proto = new ProtoOutputStream();
procStats.dumpAggregatedProtoForStatsd(proto);
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
.writeByteArray(proto.getBytes())
.build();
pulledData.add(e);
new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark)
.delete();
new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + highWaterMark)
.createNewFile();
} catch (IOException e) {
Slog.e(TAG, "Getting procstats failed: ", e);
return StatsManager.PULL_SKIP;
} catch (RemoteException e) {
Slog.e(TAG, "Getting procstats failed: ", e);
return StatsManager.PULL_SKIP;
} catch (SecurityException e) {
} catch (RemoteException | IOException e) {
Slog.e(TAG, "Getting procstats failed: ", e);
return StatsManager.PULL_SKIP;
} finally {
Binder.restoreCallingIdentity(token);
}
}
return StatsManager.PULL_SUCCESS;
}