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

Commit f7843fa9 authored by Sanna Catherine de Treville Wager's avatar Sanna Catherine de Treville Wager Committed by Android (Google) Code Review
Browse files

Merge "Simplify processAndFlushTimeStampSeries"

parents 47522cfb a80649ad
Loading
Loading
Loading
Loading
+36 −59
Original line number Diff line number Diff line
@@ -54,16 +54,6 @@ PerformanceAnalysis::PerformanceAnalysis() {
    kPeriodMsCPU = static_cast<int>(kPeriodMs * kRatio);
}

// converts a time series into a map. key: buffer period length. value: count
static std::map<int, int> buildBuckets(const std::vector<int64_t> &samples) {
    // TODO allow buckets of variable resolution
    std::map<int, int> buckets;
    for (size_t i = 1; i < samples.size(); ++i) {
        ++buckets[deltaMs(samples[i - 1], samples[i])];
    }
    return buckets;
}

static int widthOf(int x) {
    int width = 0;
    while (x > 0) {
@@ -79,21 +69,41 @@ static int widthOf(int x) {
// small or large values and stores these as peaks, and flushes
// the timestamp series from memory.
void PerformanceAnalysis::processAndFlushTimeStampSeries() {
    if (mTimeStampSeries.empty()) {
        ALOGD("Timestamp series is empty");
        return;
    }

    // mHists is empty if program just started
    if (mHists.empty()) {
        mHists.emplace_front(static_cast<uint64_t>(mTimeStampSeries[0]),
                            std::map<int, int>());
    }

    // 1) analyze the series to store all outliers and their exact timestamps:
    storeOutlierData(mTimeStampSeries);

    // 2) detect peaks in the outlier series
    detectPeaks();

    // 3) compute its histogram, append to mRecentHists and clear the time series
    mRecentHists.emplace_back(static_cast<timestamp>(mTimeStampSeries[0]),
                              buildBuckets(mTimeStampSeries));
    // do not let mRecentHists exceed capacity
    // ALOGD("mRecentHists size: %d", static_cast<int>(mRecentHists.size()));
    if (mRecentHists.size() >= kRecentHistsCapacity) {
        //  ALOGD("popped back mRecentHists");
        mRecentHists.pop_front();
    // if the current histogram has spanned its maximum time interval,
    // insert a new empty histogram to the front of mHists
    if (deltaMs(mHists[0].first, mTimeStampSeries[0]) >= kMaxHistTimespanMs) {
        mHists.emplace_front(static_cast<uint64_t>(mTimeStampSeries[0]),
                             std::map<int, int>());
        // When memory is full, delete oldest histogram
        if (mHists.size() >= kHistsCapacity) {
            mHists.resize(kHistsCapacity);
        }
    }

    // 3) add current time intervals to histogram
    for (size_t i = 1; i < mTimeStampSeries.size(); ++i) {
        ++mHists[0].second[deltaMs(
                mTimeStampSeries[i - 1], mTimeStampSeries[i])];
    }

    // clear the timestamps
    mTimeStampSeries.clear();
}

@@ -116,48 +126,14 @@ void PerformanceAnalysis::logTsEntry(int64_t ts) {
    mTimeStampSeries.push_back(ts);
    // if length of the time series has reached kShortHistSize samples,
    // analyze the data and flush the timestamp series from memory
    if (mTimeStampSeries.size() >= kShortHistSize) {
    if (mTimeStampSeries.size() >= kHistSize) {
        processAndFlushTimeStampSeries();
    }
}

// When the short-term histogram array mRecentHists has reached capacity,
// merge histograms for data compression and store them in mLongTermHists
// clears mRecentHists
// TODO: have logTsEntry write directly to mLongTermHists, discard mRecentHists,
// start a new histogram when a peak occurs
void PerformanceAnalysis::processAndFlushRecentHists() {

    // Buckets is used to aggregate short-term histograms.
    Histogram buckets;
    timestamp startingTs = mRecentHists[0].first;

    for (const auto &shortHist: mRecentHists) {
        // If the time between starting and ending timestamps has reached the maximum,
        // add the current histogram (buckets) to the long-term histogram buffer,
        // clear buckets, and start a new long-term histogram aggregation process.
        if (deltaMs(startingTs, shortHist.first) >= kMaxHistTimespanMs) {
            mLongTermHists.emplace_back(startingTs, std::move(buckets));
            buckets.clear();
            startingTs = shortHist.first;
            // When memory is full, delete oldest histogram
            // TODO use a circular buffer
            if (mLongTermHists.size() >= kLongTermHistsCapacity) {
                mLongTermHists.pop_front();
            }
        }

        // add current histogram to buckets
        for (const auto &countPair : shortHist.second) {
            buckets[countPair.first] += countPair.second;
        }
    }
    mRecentHists.clear();
    // TODO: decide when/where to call writeToFile
    // TODO: add a thread-specific extension to the file name
    static const char* const kName = (const char *) "/data/misc/audioserver/sample_results.txt";
    writeToFile(mOutlierData, mLongTermHists, kName, false);
}
// TODO: move this someplace
// static const char* const kName = (const char *) "/data/misc/audioserver/sample_results.txt";
//    writeToFile(mOutlierData, mLongTermHists, kName, false);

// Given a series of outlier intervals (mOutlier data),
// looks for changes in distribution (peaks), which can be either positive or negative.
@@ -267,13 +243,14 @@ void PerformanceAnalysis::testFunction() {
// TODO consider changing all ints to uint32_t or uint64_t
// TODO: move this to ReportPerformance, probably make it a friend function of PerformanceAnalysis
void PerformanceAnalysis::reportPerformance(String8 *body, int maxHeight) {
    if (mRecentHists.size() < 1) {
        ALOGD("reportPerformance: mRecentHists is empty");
    if (mHists.empty()) {
        ALOGD("reportPerformance: mHists is empty");
        return;
    }
    ALOGD("reportPerformance: hists size %d", static_cast<int>(mHists.size()));
    // TODO: more elaborate data analysis
    std::map<int, int> buckets;
    for (const auto &shortHist: mRecentHists) {
    for (const auto &shortHist: mHists) {
        for (const auto &countPair : shortHist.second) {
            buckets[countPair.first] += countPair.second;
        }
+12 −17
Original line number Diff line number Diff line
@@ -43,16 +43,17 @@ public:
    // the timestamp series from memory.
    void processAndFlushTimeStampSeries();

    // Given a series of audio processing wakeup timestamps,
    // compresses and and analyzes the data, and flushes
    // the timestamp series from memory.
    void processAndFlushTimeStampSeriesOld();

    // Called when an audio on/off event is read from the buffer,
    // e.g. EVENT_AUDIO_STATE.
    // calls flushTimeStampSeries on the data up to the event,
    // effectively discarding the idle audio time interval
    void handleStateChange();

    // When the short-term histogram array mRecentHists has reached capacity,
    // merges histograms for data compression and stores them in mLongTermHists
    void processAndFlushRecentHists();

    // Writes wakeup timestamp entry to log and runs analysis
    // TODO: make this thread safe. Each thread should have its own instance
    // of PerformanceAnalysis.
@@ -90,16 +91,11 @@ private:
    // a peak is a moment at which the average outlier interval changed significantly
    std::deque<timestamp> mPeakTimestamps;

    // TODO: turn these into circular buffers for better data flow
    // FIFO of small histograms
    // stores fixed-size short buffer period histograms with timestamp of first sample
    std::deque<std::pair<timestamp, Histogram>> mRecentHists;

    // FIFO of small histograms
    // stores fixed-size long-term buffer period histograms with timestamp of first sample
    std::deque<std::pair<timestamp, Histogram>> mLongTermHists;
    // stores stores buffer period histograms with timestamp of first sample
    // TODO use a circular buffer
    std::deque<std::pair<timestamp, Histogram>> mHists;

    // vector of timestamps, collected from NBLog for a (TODO) specific thread
    // vector of timestamps, collected from NBLog for a specific thread
    // when a vector reaches its maximum size, the data is processed and flushed
    std::vector<timestamp_raw> mTimeStampSeries;

@@ -119,12 +115,11 @@ private:
    static const int kStddevThreshold = 5;

    // capacity allocated to data structures
    // TODO: adjust all of these values
    static const int kRecentHistsCapacity = 100; // number of short-term histograms stored in memory
    static const int kShortHistSize = 50; // number of samples in a short-term histogram
    // TODO: make these values longer when testing is finished
    static const int kHistsCapacity = 20; // number of short-term histograms stored in memory
    static const int kHistSize = 1000; // max number of samples stored in a histogram
    static const int kOutlierSeriesSize = 100; // number of values stored in outlier array
    static const int kPeakSeriesSize = 100; // number of values stored in peak array
    static const int kLongTermHistsCapacity = 20; // number of long-term histogram stored in memory
    // maximum elapsed time between first and last timestamp of a long-term histogram
    static const int kMaxHistTimespanMs = 5 * kMsPerSec;