FastMixerDumpState.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * Copyright (C) 2014 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. #define LOG_TAG "FastMixerDumpState"
  17. //#define LOG_NDEBUG 0
  18. #include "Configuration.h"
  19. #ifdef FAST_THREAD_STATISTICS
  20. #include <audio_utils/Statistics.h>
  21. #ifdef CPU_FREQUENCY_STATISTICS
  22. #include <cpustats/ThreadCpuUsage.h>
  23. #endif
  24. #endif
  25. #include <utils/Debug.h>
  26. #include <utils/Log.h>
  27. #include "FastMixerDumpState.h"
  28. namespace android {
  29. FastMixerDumpState::FastMixerDumpState() : FastThreadDumpState(),
  30. mWriteSequence(0), mFramesWritten(0),
  31. mNumTracks(0), mWriteErrors(0),
  32. mSampleRate(0), mFrameCount(0),
  33. mTrackMask(0)
  34. {
  35. }
  36. FastMixerDumpState::~FastMixerDumpState()
  37. {
  38. }
  39. // helper function called by qsort()
  40. static int compare_uint32_t(const void *pa, const void *pb)
  41. {
  42. uint32_t a = *(const uint32_t *)pa;
  43. uint32_t b = *(const uint32_t *)pb;
  44. if (a < b) {
  45. return -1;
  46. } else if (a > b) {
  47. return 1;
  48. } else {
  49. return 0;
  50. }
  51. }
  52. void FastMixerDumpState::dump(int fd) const
  53. {
  54. if (mCommand == FastMixerState::INITIAL) {
  55. dprintf(fd, " FastMixer not initialized\n");
  56. return;
  57. }
  58. double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
  59. (mMeasuredWarmupTs.tv_nsec / 1000000.0);
  60. double mixPeriodSec = (double) mFrameCount / mSampleRate;
  61. dprintf(fd, " FastMixer command=%s writeSequence=%u framesWritten=%u\n"
  62. " numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
  63. " sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
  64. " mixPeriod=%.2f ms latency=%.2f ms\n",
  65. FastMixerState::commandToString(mCommand), mWriteSequence, mFramesWritten,
  66. mNumTracks, mWriteErrors, mUnderruns, mOverruns,
  67. mSampleRate, mFrameCount, measuredWarmupMs, mWarmupCycles,
  68. mixPeriodSec * 1e3, mLatencyMs);
  69. dprintf(fd, " FastMixer Timestamp stats: %s\n", mTimestampVerifier.toString().c_str());
  70. #ifdef FAST_THREAD_STATISTICS
  71. // find the interval of valid samples
  72. const uint32_t bounds = mBounds;
  73. const uint32_t newestOpen = bounds & 0xFFFF;
  74. uint32_t oldestClosed = bounds >> 16;
  75. //uint32_t n = (newestOpen - oldestClosed) & 0xFFFF;
  76. uint32_t n;
  77. __builtin_sub_overflow(newestOpen, oldestClosed, &n);
  78. n &= 0xFFFF;
  79. if (n > mSamplingN) {
  80. ALOGE("too many samples %u", n);
  81. n = mSamplingN;
  82. }
  83. // statistics for monotonic (wall clock) time, thread raw CPU load in time, CPU clock frequency,
  84. // and adjusted CPU load in MHz normalized for CPU clock frequency
  85. audio_utils::Statistics<double> wall, loadNs;
  86. #ifdef CPU_FREQUENCY_STATISTICS
  87. audio_utils::Statistics<double> kHz, loadMHz;
  88. uint32_t previousCpukHz = 0;
  89. #endif
  90. // Assuming a normal distribution for cycle times, three standard deviations on either side of
  91. // the mean account for 99.73% of the population. So if we take each tail to be 1/1000 of the
  92. // sample set, we get 99.8% combined, or close to three standard deviations.
  93. static const uint32_t kTailDenominator = 1000;
  94. uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
  95. // loop over all the samples
  96. for (uint32_t j = 0; j < n; ++j) {
  97. size_t i = oldestClosed++ & (mSamplingN - 1);
  98. uint32_t wallNs = mMonotonicNs[i];
  99. if (tail != NULL) {
  100. tail[j] = wallNs;
  101. }
  102. wall.add(wallNs);
  103. uint32_t sampleLoadNs = mLoadNs[i];
  104. loadNs.add(sampleLoadNs);
  105. #ifdef CPU_FREQUENCY_STATISTICS
  106. uint32_t sampleCpukHz = mCpukHz[i];
  107. // skip bad kHz samples
  108. if ((sampleCpukHz & ~0xF) != 0) {
  109. kHz.add(sampleCpukHz >> 4);
  110. if (sampleCpukHz == previousCpukHz) {
  111. double megacycles = (double) sampleLoadNs * (double) (sampleCpukHz >> 4) * 1e-12;
  112. double adjMHz = megacycles / mixPeriodSec; // _not_ wallNs * 1e9
  113. loadMHz.add(adjMHz);
  114. }
  115. }
  116. previousCpukHz = sampleCpukHz;
  117. #endif
  118. }
  119. if (n) {
  120. dprintf(fd, " Simple moving statistics over last %.1f seconds:\n",
  121. wall.getN() * mixPeriodSec);
  122. dprintf(fd, " wall clock time in ms per mix cycle:\n"
  123. " mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
  124. wall.getMean()*1e-6, wall.getMin()*1e-6, wall.getMax()*1e-6,
  125. wall.getStdDev()*1e-6);
  126. dprintf(fd, " raw CPU load in us per mix cycle:\n"
  127. " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
  128. loadNs.getMean()*1e-3, loadNs.getMin()*1e-3, loadNs.getMax()*1e-3,
  129. loadNs.getStdDev()*1e-3);
  130. } else {
  131. dprintf(fd, " No FastMixer statistics available currently\n");
  132. }
  133. #ifdef CPU_FREQUENCY_STATISTICS
  134. dprintf(fd, " CPU clock frequency in MHz:\n"
  135. " mean=%.0f min=%.0f max=%.0f stddev=%.0f\n",
  136. kHz.getMean()*1e-3, kHz.getMin()*1e-3, kHz.getMax()*1e-3, kHz.getStdDev()*1e-3);
  137. dprintf(fd, " adjusted CPU load in MHz (i.e. normalized for CPU clock frequency):\n"
  138. " mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
  139. loadMHz.getMean(), loadMHz.getMin(), loadMHz.getMax(), loadMHz.getStdDev());
  140. #endif
  141. if (tail != NULL) {
  142. qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
  143. // assume same number of tail samples on each side, left and right
  144. uint32_t count = n / kTailDenominator;
  145. audio_utils::Statistics<double> left, right;
  146. for (uint32_t i = 0; i < count; ++i) {
  147. left.add(tail[i]);
  148. right.add(tail[n - (i + 1)]);
  149. }
  150. dprintf(fd, " Distribution of mix cycle times in ms for the tails "
  151. "(> ~3 stddev outliers):\n"
  152. " left tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n"
  153. " right tail: mean=%.2f min=%.2f max=%.2f stddev=%.2f\n",
  154. left.getMean()*1e-6, left.getMin()*1e-6, left.getMax()*1e-6, left.getStdDev()*1e-6,
  155. right.getMean()*1e-6, right.getMin()*1e-6, right.getMax()*1e-6,
  156. right.getStdDev()*1e-6);
  157. delete[] tail;
  158. }
  159. #endif
  160. // The active track mask and track states are updated non-atomically.
  161. // So if we relied on isActive to decide whether to display,
  162. // then we might display an obsolete track or omit an active track.
  163. // Instead we always display all tracks, with an indication
  164. // of whether we think the track is active.
  165. uint32_t trackMask = mTrackMask;
  166. dprintf(fd, " Fast tracks: sMaxFastTracks=%u activeMask=%#x\n",
  167. FastMixerState::sMaxFastTracks, trackMask);
  168. dprintf(fd, " Index Active Full Partial Empty Recent Ready Written\n");
  169. for (uint32_t i = 0; i < FastMixerState::sMaxFastTracks; ++i, trackMask >>= 1) {
  170. bool isActive = trackMask & 1;
  171. const FastTrackDump *ftDump = &mTracks[i];
  172. const FastTrackUnderruns& underruns = ftDump->mUnderruns;
  173. const char *mostRecent;
  174. switch (underruns.mBitFields.mMostRecent) {
  175. case UNDERRUN_FULL:
  176. mostRecent = "full";
  177. break;
  178. case UNDERRUN_PARTIAL:
  179. mostRecent = "partial";
  180. break;
  181. case UNDERRUN_EMPTY:
  182. mostRecent = "empty";
  183. break;
  184. default:
  185. mostRecent = "?";
  186. break;
  187. }
  188. dprintf(fd, " %5u %6s %4u %7u %5u %7s %5zu %10lld\n",
  189. i, isActive ? "yes" : "no",
  190. (underruns.mBitFields.mFull) & UNDERRUN_MASK,
  191. (underruns.mBitFields.mPartial) & UNDERRUN_MASK,
  192. (underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
  193. mostRecent, ftDump->mFramesReady,
  194. (long long)ftDump->mFramesWritten);
  195. }
  196. }
  197. } // android