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

Commit 0a14c4ce authored by Glenn Kasten's avatar Glenn Kasten
Browse files

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
parent 362ebcbf
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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
+19 −4
Original line number Diff line number Diff line
@@ -24,8 +24,10 @@
#include <system/audio.h>
#ifdef FAST_MIXER_STATISTICS
#include <cpustats/CentralTendencyStatistics.h>
#ifdef CPU_FREQUENCY_STATISTICS
#include <cpustats/ThreadCpuUsage.h>
#endif
#endif
#include "AudioMixer.h"
#include "FastMixer.h"

@@ -71,7 +73,9 @@ 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
@@ -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,12 +687,14 @@ 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);
    fdprintf(fd, "  adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
                 "    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,
+2 −0
Original line number Diff line number Diff line
@@ -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