Combine uids for CpuTimePerUidFreq atom

The puller for the atom frequently fails. We believe it is due to the
size of the pulled atoms. No metric can be correctly build from this
atom.

To reduce the size, we apply transformations that we would likely
perform when analyzing this data. We combine times for all shared app
gids together and combine times for the same apps. We also exclude
isolated uids which are frequently recycled and removed from the
underlying data source.

If these optimization do not help, we will need to introduce different
atoms.

Bug: 157535126
Test: cmd stats pull-source 10010
Change-Id: I0d9a18c78f456e1b0f9d7ad322f15354ead9f02b
This commit is contained in:
Rafal Slawik
2020-12-08 00:27:16 +00:00
parent 55ba4ffb1d
commit e69ade3545
2 changed files with 52 additions and 4 deletions

View File

@@ -222,6 +222,14 @@ public final class UserHandle implements Parcelable {
} }
} }
/**
* Whether a UID belongs to a shared app gid.
* @hide
*/
public static boolean isSharedAppGid(int uid) {
return getAppIdFromSharedAppGid(uid) != -1;
}
/** /**
* Returns the user for a given uid. * Returns the user for a given uid.
* @param uid A uid for an application running in a particular user. * @param uid A uid for an application running in a particular user.

View File

@@ -31,6 +31,7 @@ import static android.net.NetworkTemplate.buildTemplateMobileWithRatType;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.NetworkTemplate.getAllCollapsedRatTypes; import static android.net.NetworkTemplate.getAllCollapsedRatTypes;
import static android.os.Debug.getIonHeapsSizeKb; import static android.os.Debug.getIonHeapsSizeKb;
import static android.os.Process.LAST_SHARED_APPLICATION_GID;
import static android.os.Process.getUidForPid; import static android.os.Process.getUidForPid;
import static android.os.storage.VolumeInfo.TYPE_PRIVATE; import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
import static android.os.storage.VolumeInfo.TYPE_PUBLIC; import static android.os.storage.VolumeInfo.TYPE_PUBLIC;
@@ -1517,14 +1518,53 @@ public class StatsPullAtomService extends SystemService {
} }
int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) { int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) {
// Aggregate times for the same uids.
SparseArray<long[]> aggregated = new SparseArray<>();
mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> { mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) { // For uids known to be aggregated from many entries allow mutating in place to avoid
if (cpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) { // many copies. Otherwise, copy before aggregating.
pulledData.add(FrameworkStatsLog.buildStatsEvent( boolean mutateInPlace = false;
atomTag, uid, freqIndex, cpuFreqTimeMs[freqIndex])); if (UserHandle.isIsolated(uid)) {
// Skip individual isolated uids because they are recycled and quickly removed from
// the underlying data source.
return;
} else if (UserHandle.isSharedAppGid(uid)) {
// All shared app gids are accounted together.
uid = LAST_SHARED_APPLICATION_GID;
mutateInPlace = true;
} else if (UserHandle.isApp(uid)) {
// Apps are accounted under their app id.
uid = UserHandle.getAppId(uid);
}
long[] aggCpuFreqTimeMs = aggregated.get(uid);
if (aggCpuFreqTimeMs != null) {
if (!mutateInPlace) {
aggCpuFreqTimeMs = Arrays.copyOf(aggCpuFreqTimeMs, cpuFreqTimeMs.length);
aggregated.put(uid, aggCpuFreqTimeMs);
} }
for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
aggCpuFreqTimeMs[freqIndex] += cpuFreqTimeMs[freqIndex];
}
} else {
if (mutateInPlace) {
cpuFreqTimeMs = Arrays.copyOf(cpuFreqTimeMs, cpuFreqTimeMs.length);
}
aggregated.put(uid, cpuFreqTimeMs);
} }
}); });
int size = aggregated.size();
for (int i = 0; i < size; ++i) {
int uid = aggregated.keyAt(i);
long[] aggCpuFreqTimeMs = aggregated.valueAt(i);
for (int freqIndex = 0; freqIndex < aggCpuFreqTimeMs.length; ++freqIndex) {
if (aggCpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) {
pulledData.add(FrameworkStatsLog.buildStatsEvent(
atomTag, uid, freqIndex, aggCpuFreqTimeMs[freqIndex]));
}
}
}
return StatsManager.PULL_SUCCESS; return StatsManager.PULL_SUCCESS;
} }