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

Commit 23f89d34 authored by Sanna Catherine de Treville Wager's avatar Sanna Catherine de Treville Wager
Browse files

Write thread and data to separate files

Each file name starts with either "histogram" or
"outlier" and contains thread and hash (source
file location) information.

Test: dumpsys media.log

Change-Id: I4bbea8b5265ac539e6fb2ce16207e4f5c89d21d4
parent d0965172
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ void PerformanceAnalysis::processAndFlushTimeStampSeries() {
        return;
    }

    // mHists is empty if program just started
    // mHists is empty if thread/hash pair is sending data for the first time
    if (mHists.empty()) {
        mHists.emplace_front(static_cast<uint64_t>(mTimeStampSeries[0]),
                            std::map<int, int>());
@@ -130,10 +130,6 @@ void PerformanceAnalysis::logTsEntry(int64_t ts) {
    }
}

// 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.
// The function sets the mean to the starting value and sigma to 0, and updates
@@ -223,7 +219,6 @@ void PerformanceAnalysis::storeOutlierData(const std::vector<int64_t> &timestamp
    }
}


// FIXME: delete this temporary test code, recycled for various new functions
void PerformanceAnalysis::testFunction() {
    // produces values (4: 5000000), (13: 18000000)
@@ -241,7 +236,10 @@ void PerformanceAnalysis::testFunction() {
// TODO Make it return a std::string instead of modifying body --> is this still relevant?
// 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) const {
void PerformanceAnalysis::reportPerformance(String8 *body, int maxHeight) {
    // Add any new data
    processAndFlushTimeStampSeries();

    if (mHists.empty()) {
        ALOGD("reportPerformance: mHists is empty");
        return;
@@ -348,11 +346,18 @@ void PerformanceAnalysis::alertIfGlitch(const std::vector<int64_t> &samples) {
//------------------------------------------------------------------------------

// writes summary of performance into specified file descriptor
void dump(int fd, int indent, const PerformanceAnalysisMap &threadPerformanceAnalysis) {
void dump(int fd, int indent, PerformanceAnalysisMap &threadPerformanceAnalysis) {
    String8 body;
    const char* const kName = "/data/misc/audioserver/";
    for (auto & thread : threadPerformanceAnalysis) {
        for (auto & hash: thread.second) {
            hash.second.reportPerformance(&body);
            PerformanceAnalysis& curr = hash.second;
            curr.processAndFlushTimeStampSeries();
            // write performance data to console
            curr.reportPerformance(&body);
            // write to file
            writeToFile(curr.mOutlierData, curr.mHists, kName, false,
                        thread.first, hash.first);
        }
    }
    if (!body.isEmpty()) {
+27 −13
Original line number Diff line number Diff line
@@ -23,12 +23,12 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <sys/prctl.h>
#include <utility>
#include <media/nbaio/NBLog.h>
#include <media/nbaio/PerformanceAnalysis.h>
#include <media/nbaio/ReportPerformance.h>
// #include <utils/CallStack.h> // used to print callstack
#include <utils/Log.h>
#include <utils/String8.h>

@@ -40,34 +40,48 @@ namespace ReportPerformance {
// TODO: format the data efficiently and write different types of data to different files
void writeToFile(const std::deque<std::pair<outlierInterval, timestamp>> &outlierData,
                                    const std::deque<std::pair<timestamp, Histogram>> &hists,
                                    const char * kName,
                                    bool append) {
    ALOGD("writing performance data to file");
                                    const char * kDirectory,
                                    bool append, int author, log_hash_t hash) {
    if (outlierData.empty() || hists.empty()) {
        ALOGW("No data, returning.");
        return;
    }

    std::stringstream outlierName;
    std::stringstream histogramName;

    outlierName << kDirectory << "outliers_" << author << "_" << hash;
    histogramName << kDirectory << "histograms_" << author << "_" << hash;

    std::ofstream ofs;
    ofs.open(kName, append ? std::ios::app : std::ios::trunc);
    ofs.open(outlierName.str().c_str(), append ? std::ios::app : std::ios::trunc);
    if (!ofs.is_open()) {
        ALOGW("couldn't open file %s", kName);
        ALOGW("couldn't open file %s", outlierName.str().c_str());
        return;
    }
    ofs << "Outlier data: interval and timestamp\n";
    for (const auto &outlier : outlierData) {
        ofs << outlier.first << ": " << outlier.second << "\n";
    }
    ofs << "Histogram data\n";
    ofs.close();

    std::ofstream hfs;
    hfs.open(histogramName.str().c_str(), append ? std::ios::app : std::ios::trunc);
    if (!hfs.is_open()) {
        ALOGW("couldn't open file %s", histogramName.str().c_str());
        return;
    }
    hfs << "Histogram data\n";
    for (const auto &hist : hists) {
        ofs << "\ttimestamp\n";
        ofs << hist.first << "\n";
        ofs << "\tbuckets and counts\n";
        hfs << "\ttimestamp\n";
        hfs << hist.first << "\n";
        hfs << "\tbuckets and counts\n";
        for (const auto &bucket : hist.second) {
            ofs << bucket.first << ": " << bucket.second << "\n";
            hfs << bucket.first << ": " << bucket.second << "\n";
        }
        ofs << "\n"; // separate histograms with a newline
        hfs << "\n"; // separate histograms with a newline
    }
    ofs.close();
    hfs.close();
}

} // namespace ReportPerformance
+11 −12
Original line number Diff line number Diff line
@@ -29,6 +29,12 @@ namespace android {

namespace ReportPerformance {

class PerformanceAnalysis;

// a map of PerformanceAnalysis instances
// The outer key is for the thread, the inner key for the source file location.
using PerformanceAnalysisMap = std::map<int, std::map<log_hash_t, PerformanceAnalysis>>;

class PerformanceAnalysis {
    // This class stores and analyzes audio processing wakeup timestamps from NBLog
    // FIXME: currently, all performance data is stored in deques. Need to add a mutex.
@@ -38,15 +44,13 @@ public:

    PerformanceAnalysis();

    // Given a series of audio processing wakeup timestamps,
    // compresses and and analyzes the data, and flushes
    // the timestamp series from memory.
    void processAndFlushTimeStampSeries();
    friend void dump(int fd, int indent,
                     PerformanceAnalysisMap &threadPerformanceAnalysis);

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

    // Called when an audio on/off event is read from the buffer,
    // e.g. EVENT_AUDIO_STATE.
@@ -73,7 +77,7 @@ public:
    // input: series of short histograms. Generates a string of analysis of the buffer periods
    // TODO: WIP write more detailed analysis
    // FIXME: move this data visualization to a separate class. Model/view/controller
    void reportPerformance(String8 *body, int maxHeight = 10) const;
    void reportPerformance(String8 *body, int maxHeight = 10);

    // TODO: delete this. temp for testing
    void testFunction();
@@ -134,12 +138,7 @@ private:

};

// a map of PerformanceAnalysis instances
// The outer key is for the thread, the inner key for the source file location.
using PerformanceAnalysisMap = std::map<int, std::map<log_hash_t, PerformanceAnalysis>>;

void dump(int fd, int indent, const PerformanceAnalysisMap &threadPerformanceAnalysis);

void dump(int fd, int indent, PerformanceAnalysisMap &threadPerformanceAnalysis);
void dumpLine(int fd, int indent, const String8 &body);

} // namespace ReportPerformance
+1 −2
Original line number Diff line number Diff line
@@ -58,8 +58,7 @@ static inline uint32_t log2(uint32_t x) {
// intervals to a file.
void writeToFile(const std::deque<std::pair<outlierInterval, timestamp>> &outlierData,
                 const std::deque<std::pair<timestamp, Histogram>> &hists,
                 const char * kName,
                 bool append);
                 const char * kName, bool append, int author, log_hash_t hash);

} // namespace ReportPerformance