From f2dcacffd025a465333efdd4fd818b1af3767cef Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 28 Apr 2015 09:47:19 -0700 Subject: [PATCH] show avatar data receive rate by default with display name --- interface/src/avatar/Avatar.cpp | 16 ++++++++++++++-- libraries/avatars/src/AvatarData.cpp | 17 ++++++++++++----- libraries/avatars/src/AvatarData.h | 13 ++++++++----- libraries/avatars/src/AvatarHashMap.cpp | 4 ++-- libraries/shared/src/SimpleMovingAverage.cpp | 6 +++--- libraries/shared/src/SimpleMovingAverage.h | 7 +++++-- 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b3439317d8..94589623bf 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -581,7 +581,8 @@ void Avatar::renderBillboard() { glm::vec2 texCoordTopLeft(0.0f, 0.0f); glm::vec2 texCoordBottomRight(1.0f, 1.0f); - DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); + DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, + glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); glPopMatrix(); @@ -709,11 +710,22 @@ void Avatar::renderDisplayName() { glm::vec4(0.2f, 0.2f, 0.2f, _displayNameAlpha * DISPLAYNAME_BACKGROUND_ALPHA / DISPLAYNAME_ALPHA)); glm::vec4 color(0.93f, 0.93f, 0.93f, _displayNameAlpha); + + // optionally render timing stats for this avatar with the display name + QString renderedDisplayName = _displayName; + + const float BYTES_PER_KILOBYTE = 1000.0f; + float kilobytesPerSecond = getAverageBytesReceivedPerSecond() / BYTES_PER_KILOBYTE; + + renderedDisplayName += QString(" - (%1 KBps, %2 Hz)") + .arg(QString::number(kilobytesPerSecond, 'f', 2)) + .arg(getReceiveRate()); + QByteArray ba = _displayName.toLocal8Bit(); const char* text = ba.data(); glDisable(GL_POLYGON_OFFSET_FILL); - textRenderer(DISPLAYNAME)->draw(text_x, text_y, text, color); + textRenderer(DISPLAYNAME)->draw(text_x, text_y, renderedDisplayName, color); glPopMatrix(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index a8d2c209c3..f0e4eb118b 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -58,11 +58,11 @@ AvatarData::AvatarData() : _billboard(), _errorLogExpiry(0), _owningAvatarMixer(), - _lastUpdateTimer(), _velocity(0.0f), _targetVelocity(0.0f), _localAABox(DEFAULT_LOCAL_AABOX_CORNER, DEFAULT_LOCAL_AABOX_SCALE) { + } AvatarData::~AvatarData() { @@ -268,9 +268,6 @@ bool AvatarData::shouldLogError(const quint64& now) { // read data in packet starting at byte offset and return number of bytes parsed int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { - // reset the last heard timer since we have new data for this AvatarData - _lastUpdateTimer.restart(); - // lazily allocate memory for HeadData in case we're not an Avatar instance if (!_headData) { _headData = new HeadData(this); @@ -555,7 +552,17 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { } } // numJoints * 8 bytes - return sourceBuffer - startPosition; + int numBytesRead = sourceBuffer - startPosition; + _averageBytesReceived.updateAverage(numBytesRead); + return numBytesRead; +} + +int AvatarData::getAverageBytesReceivedPerSecond() const { + return lrint(_averageBytesReceived.getAverageSampleValuePerSecond()); +} + +int AvatarData::getReceiveRate() const { + return lrint(1.0f / _averageBytesReceived.getEventDeltaAverage()); } bool AvatarData::hasReferential() { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 58e9c42c3c..0aa911112a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -46,9 +46,9 @@ typedef unsigned long long quint64; #include #include -#include - #include +#include +#include #include "AABox.h" #include "HandData.h" @@ -293,11 +293,13 @@ public: Node* getOwningAvatarMixer() { return _owningAvatarMixer.data(); } void setOwningAvatarMixer(const QWeakPointer& owningAvatarMixer) { _owningAvatarMixer = owningAvatarMixer; } - QElapsedTimer& getLastUpdateTimer() { return _lastUpdateTimer; } - const AABox& getLocalAABox() const { return _localAABox; } const Referential* getReferential() const { return _referential; } + int getUsecsSinceLastUpdate() const { return _averageBytesReceived.getUsecsSinceLastEvent(); } + int getAverageBytesReceivedPerSecond() const; + int getReceiveRate() const; + void setVelocity(const glm::vec3 velocity) { _velocity = velocity; } Q_INVOKABLE glm::vec3 getVelocity() const { return _velocity; } glm::vec3 getTargetVelocity() const { return _targetVelocity; } @@ -382,7 +384,6 @@ protected: quint64 _errorLogExpiry; ///< time in future when to log an error QWeakPointer _owningAvatarMixer; - QElapsedTimer _lastUpdateTimer; PlayerPointer _player; @@ -395,6 +396,8 @@ protected: AABox _localAABox; + SimpleMovingAverage _averageBytesReceived {}; + private: // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index ae3a8c3e5c..3e913acbd7 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -25,11 +25,11 @@ AvatarHash::iterator AvatarHashMap::erase(const AvatarHash::iterator& iterator) return _avatarHash.erase(iterator); } -const qint64 AVATAR_SILENCE_THRESHOLD_MSECS = 5 * 1000; +const qint64 AVATAR_SILENCE_THRESHOLD_USECS = 5 * 1000 * 1000; bool AvatarHashMap::shouldKillAvatar(const AvatarSharedPointer& sharedAvatar) { return (sharedAvatar->getOwningAvatarMixer() == NULL - || sharedAvatar->getLastUpdateTimer().elapsed() > AVATAR_SILENCE_THRESHOLD_MSECS); + || sharedAvatar->getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS); } void AvatarHashMap::processAvatarMixerDatagram(const QByteArray& datagram, const QWeakPointer& mixerWeakPointer) { diff --git a/libraries/shared/src/SimpleMovingAverage.cpp b/libraries/shared/src/SimpleMovingAverage.cpp index 90a9509c91..1d2574ecbf 100644 --- a/libraries/shared/src/SimpleMovingAverage.cpp +++ b/libraries/shared/src/SimpleMovingAverage.cpp @@ -52,9 +52,9 @@ void SimpleMovingAverage::reset() { float SimpleMovingAverage::getEventDeltaAverage() const { return (ONE_MINUS_WEIGHTING * _eventDeltaAverage) + - (WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000.0f)); + (WEIGHTING * ((usecTimestampNow() - _lastEventTimestamp) / 1000000.0f )); } -float SimpleMovingAverage::getAverageSampleValuePerSecond() const { - return _average * (1.0f / getEventDeltaAverage()); +uint64_t SimpleMovingAverage::getUsecsSinceLastEvent() const { + return usecTimestampNow() - _lastEventTimestamp; } diff --git a/libraries/shared/src/SimpleMovingAverage.h b/libraries/shared/src/SimpleMovingAverage.h index 3eec9d5be8..4233411466 100644 --- a/libraries/shared/src/SimpleMovingAverage.h +++ b/libraries/shared/src/SimpleMovingAverage.h @@ -25,8 +25,11 @@ public: int getSampleCount() const { return _numSamples; }; float getAverage() const { return _average; }; - float getEventDeltaAverage() const; - float getAverageSampleValuePerSecond() const; + float getEventDeltaAverage() const; // returned in microseconds + float getAverageSampleValuePerSecond() const { return _average * (1.0f / getEventDeltaAverage()); } + + uint64_t getUsecsSinceLastEvent() const; + private: int _numSamples; uint64_t _lastEventTimestamp;