Develop histogram logging
Add date to WriteToFile filenames and simplify
file format. Add timestamp logging to
NormalMixer. Change histogram resolution
dynamically based on logarithmic distance
from the distribution center. Add context
information: thread, hash and time.
Example of right end of a histogram with
rounding for values >= 27:
1 1 2 1 1 1 2 2 1
| | |
| | | | | | | | |
_____________________________________________
21.1 21.2 22.9 23.0 23.3 27.0 34.0 37.0 38.0 ms
Test: dumpsys media.log
Change-Id: I255e2d28d76a1c7a06d48e7c3eacdf2f846a7ea3
diff --git a/media/libnbaio/ReportPerformance.cpp b/media/libnbaio/ReportPerformance.cpp
index 813df94..e64a6d3 100644
--- a/media/libnbaio/ReportPerformance.cpp
+++ b/media/libnbaio/ReportPerformance.cpp
@@ -25,6 +25,7 @@
#include <string.h>
#include <sstream>
#include <sys/prctl.h>
+#include <sys/time.h>
#include <utility>
#include <media/nbaio/NBLog.h>
#include <media/nbaio/PerformanceAnalysis.h>
@@ -36,13 +37,16 @@
namespace ReportPerformance {
-// Writes outlier intervals, timestamps, and histograms spanning long time intervals to a file.
-// TODO: format the data efficiently and write different types of data to different files
+// Writes outlier intervals, timestamps, and histograms spanning long time intervals to file.
+// TODO: write data in binary format
void writeToFile(const std::deque<std::pair<timestamp, Histogram>> &hists,
const std::deque<std::pair<msInterval, timestamp>> &outlierData,
const std::deque<timestamp> &peakTimestamps,
const char * directory, bool append, int author, log_hash_t hash) {
- if (outlierData.empty() || hists.empty()) {
+
+ // TODO: remove old files, implement rotating files as in AudioFlinger.cpp
+
+ if (outlierData.empty() && hists.empty() && peakTimestamps.empty()) {
ALOGW("No data, returning.");
return;
}
@@ -51,9 +55,21 @@
std::stringstream histogramName;
std::stringstream peakName;
- histogramName << directory << "histograms_" << author << "_" << hash;
- outlierName << directory << "outliers_" << author << "_" << hash;
- peakName << directory << "peaks_" << author << "_" << hash;
+ // get current time
+ char currTime[16]; //YYYYMMDDHHMMSS + '\0' + one unused
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ struct tm tm;
+ localtime_r(&tv.tv_sec, &tm);
+ strftime(currTime, sizeof(currTime), "%Y%m%d%H%M%S", &tm);
+
+ // generate file names
+ std::stringstream common;
+ common << author << "_" << hash << "_" << currTime << ".csv";
+
+ histogramName << directory << "histograms_" << common.str();
+ outlierName << directory << "outliers_" << common.str();
+ peakName << directory << "peaks_" << common.str();
std::ofstream hfs;
hfs.open(histogramName.str(), append ? std::ios::app : std::ios::trunc);
@@ -61,16 +77,16 @@
ALOGW("couldn't open file %s", histogramName.str().c_str());
return;
}
- hfs << "Histogram data\n";
+ // each histogram is written as a line where the first value is the timestamp and
+ // subsequent values are pairs of buckets and counts. Each value is separated
+ // by a comma, and each histogram is separated by a newline.
for (const auto &hist : hists) {
- hfs << "\ttimestamp\n";
- hfs << hist.first << "\n";
- hfs << "\tbuckets (in ms) and counts\n";
+ hfs << hist.first << ", ";
for (const auto &bucket : hist.second) {
hfs << bucket.first / static_cast<double>(kJiffyPerMs)
- << ": " << bucket.second << "\n";
+ << ", " << bucket.second << ", ";
}
- hfs << "\n"; // separate histograms with a newline
+ hfs << "\n";
}
hfs.close();
@@ -80,9 +96,10 @@
ALOGW("couldn't open file %s", outlierName.str().c_str());
return;
}
- ofs << "Outlier data: interval and timestamp\n";
+ // outliers are written as pairs separated by newlines, where each
+ // pair's values are separated by a comma
for (const auto &outlier : outlierData) {
- ofs << outlier.first << ": " << outlier.second << "\n";
+ ofs << outlier.first << ", " << outlier.second << "\n";
}
ofs.close();
@@ -92,9 +109,9 @@
ALOGW("couldn't open file %s", peakName.str().c_str());
return;
}
- pfs << "Peak data: timestamp\n";
+ // peaks are simply timestamps separated by commas
for (const auto &peak : peakTimestamps) {
- pfs << peak << "\n";
+ pfs << peak << ", ";
}
pfs.close();
}