mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 23:40:11 +02:00
add timings to AudioMixer
This commit is contained in:
parent
2a6e46aa0c
commit
132e9bd644
2 changed files with 96 additions and 23 deletions
|
@ -260,6 +260,7 @@ void AudioMixer::sendStatsPacket() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// general stats
|
||||||
statsObject["useDynamicJitterBuffers"] = _numStaticJitterFrames == -1;
|
statsObject["useDynamicJitterBuffers"] = _numStaticJitterFrames == -1;
|
||||||
statsObject["trailing_sleep_percentage"] = _trailingSleepRatio * 100.0f;
|
statsObject["trailing_sleep_percentage"] = _trailingSleepRatio * 100.0f;
|
||||||
statsObject["performance_throttling_ratio"] = _performanceThrottlingRatio;
|
statsObject["performance_throttling_ratio"] = _performanceThrottlingRatio;
|
||||||
|
@ -267,16 +268,36 @@ void AudioMixer::sendStatsPacket() {
|
||||||
statsObject["avg_streams_per_frame"] = (float)_stats.sumStreams / (float)_numStatFrames;
|
statsObject["avg_streams_per_frame"] = (float)_stats.sumStreams / (float)_numStatFrames;
|
||||||
statsObject["avg_listeners_per_frame"] = (float)_stats.sumListeners / (float)_numStatFrames;
|
statsObject["avg_listeners_per_frame"] = (float)_stats.sumListeners / (float)_numStatFrames;
|
||||||
|
|
||||||
_sumMixTimesIndex = (_sumMixTimesIndex + 1) % MIX_TIMES_TRAILING_SECONDS;
|
// timing stats
|
||||||
_sumMixTimesTrailing -= _sumMixTimesHistory[_sumMixTimesIndex];
|
QJsonObject timingStats;
|
||||||
_sumMixTimesHistory[_sumMixTimesIndex] = _sumMixTimes.count();
|
uint64_t timing, trailing;
|
||||||
_sumMixTimesTrailing += _sumMixTimesHistory[_sumMixTimesIndex];
|
|
||||||
|
|
||||||
statsObject["avg_us_per_frame"] = (qint64)(_sumMixTimes.count() / _numStatFrames);
|
_sleepTiming.get(timing, trailing);
|
||||||
statsObject["avg_us_per_frames_trailing"] =
|
timingStats["us_per_sleep"] = (qint64)(timing / _numStatFrames);
|
||||||
(qint64)((_sumMixTimesTrailing / MIX_TIMES_TRAILING_SECONDS) / _numStatFrames);
|
timingStats["us_per_sleep_trailing"] = (qint64)(trailing / _numStatFrames);
|
||||||
|
|
||||||
|
_frameTiming.get(timing, trailing);
|
||||||
|
timingStats["us_per_frame"] = (qint64)(timing / _numStatFrames);
|
||||||
|
timingStats["us_per_frame_trailing"] = (qint64)(trailing / _numStatFrames);
|
||||||
|
|
||||||
|
_prepareTiming.get(timing, trailing);
|
||||||
|
timingStats["us_per_prepare"] = (qint64)(timing / _numStatFrames);
|
||||||
|
timingStats["us_per_prepare_trailing"] = (qint64)(trailing / _numStatFrames);
|
||||||
|
|
||||||
|
_mixTiming.get(timing, trailing);
|
||||||
|
timingStats["us_per_mix"] = (qint64)(timing / _numStatFrames);
|
||||||
|
timingStats["us_per_mix_trailing"] = (qint64)(trailing / _numStatFrames);
|
||||||
|
|
||||||
|
_eventsTiming.get(timing, trailing);
|
||||||
|
timingStats["us_per_events"] = (qint64)(timing / _numStatFrames);
|
||||||
|
timingStats["us_per_events_trailing"] = (qint64)(trailing / _numStatFrames);
|
||||||
|
|
||||||
|
// call it "avg_..." to keep it higher in the display, sorted alphabetically
|
||||||
|
statsObject["avg_timing_stats"] = timingStats;
|
||||||
|
|
||||||
|
// mix stats
|
||||||
QJsonObject mixStats;
|
QJsonObject mixStats;
|
||||||
|
|
||||||
mixStats["%_hrtf_mixes"] = percentageForMixStats(_stats.hrtfRenders);
|
mixStats["%_hrtf_mixes"] = percentageForMixStats(_stats.hrtfRenders);
|
||||||
mixStats["%_hrtf_silent_mixes"] = percentageForMixStats(_stats.hrtfSilentRenders);
|
mixStats["%_hrtf_silent_mixes"] = percentageForMixStats(_stats.hrtfSilentRenders);
|
||||||
mixStats["%_hrtf_struggle_mixes"] = percentageForMixStats(_stats.hrtfStruggleRenders);
|
mixStats["%_hrtf_struggle_mixes"] = percentageForMixStats(_stats.hrtfStruggleRenders);
|
||||||
|
@ -289,7 +310,6 @@ void AudioMixer::sendStatsPacket() {
|
||||||
statsObject["mix_stats"] = mixStats;
|
statsObject["mix_stats"] = mixStats;
|
||||||
|
|
||||||
_numStatFrames = 0;
|
_numStatFrames = 0;
|
||||||
_sumMixTimes = std::chrono::microseconds(0);
|
|
||||||
_stats.reset();
|
_stats.reset();
|
||||||
|
|
||||||
// add stats for each listerner
|
// add stats for each listerner
|
||||||
|
@ -364,22 +384,30 @@ void AudioMixer::start() {
|
||||||
unsigned int frame = 1;
|
unsigned int frame = 1;
|
||||||
|
|
||||||
while (!_isFinished) {
|
while (!_isFinished) {
|
||||||
manageLoad(frameTimestamp, framesSinceManagement);
|
{
|
||||||
|
auto timer = _sleepTiming.timer();
|
||||||
|
manageLoad(frameTimestamp, framesSinceManagement);
|
||||||
|
}
|
||||||
|
|
||||||
// start timing the frame
|
auto timer = _frameTiming.timer();
|
||||||
auto startTime = p_high_resolution_clock::now();
|
|
||||||
|
|
||||||
// aquire the read-lock in a single thread, to avoid canonical rwlock undefined behaviors
|
// aquire the read-lock in a single thread, to avoid canonical rwlock undefined behaviors
|
||||||
// node removal will acquire a write lock;
|
// node removal will acquire a write lock;
|
||||||
// read locks (in slave threads) while a write lock is pending have undefined order in pthread
|
// read locks (in slave threads) while a write lock is pending have undefined order in pthread
|
||||||
nodeList->algorithm([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) {
|
nodeList->algorithm([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) {
|
||||||
// prepare frames; pop off any new audio from their streams
|
// prepare frames; pop off any new audio from their streams
|
||||||
std::for_each(cbegin, cend, [&](const SharedNodePointer& node) {
|
{
|
||||||
_stats.sumStreams += prepareFrame(node, frame);
|
auto timer = _prepareTiming.timer();
|
||||||
});
|
std::for_each(cbegin, cend, [&](const SharedNodePointer& node) {
|
||||||
|
_stats.sumStreams += prepareFrame(node, frame);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// mix across slave threads
|
// mix across slave threads
|
||||||
_slavePool.mix(cbegin, cend, frame);
|
{
|
||||||
|
auto timer = _mixTiming.timer();
|
||||||
|
_slavePool.mix(cbegin, cend, frame);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// gather stats
|
// gather stats
|
||||||
|
@ -388,14 +416,13 @@ void AudioMixer::start() {
|
||||||
slave.stats.reset();
|
slave.stats.reset();
|
||||||
});
|
});
|
||||||
|
|
||||||
// stop timing the frame
|
|
||||||
_sumMixTimes += std::chrono::duration_cast<std::chrono::microseconds>(p_high_resolution_clock::now() - startTime);
|
|
||||||
|
|
||||||
++frame;
|
++frame;
|
||||||
++_numStatFrames;
|
++_numStatFrames;
|
||||||
|
|
||||||
// play nice with qt event-looping
|
// play nice with qt event-looping
|
||||||
{
|
{
|
||||||
|
auto timer = _eventsTiming.timer();
|
||||||
|
|
||||||
// since we're a while loop we need to yield to qt's event processing
|
// since we're a while loop we need to yield to qt's event processing
|
||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
@ -695,3 +722,28 @@ void AudioMixer::parseSettingsObject(const QJsonObject &settingsObject) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioMixer::Timer::Timing::Timing(uint64_t& sum) : _sum(sum) {
|
||||||
|
_timing = p_high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioMixer::Timer::Timing::~Timing() {
|
||||||
|
_sum += std::chrono::duration_cast<std::chrono::microseconds>(p_high_resolution_clock::now() - _timing).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioMixer::Timer::get(uint64_t& timing, uint64_t& trailing) {
|
||||||
|
// update history
|
||||||
|
_index = (_index + 1) % TIMER_TRAILING_SECONDS;
|
||||||
|
uint64_t oldTiming = _history[_index];
|
||||||
|
_history[_index] = _sum;
|
||||||
|
|
||||||
|
// update trailing
|
||||||
|
_trailing -= oldTiming;
|
||||||
|
_trailing += _sum;
|
||||||
|
|
||||||
|
timing = _sum;
|
||||||
|
trailing = _trailing / TIMER_TRAILING_SECONDS;
|
||||||
|
|
||||||
|
// reset _sum;
|
||||||
|
_sum = 0;
|
||||||
|
}
|
||||||
|
|
|
@ -90,11 +90,32 @@ private:
|
||||||
|
|
||||||
AudioMixerSlavePool _slavePool;
|
AudioMixerSlavePool _slavePool;
|
||||||
|
|
||||||
static const int MIX_TIMES_TRAILING_SECONDS = 10;
|
class Timer {
|
||||||
std::chrono::microseconds _sumMixTimes { 0 };
|
public:
|
||||||
uint64_t _sumMixTimesTrailing { 0 };
|
class Timing{
|
||||||
uint64_t _sumMixTimesHistory[MIX_TIMES_TRAILING_SECONDS] {};
|
public:
|
||||||
int _sumMixTimesIndex { 0 };
|
Timing(uint64_t& sum);
|
||||||
|
~Timing();
|
||||||
|
private:
|
||||||
|
p_high_resolution_clock::time_point _timing;
|
||||||
|
uint64_t& _sum;
|
||||||
|
};
|
||||||
|
|
||||||
|
Timing timer() { return Timing(_sum); }
|
||||||
|
void get(uint64_t& timing, uint64_t& trailing);
|
||||||
|
private:
|
||||||
|
static const int TIMER_TRAILING_SECONDS = 10;
|
||||||
|
|
||||||
|
uint64_t _sum { 0 };
|
||||||
|
uint64_t _trailing { 0 };
|
||||||
|
uint64_t _history[TIMER_TRAILING_SECONDS] {};
|
||||||
|
int _index { 0 };
|
||||||
|
};
|
||||||
|
Timer _sleepTiming;
|
||||||
|
Timer _frameTiming;
|
||||||
|
Timer _prepareTiming;
|
||||||
|
Timer _mixTiming;
|
||||||
|
Timer _eventsTiming;
|
||||||
|
|
||||||
static int _numStaticJitterFrames; // -1 denotes dynamic jitter buffering
|
static int _numStaticJitterFrames; // -1 denotes dynamic jitter buffering
|
||||||
static float _noiseMutingThreshold;
|
static float _noiseMutingThreshold;
|
||||||
|
|
Loading…
Reference in a new issue