blob: 4e446a437726cac6928f663bf45deb59ada48265 [file] [log] [blame]
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18#define LOG_TAG "PerformanceAnalysis"
19// #define LOG_NDEBUG 0
20
21#include <algorithm>
22#include <climits>
23#include <deque>
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -070024#include <iostream>
25#include <math.h>
26#include <numeric>
27#include <vector>
28#include <stdarg.h>
29#include <stdint.h>
30#include <stdio.h>
31#include <string.h>
32#include <sys/prctl.h>
33#include <time.h>
34#include <new>
35#include <audio_utils/roundup.h>
36#include <media/nbaio/NBLog.h>
37#include <media/nbaio/PerformanceAnalysis.h>
Sanna Catherine de Treville Wager80448082017-07-11 14:07:59 -070038#include <media/nbaio/ReportPerformance.h>
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -070039#include <utils/Log.h>
40#include <utils/String8.h>
41
42#include <queue>
43#include <utility>
44
45namespace android {
46
Sanna Catherine de Treville Wager80448082017-07-11 14:07:59 -070047namespace ReportPerformance {
48
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -070049// Given a the most recent timestamp of a series of audio processing
50// wakeup timestamps,
51// buckets the time interval into a histogram, searches for
Sanna Catherine de Treville Wagera8a8a472017-07-11 09:41:25 -070052// outliers, analyzes the outlier series for unexpectedly
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -070053// small or large values and stores these as peaks
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -070054void PerformanceAnalysis::logTsEntry(timestamp ts) {
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -070055 // after a state change, start a new series and do not
56 // record time intervals in-between
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -070057 if (mBufferPeriod.mPrevTs == 0) {
58 mBufferPeriod.mPrevTs = ts;
Sanna Catherine de Treville Wagera80649a2017-07-21 16:16:38 -070059 return;
60 }
61
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -070062 // calculate time interval between current and previous timestamp
63 const msInterval diffMs = static_cast<msInterval>(
64 deltaMs(mBufferPeriod.mPrevTs, ts));
65
66 const int diffJiffy = deltaJiffy(mBufferPeriod.mPrevTs, ts);
67
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -070068 // old versus new weight ratio when updating the buffer period mean
69 static constexpr double exponentialWeight = 0.999;
70 // update buffer period mean with exponential weighting
71 mBufferPeriod.mMean = (mBufferPeriod.mMean < 0) ? diffMs :
72 exponentialWeight * mBufferPeriod.mMean + (1.0 - exponentialWeight) * diffMs;
73 // set mOutlierFactor to a smaller value for the fastmixer thread
74 const int kFastMixerMax = 10;
75 // NormalMixer times vary much more than FastMixer times.
76 // TODO: mOutlierFactor values are set empirically based on what appears to be
77 // an outlier. Learn these values from the data.
Sanna Catherine de Treville Wager847b6e62017-08-03 11:35:51 -070078 // TODO: the current settings are too high, change after next data collection is over
79 mBufferPeriod.mOutlierFactor = mBufferPeriod.mMean < kFastMixerMax ? 1.8 : 2.0;
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -070080 // set outlier threshold
81 mBufferPeriod.mOutlier = mBufferPeriod.mMean * mBufferPeriod.mOutlierFactor;
82
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -070083 // Check whether the time interval between the current timestamp
84 // and the previous one is long enough to count as an outlier
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -070085 const bool isOutlier = detectAndStoreOutlier(diffMs);
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -070086 // If an outlier was found, check whether it was a peak
87 if (isOutlier) {
88 /*bool isPeak =*/ detectAndStorePeak(
89 mOutlierData[0].first, mOutlierData[0].second);
90 // TODO: decide whether to insert a new empty histogram if a peak
91 // TODO: remove isPeak if unused to avoid "unused variable" error
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -070092 // occurred at the current timestamp
Sanna Catherine de Treville Wagera80649a2017-07-21 16:16:38 -070093 }
94
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -070095 // Insert a histogram to mHists if it is empty, or
96 // close the current histogram and insert a new empty one if
97 // if the current histogram has spanned its maximum time interval.
98 if (mHists.empty() ||
99 deltaMs(mHists[0].first, ts) >= kMaxLength.HistTimespanMs) {
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700100 mHists.emplace_front(ts, std::map<int, int>());
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -0700101 // When memory is full, delete oldest histogram
102 // TODO: use a circular buffer
103 if (mHists.size() >= kMaxLength.Hists) {
104 mHists.resize(kMaxLength.Hists);
105 }
106 }
107 // add current time intervals to histogram
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700108 ++mHists[0].second[diffJiffy];
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -0700109 // update previous timestamp
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700110 mBufferPeriod.mPrevTs = ts;
Sanna Catherine de Treville Wagera8a8a472017-07-11 09:41:25 -0700111}
112
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -0700113
Sanna Catherine de Treville Wagera8a8a472017-07-11 09:41:25 -0700114// forces short-term histogram storage to avoid adding idle audio time interval
115// to buffer period data
Sanna Catherine de Treville Wager80448082017-07-11 14:07:59 -0700116void PerformanceAnalysis::handleStateChange() {
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700117 mBufferPeriod.mPrevTs = 0;
Sanna Catherine de Treville Wagera8a8a472017-07-11 09:41:25 -0700118 return;
119}
120
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700121
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700122// Checks whether the time interval between two outliers is far enough from
123// a typical delta to be considered a peak.
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700124// looks for changes in distribution (peaks), which can be either positive or negative.
125// The function sets the mean to the starting value and sigma to 0, and updates
126// them as long as no peak is detected. When a value is more than 'threshold'
127// standard deviations from the mean, a peak is detected and the mean and sigma
128// are set to the peak value and 0.
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700129bool PerformanceAnalysis::detectAndStorePeak(msInterval diff, timestamp ts) {
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700130 bool isPeak = false;
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700131 if (mOutlierData.empty()) {
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700132 return false;
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700133 }
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700134 // Update mean of the distribution
135 // TypicalDiff is used to check whether a value is unusually large
136 // when we cannot use standard deviations from the mean because the sd is set to 0.
137 mOutlierDistribution.mTypicalDiff = (mOutlierDistribution.mTypicalDiff *
138 (mOutlierData.size() - 1) + diff) / mOutlierData.size();
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700139
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700140 // Initialize short-term mean at start of program
141 if (mOutlierDistribution.mMean == 0) {
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700142 mOutlierDistribution.mMean = diff;
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700143 }
144 // Update length of current sequence of outliers
145 mOutlierDistribution.mN++;
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700146
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700147 // Check whether a large deviation from the mean occurred.
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700148 // If the standard deviation has been reset to zero, the comparison is
149 // instead to the mean of the full mOutlierInterval sequence.
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700150 if ((fabs(diff - mOutlierDistribution.mMean) <
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700151 mOutlierDistribution.kMaxDeviation * mOutlierDistribution.mSd) ||
152 (mOutlierDistribution.mSd == 0 &&
153 fabs(diff - mOutlierDistribution.mMean) <
154 mOutlierDistribution.mTypicalDiff)) {
155 // update the mean and sd using online algorithm
156 // https://en.wikipedia.org/wiki/
157 // Algorithms_for_calculating_variance#Online_algorithm
158 mOutlierDistribution.mN++;
159 const double kDelta = diff - mOutlierDistribution.mMean;
160 mOutlierDistribution.mMean += kDelta / mOutlierDistribution.mN;
161 const double kDelta2 = diff - mOutlierDistribution.mMean;
162 mOutlierDistribution.mM2 += kDelta * kDelta2;
163 mOutlierDistribution.mSd = (mOutlierDistribution.mN < 2) ? 0 :
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -0700164 sqrt(mOutlierDistribution.mM2 / (mOutlierDistribution.mN - 1));
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700165 } else {
166 // new value is far from the mean:
167 // store peak timestamp and reset mean, sd, and short-term sequence
168 isPeak = true;
169 mPeakTimestamps.emplace_front(ts);
170 // if mPeaks has reached capacity, delete oldest data
171 // Note: this means that mOutlierDistribution values do not exactly
172 // match the data we have in mPeakTimestamps, but this is not an issue
173 // in practice for estimating future peaks.
174 // TODO: turn this into a circular buffer
175 if (mPeakTimestamps.size() >= kMaxLength.Peaks) {
176 mPeakTimestamps.resize(kMaxLength.Peaks);
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700177 }
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700178 mOutlierDistribution.mMean = 0;
179 mOutlierDistribution.mSd = 0;
180 mOutlierDistribution.mN = 0;
181 mOutlierDistribution.mM2 = 0;
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700182 }
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700183 return isPeak;
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700184}
185
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -0700186
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700187// Determines whether the difference between a timestamp and the previous
188// one is beyond a threshold. If yes, stores the timestamp as an outlier
189// and writes to mOutlierdata in the following format:
190// Time elapsed since previous outlier: Timestamp of start of outlier
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700191// e.g. timestamps (ms) 1, 4, 5, 16, 18, 28 will produce pairs (4, 5), (13, 18).
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700192// TODO: learn what timestamp sequences correlate with glitches instead of
193// manually designing a heuristic.
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700194bool PerformanceAnalysis::detectAndStoreOutlier(const msInterval diffMs) {
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700195 bool isOutlier = false;
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700196 if (diffMs >= mBufferPeriod.mOutlier) {
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700197 isOutlier = true;
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700198 mOutlierData.emplace_front(
199 mOutlierDistribution.mElapsed, mBufferPeriod.mPrevTs);
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700200 // Remove oldest value if the vector is full
201 // TODO: turn this into a circular buffer
202 // TODO: make sure kShortHistSize is large enough that that data will never be lost
203 // before being written to file or to a FIFO
204 if (mOutlierData.size() >= kMaxLength.Outliers) {
205 mOutlierData.resize(kMaxLength.Outliers);
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700206 }
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700207 mOutlierDistribution.mElapsed = 0;
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700208 }
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700209 mOutlierDistribution.mElapsed += diffMs;
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700210 return isOutlier;
Sanna Catherine de Treville Wager41cad592017-06-29 14:57:59 -0700211}
212
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700213static int widthOf(int x) {
214 int width = 0;
215 if (x < 0) {
216 width++;
217 x = x == INT_MIN ? INT_MAX : -x;
218 }
219 // assert (x >= 0)
220 do {
221 ++width;
222 x /= 10;
223 } while (x > 0);
224 return width;
225}
226
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700227// computes the column width required for a specific histogram value
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700228inline int numberWidth(double number, int leftPadding) {
229 // Added values account for whitespaces needed around numbers, and for the
230 // dot and decimal digit not accounted for by widthOf
231 return std::max(std::max(widthOf(static_cast<int>(number)) + 3, 2), leftPadding + 1);
232}
233
234// rounds value to precision based on log-distance from mean
235inline double logRound(double x, double mean) {
Sanna Catherine de Treville Wager847b6e62017-08-03 11:35:51 -0700236 // Larger values decrease range of high resolution and prevent overflow
237 // of a histogram on the console.
238 // The following formula adjusts kBase based on the buffer period length.
239 // Different threads have buffer periods ranging from 2 to 40. The
240 // formula below maps buffer period 2 to kBase = ~1, 4 to ~2, 20 to ~3, 40 to ~4.
241 // TODO: tighten this for higher means, the data still overflows
242 const double kBase = log(mean) / log(2.2);
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700243 const double power = floor(
Sanna Catherine de Treville Wager847b6e62017-08-03 11:35:51 -0700244 log(abs(x - mean) / mean) / log(kBase)) + 2;
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700245 // do not round values close to the mean
246 if (power < 1) {
247 return x;
248 }
249 const int factor = static_cast<int>(pow(10, power));
250 return (static_cast<int>(x) * factor) / factor;
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700251}
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -0700252
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700253// TODO Make it return a std::string instead of modifying body
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700254// TODO: move this to ReportPerformance, probably make it a friend function
255// of PerformanceAnalysis
256void PerformanceAnalysis::reportPerformance(String8 *body, int author, log_hash_t hash,
257 int maxHeight) {
Sanna Catherine de Treville Wagera80649a2017-07-21 16:16:38 -0700258 if (mHists.empty()) {
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700259 return;
260 }
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700261
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700262 // ms of active audio in displayed histogram
263 double elapsedMs = 0;
264 // starting timestamp of histogram
265 timestamp startingTs = mHists[0].first;
266
267 // histogram which stores .1 precision ms counts instead of Jiffy multiple counts
268 // TODO: when there is more data, print many histograms, possibly separated at peaks
269 std::map<double, int> buckets;
Sanna Catherine de Treville Wagera80649a2017-07-21 16:16:38 -0700270 for (const auto &shortHist: mHists) {
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700271 for (const auto &countPair : shortHist.second) {
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700272 const double ms = static_cast<double>(countPair.first) / kJiffyPerMs;
273 buckets[logRound(ms, mBufferPeriod.mMean)] += countPair.second;
Sanna Catherine de Treville Wager847b6e62017-08-03 11:35:51 -0700274 elapsedMs += ms * countPair.second;
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700275 }
276 }
277
278 // underscores and spaces length corresponds to maximum width of histogram
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700279 static const int kLen = 200;
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700280 std::string underscores(kLen, '_');
281 std::string spaces(kLen, ' ');
282
283 auto it = buckets.begin();
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700284 double maxDelta = it->first;
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700285 int maxCount = it->second;
286 // Compute maximum values
287 while (++it != buckets.end()) {
288 if (it->first > maxDelta) {
289 maxDelta = it->first;
290 }
291 if (it->second > maxCount) {
292 maxCount = it->second;
293 }
294 }
295 int height = log2(maxCount) + 1; // maxCount > 0, safe to call log2
296 const int leftPadding = widthOf(1 << height);
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700297 const int bucketWidth = numberWidth(maxDelta, leftPadding);
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700298 int scalingFactor = 1;
299 // scale data if it exceeds maximum height
300 if (height > maxHeight) {
301 scalingFactor = (height + maxHeight) / maxHeight;
302 height /= scalingFactor;
303 }
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700304 body->appendFormat("\n%*s %3.2f %s", leftPadding + 11,
305 "Occurrences in", (elapsedMs / kMsPerSec), "seconds of audio:");
306 body->appendFormat("\n%*s%d, %lld, %lld\n", leftPadding + 11,
307 "Thread, hash, starting timestamp: ", author,
308 static_cast<long long int>(hash), static_cast<long long int>(startingTs));
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700309 // write histogram label line with bucket values
310 body->appendFormat("\n%s", " ");
311 body->appendFormat("%*s", leftPadding, " ");
312 for (auto const &x : buckets) {
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700313 const int colWidth = numberWidth(x.first, leftPadding);
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700314 body->appendFormat("%*d", colWidth, x.second);
315 }
316 // write histogram ascii art
317 body->appendFormat("\n%s", " ");
318 for (int row = height * scalingFactor; row >= 0; row -= scalingFactor) {
319 const int value = 1 << row;
320 body->appendFormat("%.*s", leftPadding, spaces.c_str());
321 for (auto const &x : buckets) {
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700322 const int colWidth = numberWidth(x.first, leftPadding);
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700323 body->appendFormat("%.*s%s", colWidth - 1,
324 spaces.c_str(), x.second < value ? " " : "|");
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700325 }
326 body->appendFormat("\n%s", " ");
327 }
328 // print x-axis
329 const int columns = static_cast<int>(buckets.size());
330 body->appendFormat("%*c", leftPadding, ' ');
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700331 body->appendFormat("%.*s", (columns + 1) * bucketWidth, underscores.c_str());
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700332 body->appendFormat("\n%s", " ");
333
334 // write footer with bucket labels
335 body->appendFormat("%*s", leftPadding, " ");
336 for (auto const &x : buckets) {
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700337 const int colWidth = numberWidth(x.first, leftPadding);
338 body->appendFormat("%*.*f", colWidth, 1, x.first);
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700339 }
Sanna Catherine de Treville Wager6ad40ee2017-07-28 10:10:55 -0700340 body->appendFormat("%.*s%s", bucketWidth, spaces.c_str(), "ms\n");
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700341
Sanna Catherine de Treville Wager316f1fd2017-06-23 09:10:15 -0700342 // Now report glitches
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700343 body->appendFormat("\ntime elapsed between glitches and glitch timestamps:\n");
Sanna Catherine de Treville Wager316f1fd2017-06-23 09:10:15 -0700344 for (const auto &outlier: mOutlierData) {
345 body->appendFormat("%lld: %lld\n", static_cast<long long>(outlier.first),
346 static_cast<long long>(outlier.second));
347 }
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700348}
349
Sanna Catherine de Treville Wagercf6c75a2017-07-21 17:05:25 -0700350//------------------------------------------------------------------------------
351
352// writes summary of performance into specified file descriptor
Sanna Catherine de Treville Wager23f89d32017-07-24 18:24:48 -0700353void dump(int fd, int indent, PerformanceAnalysisMap &threadPerformanceAnalysis) {
Sanna Catherine de Treville Wagercf6c75a2017-07-21 17:05:25 -0700354 String8 body;
Sanna Catherine de Treville Wagerf8c34282017-07-25 11:31:18 -0700355 const char* const kDirectory = "/data/misc/audioserver/";
Sanna Catherine de Treville Wagercf6c75a2017-07-21 17:05:25 -0700356 for (auto & thread : threadPerformanceAnalysis) {
Sanna Catherine de Treville Wagerd0965172017-07-24 13:42:44 -0700357 for (auto & hash: thread.second) {
Sanna Catherine de Treville Wager23f89d32017-07-24 18:24:48 -0700358 PerformanceAnalysis& curr = hash.second;
Sanna Catherine de Treville Wager23f89d32017-07-24 18:24:48 -0700359 // write performance data to console
Sanna Catherine de Treville Wager2a6a9452017-07-28 11:02:01 -0700360 curr.reportPerformance(&body, thread.first, hash.first);
Sanna Catherine de Treville Wager0a3959e2017-07-25 16:08:17 -0700361 if (!body.isEmpty()) {
362 dumpLine(fd, indent, body);
363 body.clear();
364 }
Sanna Catherine de Treville Wager23f89d32017-07-24 18:24:48 -0700365 // write to file
Sanna Catherine de Treville Wagerf8c34282017-07-25 11:31:18 -0700366 writeToFile(curr.mHists, curr.mOutlierData, curr.mPeakTimestamps,
367 kDirectory, false, thread.first, hash.first);
Sanna Catherine de Treville Wagerd0965172017-07-24 13:42:44 -0700368 }
Sanna Catherine de Treville Wagercf6c75a2017-07-21 17:05:25 -0700369 }
Sanna Catherine de Treville Wagercf6c75a2017-07-21 17:05:25 -0700370}
371
Sanna Catherine de Treville Wager85768942017-07-26 20:17:30 -0700372
Sanna Catherine de Treville Wagercf6c75a2017-07-21 17:05:25 -0700373// Writes a string into specified file descriptor
374void dumpLine(int fd, int indent, const String8 &body) {
375 dprintf(fd, "%.*s%s \n", indent, "", body.string());
376}
377
Sanna Catherine de Treville Wager80448082017-07-11 14:07:59 -0700378} // namespace ReportPerformance
379
Sanna Catherine de Treville Wagerd0dfe432017-06-22 15:09:38 -0700380} // namespace android