Merge "Manage time_in_state tracking from one place" into sc-dev
This commit is contained in:
@@ -16,11 +16,79 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
/** CPU tracking using eBPF. */
|
||||
import android.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* CPU tracking using eBPF.
|
||||
*
|
||||
* The tracking state and data about available frequencies are cached to avoid JNI calls and
|
||||
* creating temporary arrays. The data is stored in a format that is convenient for metrics
|
||||
* computation.
|
||||
*
|
||||
* Synchronization is not needed because the underlying native library can be invoked concurrently
|
||||
* and getters are idempotent.
|
||||
*/
|
||||
public final class KernelCpuBpfTracking {
|
||||
private static boolean sTracking = false;
|
||||
|
||||
/** Cached mapping from frequency index to frequency in kHz. */
|
||||
private static long[] sFreqs = null;
|
||||
|
||||
/** Cached mapping from frequency index to CPU cluster / policy. */
|
||||
private static int[] sFreqsClusters = null;
|
||||
|
||||
private KernelCpuBpfTracking() {
|
||||
}
|
||||
|
||||
/** Returns whether CPU tracking using eBPF is supported. */
|
||||
public static native boolean isSupported();
|
||||
|
||||
/** Starts CPU tracking using eBPF. */
|
||||
public static boolean startTracking() {
|
||||
if (!sTracking) {
|
||||
sTracking = startTrackingInternal();
|
||||
}
|
||||
return sTracking;
|
||||
}
|
||||
|
||||
private static native boolean startTrackingInternal();
|
||||
|
||||
/** Returns frequencies in kHz on which CPU is tracked. Empty if not supported. */
|
||||
public static long[] getFreqs() {
|
||||
if (sFreqs == null) {
|
||||
long[] freqs = getFreqsInternal();
|
||||
if (freqs == null) {
|
||||
return new long[0];
|
||||
}
|
||||
sFreqs = freqs;
|
||||
}
|
||||
return sFreqs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static native long[] getFreqsInternal();
|
||||
|
||||
/**
|
||||
* Returns the cluster (policy) number for each frequency on which CPU is tracked. Empty if
|
||||
* not supported.
|
||||
*/
|
||||
public static int[] getFreqsClusters() {
|
||||
if (sFreqsClusters == null) {
|
||||
int[] freqsClusters = getFreqsClustersInternal();
|
||||
if (freqsClusters == null) {
|
||||
return new int[0];
|
||||
}
|
||||
sFreqsClusters = freqsClusters;
|
||||
}
|
||||
return sFreqsClusters;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static native int[] getFreqsClustersInternal();
|
||||
|
||||
/** Returns the number of clusters (policies). */
|
||||
public static int getClusters() {
|
||||
int[] freqClusters = getFreqsClusters();
|
||||
return freqClusters.length > 0 ? freqClusters[freqClusters.length - 1] + 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,22 +16,22 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
/**
|
||||
* Reads total CPU time bpf map.
|
||||
*/
|
||||
import android.annotation.Nullable;
|
||||
|
||||
/** Reads total CPU time bpf map. */
|
||||
public final class KernelCpuTotalBpfMapReader {
|
||||
private KernelCpuTotalBpfMapReader() {
|
||||
}
|
||||
|
||||
/** Reads total CPU time from bpf map. */
|
||||
public static native boolean read(Callback callback);
|
||||
|
||||
/** Callback accepting values read from bpf map. */
|
||||
public interface Callback {
|
||||
/**
|
||||
* Accepts values read from bpf map: cluster index, frequency in kilohertz and time in
|
||||
* milliseconds that the cpu cluster spent at the frequency (excluding sleep).
|
||||
*/
|
||||
void accept(int cluster, int freqKhz, long timeMs);
|
||||
/** Reads total CPU times (excluding sleep) per frequency in milliseconds from bpf map. */
|
||||
@Nullable
|
||||
public static long[] read() {
|
||||
if (!KernelCpuBpfTracking.startTracking()) {
|
||||
return null;
|
||||
}
|
||||
return readInternal();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static native long[] readInternal();
|
||||
}
|
||||
|
||||
@@ -68,14 +68,15 @@ public abstract class KernelCpuUidBpfMapReader {
|
||||
|
||||
final String mTag = this.getClass().getSimpleName();
|
||||
private int mErrors = 0;
|
||||
private boolean mTracking = false;
|
||||
protected SparseArray<long[]> mData = new SparseArray<>();
|
||||
private long mLastReadTime = 0;
|
||||
protected final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
|
||||
protected final ReentrantReadWriteLock.ReadLock mReadLock = mLock.readLock();
|
||||
protected final ReentrantReadWriteLock.WriteLock mWriteLock = mLock.writeLock();
|
||||
|
||||
public native boolean startTrackingBpfTimes();
|
||||
public boolean startTrackingBpfTimes() {
|
||||
return KernelCpuBpfTracking.startTracking();
|
||||
}
|
||||
|
||||
protected abstract boolean readBpfData();
|
||||
|
||||
@@ -116,7 +117,7 @@ public abstract class KernelCpuUidBpfMapReader {
|
||||
if (mErrors > ERROR_THRESHOLD) {
|
||||
return null;
|
||||
}
|
||||
if (!mTracking && !startTrackingBpfTimes()) {
|
||||
if (!startTrackingBpfTimes()) {
|
||||
Slog.w(mTag, "Failed to start tracking");
|
||||
mErrors++;
|
||||
return null;
|
||||
@@ -182,7 +183,9 @@ public abstract class KernelCpuUidBpfMapReader {
|
||||
protected final native boolean readBpfData();
|
||||
|
||||
@Override
|
||||
public final native long[] getDataDimensions();
|
||||
public final long[] getDataDimensions() {
|
||||
return KernelCpuBpfTracking.getFreqsInternal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUidsInRange(int startUid, int endUid) {
|
||||
|
||||
@@ -24,8 +24,48 @@ static jboolean KernelCpuBpfTracking_isSupported(JNIEnv *, jobject) {
|
||||
return android::bpf::isTrackingUidTimesSupported() ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean KernelCpuBpfTracking_startTrackingInternal(JNIEnv *, jobject) {
|
||||
return android::bpf::startTrackingUidTimes();
|
||||
}
|
||||
|
||||
static jlongArray KernelCpuBpfTracking_getFreqsInternal(JNIEnv *env, jobject) {
|
||||
auto freqs = android::bpf::getCpuFreqs();
|
||||
if (!freqs) return NULL;
|
||||
|
||||
std::vector<uint64_t> allFreqs;
|
||||
for (const auto &vec : *freqs) std::copy(vec.begin(), vec.end(), std::back_inserter(allFreqs));
|
||||
|
||||
auto ar = env->NewLongArray(allFreqs.size());
|
||||
if (ar != NULL) {
|
||||
env->SetLongArrayRegion(ar, 0, allFreqs.size(),
|
||||
reinterpret_cast<const jlong *>(allFreqs.data()));
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
|
||||
static jintArray KernelCpuBpfTracking_getFreqsClustersInternal(JNIEnv *env, jobject) {
|
||||
auto freqs = android::bpf::getCpuFreqs();
|
||||
if (!freqs) return NULL;
|
||||
|
||||
std::vector<uint32_t> freqsClusters;
|
||||
uint32_t clusters = freqs->size();
|
||||
for (uint32_t c = 0; c < clusters; ++c) {
|
||||
freqsClusters.insert(freqsClusters.end(), (*freqs)[c].size(), c);
|
||||
}
|
||||
|
||||
auto ar = env->NewIntArray(freqsClusters.size());
|
||||
if (ar != NULL) {
|
||||
env->SetIntArrayRegion(ar, 0, freqsClusters.size(),
|
||||
reinterpret_cast<const jint *>(freqsClusters.data()));
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
|
||||
static const JNINativeMethod methods[] = {
|
||||
{"isSupported", "()Z", (void *)KernelCpuBpfTracking_isSupported},
|
||||
{"startTrackingInternal", "()Z", (void *)KernelCpuBpfTracking_startTrackingInternal},
|
||||
{"getFreqsInternal", "()[J", (void *)KernelCpuBpfTracking_getFreqsInternal},
|
||||
{"getFreqsClustersInternal", "()[I", (void *)KernelCpuBpfTracking_getFreqsClustersInternal},
|
||||
};
|
||||
|
||||
int register_com_android_internal_os_KernelCpuBpfTracking(JNIEnv *env) {
|
||||
|
||||
@@ -20,33 +20,27 @@
|
||||
|
||||
namespace android {
|
||||
|
||||
static jboolean KernelCpuTotalBpfMapReader_read(JNIEnv *env, jobject, jobject callback) {
|
||||
jclass callbackClass = env->GetObjectClass(callback);
|
||||
jmethodID callbackMethod = env->GetMethodID(callbackClass, "accept", "(IIJ)V");
|
||||
if (callbackMethod == 0) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
auto freqs = android::bpf::getCpuFreqs();
|
||||
if (!freqs) return JNI_FALSE;
|
||||
static jlongArray KernelCpuTotalBpfMapReader_readInternal(JNIEnv *env, jobject) {
|
||||
auto freqTimes = android::bpf::getTotalCpuFreqTimes();
|
||||
if (!freqTimes) return JNI_FALSE;
|
||||
|
||||
auto freqsClusterSize = (*freqs).size();
|
||||
for (uint32_t clusterIndex = 0; clusterIndex < freqsClusterSize; ++clusterIndex) {
|
||||
auto freqsSize = (*freqs)[clusterIndex].size();
|
||||
for (uint32_t freqIndex = 0; freqIndex < freqsSize; ++freqIndex) {
|
||||
env->CallVoidMethod(callback, callbackMethod, clusterIndex,
|
||||
(*freqs)[clusterIndex][freqIndex],
|
||||
(*freqTimes)[clusterIndex][freqIndex] / 1000000);
|
||||
std::vector<uint64_t> allTimes;
|
||||
for (const auto &vec : *freqTimes) {
|
||||
for (const auto &timeNs : vec) {
|
||||
allTimes.push_back(timeNs / 1000000);
|
||||
}
|
||||
}
|
||||
return JNI_TRUE;
|
||||
|
||||
auto ar = env->NewLongArray(allTimes.size());
|
||||
if (ar != NULL) {
|
||||
env->SetLongArrayRegion(ar, 0, allTimes.size(),
|
||||
reinterpret_cast<const jlong *>(allTimes.data()));
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
|
||||
static const JNINativeMethod methods[] = {
|
||||
{"read", "(Lcom/android/internal/os/KernelCpuTotalBpfMapReader$Callback;)Z",
|
||||
(void *)KernelCpuTotalBpfMapReader_read},
|
||||
{"readInternal", "()[J", (void *)KernelCpuTotalBpfMapReader_readInternal},
|
||||
};
|
||||
|
||||
int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv *env) {
|
||||
|
||||
@@ -82,25 +82,9 @@ static jboolean KernelCpuUidFreqTimeBpfMapReader_readBpfData(JNIEnv *env, jobjec
|
||||
return true;
|
||||
}
|
||||
|
||||
static jlongArray KernelCpuUidFreqTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) {
|
||||
auto freqs = android::bpf::getCpuFreqs();
|
||||
if (!freqs) return NULL;
|
||||
|
||||
std::vector<uint64_t> allFreqs;
|
||||
for (const auto &vec : *freqs) std::copy(vec.begin(), vec.end(), std::back_inserter(allFreqs));
|
||||
|
||||
auto ar = env->NewLongArray(allFreqs.size());
|
||||
if (ar != NULL) {
|
||||
env->SetLongArrayRegion(ar, 0, allFreqs.size(),
|
||||
reinterpret_cast<const jlong *>(allFreqs.data()));
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
|
||||
static const JNINativeMethod gFreqTimeMethods[] = {
|
||||
{"removeUidRange", "(II)Z", (void *)KernelCpuUidFreqTimeBpfMapReader_removeUidRange},
|
||||
{"readBpfData", "()Z", (void *)KernelCpuUidFreqTimeBpfMapReader_readBpfData},
|
||||
{"getDataDimensions", "()[J", (void *)KernelCpuUidFreqTimeBpfMapReader_getDataDimensions},
|
||||
};
|
||||
|
||||
static jboolean KernelCpuUidActiveTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
|
||||
@@ -186,10 +170,6 @@ static const readerMethods gAllMethods[] = {
|
||||
{"KernelCpuUidClusterTimeBpfMapReader", gClusterTimeMethods, NELEM(gClusterTimeMethods)},
|
||||
};
|
||||
|
||||
static jboolean KernelCpuUidBpfMapReader_startTrackingBpfTimes(JNIEnv *, jobject) {
|
||||
return android::bpf::startTrackingUidTimes();
|
||||
}
|
||||
|
||||
int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env) {
|
||||
gSparseArrayClassInfo.clazz = FindClassOrDie(env, "android/util/SparseArray");
|
||||
gSparseArrayClassInfo.clazz = MakeGlobalRefOrDie(env, gSparseArrayClassInfo.clazz);
|
||||
@@ -198,14 +178,10 @@ int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env) {
|
||||
gSparseArrayClassInfo.get =
|
||||
GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "get", "(I)Ljava/lang/Object;");
|
||||
constexpr auto readerName = "com/android/internal/os/KernelCpuUidBpfMapReader";
|
||||
constexpr JNINativeMethod method = {"startTrackingBpfTimes", "()Z",
|
||||
(void *)KernelCpuUidBpfMapReader_startTrackingBpfTimes};
|
||||
|
||||
int ret = RegisterMethodsOrDie(env, readerName, &method, 1);
|
||||
if (ret < 0) return ret;
|
||||
auto c = FindClassOrDie(env, readerName);
|
||||
gmData = GetFieldIDOrDie(env, c, "mData", "Landroid/util/SparseArray;");
|
||||
|
||||
int ret = 0;
|
||||
for (const auto &m : gAllMethods) {
|
||||
auto fullName = android::base::StringPrintf("%s$%s", readerName, m.name);
|
||||
ret = RegisterMethodsOrDie(env, fullName.c_str(), m.methods, m.numMethods);
|
||||
|
||||
@@ -1471,12 +1471,18 @@ public class StatsPullAtomService extends SystemService {
|
||||
}
|
||||
|
||||
int pullCpuTimePerClusterFreqLocked(int atomTag, List<StatsEvent> pulledData) {
|
||||
boolean success = KernelCpuTotalBpfMapReader.read((cluster, freq, timeMs) -> {
|
||||
pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
|
||||
});
|
||||
if (!success) {
|
||||
int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
|
||||
long[] freqs = KernelCpuBpfTracking.getFreqs();
|
||||
long[] timesMs = KernelCpuTotalBpfMapReader.read();
|
||||
if (timesMs == null) {
|
||||
return StatsManager.PULL_SKIP;
|
||||
}
|
||||
for (int freqIndex = 0; freqIndex < timesMs.length; ++freqIndex) {
|
||||
int cluster = freqsClusters[freqIndex];
|
||||
long freq = freqs[freqIndex];
|
||||
long timeMs = timesMs[freqIndex];
|
||||
pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
|
||||
}
|
||||
return StatsManager.PULL_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1503,48 +1509,42 @@ public class StatsPullAtomService extends SystemService {
|
||||
}
|
||||
|
||||
private void registerCpuCyclesPerUidCluster() {
|
||||
int tagId = FrameworkStatsLog.CPU_CYCLES_PER_UID_CLUSTER;
|
||||
PullAtomMetadata metadata = new PullAtomMetadata.Builder()
|
||||
.setAdditiveFields(new int[] {3, 4, 5})
|
||||
.build();
|
||||
mStatsManager.setPullAtomCallback(
|
||||
tagId,
|
||||
metadata,
|
||||
DIRECT_EXECUTOR,
|
||||
mStatsCallbackImpl
|
||||
);
|
||||
// If eBPF tracking is not support, the procfs fallback is used if the kernel knows about
|
||||
// CPU frequencies.
|
||||
if (KernelCpuBpfTracking.isSupported() || KernelCpuBpfTracking.getClusters() > 0) {
|
||||
int tagId = FrameworkStatsLog.CPU_CYCLES_PER_UID_CLUSTER;
|
||||
PullAtomMetadata metadata = new PullAtomMetadata.Builder()
|
||||
.setAdditiveFields(new int[] {3, 4, 5})
|
||||
.build();
|
||||
mStatsManager.setPullAtomCallback(
|
||||
tagId,
|
||||
metadata,
|
||||
DIRECT_EXECUTOR,
|
||||
mStatsCallbackImpl
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int pullCpuCyclesPerUidClusterLocked(int atomTag, List<StatsEvent> pulledData) {
|
||||
// TODO(b/179485697): Remove power profile dependency.
|
||||
PowerProfile powerProfile = new PowerProfile(mContext);
|
||||
// Frequency index to frequency mapping.
|
||||
long[] freqs = mCpuUidFreqTimeReader.readFreqs(powerProfile);
|
||||
// Frequency index to cluster mapping.
|
||||
int[] freqClusters = new int[freqs.length];
|
||||
// Frequency index to power mapping.
|
||||
double[] freqPowers = new double[freqs.length];
|
||||
// Number of clusters.
|
||||
int clusters;
|
||||
|
||||
// Initialize frequency mappings.
|
||||
int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
|
||||
int clusters = KernelCpuBpfTracking.getClusters();
|
||||
long[] freqs = KernelCpuBpfTracking.getFreqs();
|
||||
double[] freqsPowers = new double[freqs.length];
|
||||
// Initialize frequency power mapping.
|
||||
{
|
||||
int cluster = 0;
|
||||
int freqClusterIndex = 0;
|
||||
long lastFreq = -1;
|
||||
int lastCluster = -1;
|
||||
for (int freqIndex = 0; freqIndex < freqs.length; ++freqIndex, ++freqClusterIndex) {
|
||||
long currFreq = freqs[freqIndex];
|
||||
if (currFreq <= lastFreq) {
|
||||
cluster++;
|
||||
int cluster = freqsClusters[freqIndex];
|
||||
if (cluster != lastCluster) {
|
||||
freqClusterIndex = 0;
|
||||
}
|
||||
freqClusters[freqIndex] = cluster;
|
||||
freqPowers[freqIndex] =
|
||||
powerProfile.getAveragePowerForCpuCore(cluster, freqClusterIndex);
|
||||
lastFreq = currFreq;
|
||||
}
|
||||
lastCluster = cluster;
|
||||
|
||||
clusters = cluster + 1;
|
||||
freqsPowers[freqIndex] =
|
||||
powerProfile.getAveragePowerForCpuCore(cluster, freqClusterIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Aggregate 0: mcycles, 1: runtime ms, 2: power profile estimate for the same uids for
|
||||
@@ -1570,12 +1570,12 @@ public class StatsPullAtomService extends SystemService {
|
||||
}
|
||||
|
||||
for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
|
||||
int cluster = freqClusters[freqIndex];
|
||||
int cluster = freqsClusters[freqIndex];
|
||||
long timeMs = cpuFreqTimeMs[freqIndex];
|
||||
values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES] += freqs[freqIndex] * timeMs;
|
||||
values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 1] += timeMs;
|
||||
values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 2] +=
|
||||
freqPowers[freqIndex] * timeMs;
|
||||
freqsPowers[freqIndex] * timeMs;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1665,34 +1665,6 @@ public class StatsPullAtomService extends SystemService {
|
||||
}
|
||||
|
||||
int pullCpuCyclesPerThreadGroupCluster(int atomTag, List<StatsEvent> pulledData) {
|
||||
// TODO(b/179485697): Remove power profile dependency.
|
||||
PowerProfile powerProfile = new PowerProfile(mContext);
|
||||
// Frequency index to frequency mapping.
|
||||
long[] freqs = mCpuUidFreqTimeReader.readFreqs(powerProfile);
|
||||
if (freqs == null) {
|
||||
return StatsManager.PULL_SKIP;
|
||||
}
|
||||
// Frequency index to cluster mapping.
|
||||
int[] freqClusters = new int[freqs.length];
|
||||
// Number of clusters.
|
||||
int clusters;
|
||||
|
||||
// Initialize frequency mappings.
|
||||
{
|
||||
int cluster = 0;
|
||||
long lastFreq = -1;
|
||||
for (int freqIndex = 0; freqIndex < freqs.length; ++freqIndex) {
|
||||
long currFreq = freqs[freqIndex];
|
||||
if (currFreq <= lastFreq) {
|
||||
cluster++;
|
||||
}
|
||||
freqClusters[freqIndex] = cluster;
|
||||
lastFreq = currFreq;
|
||||
}
|
||||
|
||||
clusters = cluster + 1;
|
||||
}
|
||||
|
||||
SystemServiceCpuThreadTimes times = LocalServices.getService(BatteryStatsInternal.class)
|
||||
.getSystemServiceCpuThreadTimes();
|
||||
if (times == null) {
|
||||
@@ -1701,22 +1673,24 @@ public class StatsPullAtomService extends SystemService {
|
||||
|
||||
addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
|
||||
FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER,
|
||||
times.threadCpuTimesUs, clusters, freqs, freqClusters);
|
||||
times.threadCpuTimesUs);
|
||||
addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
|
||||
FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER_BINDER,
|
||||
times.binderThreadCpuTimesUs, clusters, freqs, freqClusters);
|
||||
times.binderThreadCpuTimesUs);
|
||||
|
||||
return StatsManager.PULL_SUCCESS;
|
||||
}
|
||||
|
||||
private static void addCpuCyclesPerThreadGroupClusterAtoms(
|
||||
int atomTag, List<StatsEvent> pulledData, int threadGroup, long[] cpuTimesUs,
|
||||
int clusters, long[] freqs, int[] freqClusters) {
|
||||
int atomTag, List<StatsEvent> pulledData, int threadGroup, long[] cpuTimesUs) {
|
||||
int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
|
||||
int clusters = KernelCpuBpfTracking.getClusters();
|
||||
long[] freqs = KernelCpuBpfTracking.getFreqs();
|
||||
long[] aggregatedCycles = new long[clusters];
|
||||
long[] aggregatedTimesUs = new long[clusters];
|
||||
for (int i = 0; i < cpuTimesUs.length; ++i) {
|
||||
aggregatedCycles[freqClusters[i]] += freqs[i] * cpuTimesUs[i] / 1_000;
|
||||
aggregatedTimesUs[freqClusters[i]] += cpuTimesUs[i];
|
||||
aggregatedCycles[freqsClusters[i]] += freqs[i] * cpuTimesUs[i] / 1_000;
|
||||
aggregatedTimesUs[freqsClusters[i]] += cpuTimesUs[i];
|
||||
}
|
||||
for (int cluster = 0; cluster < clusters; ++cluster) {
|
||||
pulledData.add(FrameworkStatsLog.buildStatsEvent(
|
||||
|
||||
Reference in New Issue
Block a user