1 /* 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 #ifndef ANDROID_MEDIA_PERFORMANCEANALYSIS_H 18 #define ANDROID_MEDIA_PERFORMANCEANALYSIS_H 19 20 #include <deque> 21 #include <map> 22 #include <vector> 23 24 #include <media/nblog/ReportPerformance.h> 25 26 namespace android { 27 28 namespace ReportPerformance { 29 30 class PerformanceAnalysis; 31 32 // a map of PerformanceAnalysis instances 33 // The outer key is for the thread, the inner key for the source file location. 34 using PerformanceAnalysisMap = std::map<int, std::map<log_hash_t, PerformanceAnalysis>>; 35 36 class PerformanceAnalysis { 37 // This class stores and analyzes audio processing wakeup timestamps from NBLog 38 // FIXME: currently, all performance data is stored in deques. Turn these into circular 39 // buffers. 40 // TODO: add a mutex. 41 public: 42 PerformanceAnalysis()43 PerformanceAnalysis() {}; 44 45 friend void dump(int fd, int indent, 46 PerformanceAnalysisMap &threadPerformanceAnalysis); 47 48 // Called in the case of an audio on/off event, e.g., EVENT_AUDIO_STATE. 49 // Used to discard idle time intervals 50 void handleStateChange(); 51 52 // Writes wakeup timestamp entry to log and runs analysis 53 void logTsEntry(timestamp ts); 54 55 // FIXME: make peakdetector and storeOutlierData a single function 56 // Input: mOutlierData. Looks at time elapsed between outliers 57 // finds significant changes in the distribution 58 // writes timestamps of significant changes to mPeakTimestamps 59 bool detectAndStorePeak(msInterval delta, timestamp ts); 60 61 // stores timestamps of intervals above a threshold: these are assumed outliers. 62 // writes to mOutlierData <time elapsed since previous outlier, outlier timestamp> 63 bool detectAndStoreOutlier(const msInterval diffMs); 64 65 // Generates a string of analysis of the buffer periods and prints to console 66 // FIXME: move this data visualization to a separate class. Model/view/controller 67 void reportPerformance(String8 *body, int author, log_hash_t hash, 68 int maxHeight = 10); 69 70 private: 71 72 // TODO use a circular buffer for the deques and vectors below 73 74 // stores outlier analysis: 75 // <elapsed time between outliers in ms, outlier beginning timestamp> 76 std::deque<std::pair<msInterval, timestamp>> mOutlierData; 77 78 // stores each timestamp at which a peak was detected 79 // a peak is a moment at which the average outlier interval changed significantly 80 std::deque<timestamp> mPeakTimestamps; 81 82 // stores buffer period histograms with timestamp of first sample 83 std::deque<std::pair<timestamp, Histogram>> mHists; 84 85 // Parameters used when detecting outliers 86 struct BufferPeriod { 87 double mMean = -1; // average time between audio processing wakeups 88 double mOutlierFactor = -1; // values > mMean * mOutlierFactor are outliers 89 double mOutlier = -1; // this is set to mMean * mOutlierFactor 90 timestamp mPrevTs = -1; // previous timestamp 91 } mBufferPeriod; 92 93 // capacity allocated to data structures 94 struct MaxLength { 95 size_t Hists; // number of histograms stored in memory 96 size_t Outliers; // number of values stored in outlier array 97 size_t Peaks; // number of values stored in peak array 98 int HistTimespanMs; // maximum histogram timespan 99 }; 100 // These values allow for 10 hours of data allowing for a glitch and a peak 101 // as often as every 3 seconds 102 static constexpr MaxLength kMaxLength = {.Hists = 60, .Outliers = 12000, 103 .Peaks = 12000, .HistTimespanMs = 10 * kSecPerMin * kMsPerSec }; 104 105 // these variables ensure continuity while analyzing the timestamp 106 // series one sample at a time. 107 // TODO: change this to a running variance/mean class 108 struct OutlierDistribution { 109 msInterval mMean = 0; // sample mean since previous peak 110 msInterval mSd = 0; // sample sd since previous peak 111 msInterval mElapsed = 0; // time since previous detected outlier 112 const int kMaxDeviation = 5; // standard deviations from the mean threshold 113 msInterval mTypicalDiff = 0; // global mean of outliers 114 double mN = 0; // length of sequence since the last peak 115 double mM2 = 0; // used to calculate sd 116 } mOutlierDistribution; 117 }; 118 119 void dump(int fd, int indent, PerformanceAnalysisMap &threadPerformanceAnalysis); 120 void dumpLine(int fd, int indent, const String8 &body); 121 122 } // namespace ReportPerformance 123 124 } // namespace android 125 126 #endif // ANDROID_MEDIA_PERFORMANCEANALYSIS_H 127