From 0a14c4ce1a41bc09eb7855fa531a3af629a69139 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Wed, 13 Jun 2012 14:58:49 -0700 Subject: Make CPU frequency statistics optional Certain CPUs with dynamic cluster swapping and hotplug don't report CPU frequency accurately. The file descriptors used to read the frequency become stale and report bogus data. So make this feature a build time option for debugging only. This will also improve performance of the fast mixer loop. Change-Id: I602f81ec3281a37992769208be08084ed1469e8c --- services/audioflinger/Android.mk | 3 +++ services/audioflinger/FastMixer.cpp | 23 +++++++++++++++++++---- services/audioflinger/FastMixer.h | 2 ++ 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'services') diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index f32d90f..8473fab 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -84,6 +84,9 @@ LOCAL_SRC_FILES += FastMixer.cpp FastMixerState.cpp LOCAL_CFLAGS += -DFAST_MIXER_STATISTICS +# uncomment to display CPU load adjusted for CPU frequency +# LOCAL_CFLAGS += -DCPU_FREQUENCY_STATISTICS + LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"' LOCAL_CFLAGS += -DHAVE_REQUEST_PRIORITY -UFAST_TRACKS_AT_NON_NATIVE_SAMPLE_RATE -USOAKER diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp index 3fe50dc..19ee9b3 100644 --- a/services/audioflinger/FastMixer.cpp +++ b/services/audioflinger/FastMixer.cpp @@ -24,8 +24,10 @@ #include #ifdef FAST_MIXER_STATISTICS #include +#ifdef CPU_FREQUENCY_STATISTICS #include #endif +#endif #include "AudioMixer.h" #include "FastMixer.h" @@ -71,8 +73,10 @@ bool FastMixer::threadLoop() bool oldLoadValid = false; // whether oldLoad is valid uint32_t bounds = 0; bool full = false; // whether we have collected at least kSamplingN samples +#ifdef CPU_FREQUENCY_STATISTICS ThreadCpuUsage tcu; // for reading the current CPU clock frequency in kHz #endif +#endif unsigned coldGen = 0; // last observed mColdGen bool isWarm = false; // true means ready to mix, false means wait for warmup before mixing struct timespec measuredWarmupTs = {0, 0}; // how long did it take for warmup to complete @@ -527,16 +531,20 @@ bool FastMixer::threadLoop() } oldLoad = newLoad; } +#ifdef CPU_FREQUENCY_STATISTICS // get the absolute value of CPU clock frequency in kHz int cpuNum = sched_getcpu(); uint32_t kHz = tcu.getCpukHz(cpuNum); kHz = (kHz << 4) | (cpuNum & 0xF); +#endif // save values in FIFO queues for dumpsys // these stores #1, #2, #3 are not atomic with respect to each other, // or with respect to store #4 below dumpState->mMonotonicNs[i] = monotonicNs; dumpState->mLoadNs[i] = loadNs; +#ifdef CPU_FREQUENCY_STATISTICS dumpState->mCpukHz[i] = kHz; +#endif // this store #4 is not atomic with respect to stores #1, #2, #3 above, but // the newest open and oldest closed halves are atomic with respect to each other dumpState->mBounds = bounds; @@ -579,7 +587,9 @@ FastMixerDumpState::FastMixerDumpState() : // so clearing reduces chance for dumpsys to read random uninitialized samples memset(&mMonotonicNs, 0, sizeof(mMonotonicNs)); memset(&mLoadNs, 0, sizeof(mLoadNs)); +#ifdef CPU_FREQUENCY_STATISTICS memset(&mCpukHz, 0, sizeof(mCpukHz)); +#endif } FastMixerDumpState::~FastMixerDumpState() @@ -643,18 +653,20 @@ void FastMixerDumpState::dump(int fd) } // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency, // and adjusted CPU load in MHz normalized for CPU clock frequency - CentralTendencyStatistics wall, loadNs, kHz, loadMHz; - // only compute adjusted CPU load in Hz if current CPU number and CPU clock frequency are stable - bool valid = false; + CentralTendencyStatistics wall, loadNs; +#ifdef CPU_FREQUENCY_STATISTICS + CentralTendencyStatistics kHz, loadMHz; uint32_t previousCpukHz = 0; +#endif // loop over all the samples for (; n > 0; --n) { size_t i = oldestClosed++ & (kSamplingN - 1); uint32_t wallNs = mMonotonicNs[i]; wall.sample(wallNs); uint32_t sampleLoadNs = mLoadNs[i]; - uint32_t sampleCpukHz = mCpukHz[i]; loadNs.sample(sampleLoadNs); +#ifdef CPU_FREQUENCY_STATISTICS + uint32_t sampleCpukHz = mCpukHz[i]; // skip bad kHz samples if ((sampleCpukHz & ~0xF) != 0) { kHz.sample(sampleCpukHz >> 4); @@ -665,6 +677,7 @@ void FastMixerDumpState::dump(int fd) } } previousCpukHz = sampleCpukHz; +#endif } fdprintf(fd, "Simple moving statistics over last %.1f seconds:\n", wall.n() * mixPeriodSec); fdprintf(fd, " wall clock time in ms per mix cycle:\n" @@ -674,6 +687,7 @@ void FastMixerDumpState::dump(int fd) " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", loadNs.mean()*1e-3, loadNs.minimum()*1e-3, loadNs.maximum()*1e-3, loadNs.stddev()*1e-3); +#ifdef CPU_FREQUENCY_STATISTICS fdprintf(fd, " CPU clock frequency in MHz:\n" " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n", kHz.mean()*1e-3, kHz.minimum()*1e-3, kHz.maximum()*1e-3, kHz.stddev()*1e-3); @@ -681,6 +695,7 @@ void FastMixerDumpState::dump(int fd) " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n", loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev()); #endif +#endif // The active track mask and track states are updated non-atomically. // So if we relied on isActive to decide whether to display, // then we might display an obsolete track or omit an active track. diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h index 06e76d5..462739b 100644 --- a/services/audioflinger/FastMixer.h +++ b/services/audioflinger/FastMixer.h @@ -116,8 +116,10 @@ struct FastMixerDumpState { // The elements in the *Ns arrays are in units of nanoseconds <= 3999999999. uint32_t mMonotonicNs[kSamplingN]; // delta monotonic (wall clock) time uint32_t mLoadNs[kSamplingN]; // delta CPU load in time +#ifdef CPU_FREQUENCY_STATISTICS uint32_t mCpukHz[kSamplingN]; // absolute CPU clock frequency in kHz, bits 0-3 are CPU# #endif +#endif }; } // namespace android -- cgit v1.1