From 357cc052e10541c0b3b420978438f3952a1e839a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 8 Feb 2017 15:32:48 -0800 Subject: [PATCH 1/7] first cut at simulation stats --- interface/src/avatar/Avatar.cpp | 18 ++++++++++++++++++ interface/src/avatar/Avatar.h | 8 ++++++++ interface/src/avatar/AvatarManager.cpp | 7 +++++++ interface/src/avatar/AvatarManager.h | 2 ++ .../developer/debugging/debugAvatarMixer.js | 9 +++++++-- 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 64e82f63da..f8105eca16 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -306,13 +306,18 @@ bool Avatar::shouldDie() const { } void Avatar::simulate(float deltaTime, bool inView) { + _simulationRate.increment(); + PROFILE_RANGE(simulation, "simulate"); PerformanceTimer perfTimer("simulate"); { PROFILE_RANGE(simulation, "updateJoints"); if (inView && _hasNewJointData) { _skeletonModel->getRig()->copyJointsFromJointData(_jointData); + _jointDataSimulationRate.increment(); + _skeletonModel->simulate(deltaTime, true); + _skeletonModelSimulationRate.increment(); locationChanged(); // joints changed, so if there are any children, update them. _hasNewJointData = false; @@ -328,6 +333,7 @@ void Avatar::simulate(float deltaTime, bool inView) { } else { // a non-full update is still required so that the position, rotation, scale and bounds of the skeletonModel are updated. _skeletonModel->simulate(deltaTime, false); + _skeletonModelSimulationRate.increment(); } } @@ -357,6 +363,18 @@ void Avatar::simulate(float deltaTime, bool inView) { } } +float Avatar::getSimulationRate(const QString& rateName) { + if (rateName == "") { + return _simulationRate.rate(); + } else if (rateName == "avatar") { + return _simulationRate.rate(); + } else if (rateName == "skeletonModel") { + return _skeletonModelSimulationRate.rate(); + } else if (rateName == "jointData") { + return _jointDataSimulationRate.rate(); + } +} + bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const { const float HEAD_SPHERE_RADIUS = 0.1f; glm::vec3 theirLookAt = dynamic_pointer_cast(avatar)->getHead()->getLookAtPosition(); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 8f2b0817c1..e0d19fcbc1 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -182,6 +182,8 @@ public: void animateScaleChanges(float deltaTime); void setTargetScale(float targetScale) override; + Q_INVOKABLE float getSimulationRate(const QString& rateName = QString("")); + public slots: // FIXME - these should be migrated to use Pose data instead @@ -259,6 +261,12 @@ protected: void addToScene(AvatarSharedPointer self); void ensureInScene(AvatarSharedPointer self); + // Some rate tracking support + RateCounter<> _simulationRate; + RateCounter<> _skeletonModelSimulationRate; + RateCounter<> _jointDataSimulationRate; + + private: uint64_t _lastRenderUpdateTime { 0 }; int _leftPointerGeometryID { 0 }; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index df3164e6fc..136d7cc016 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -137,6 +137,13 @@ float AvatarManager::getAvatarDataRate(const QUuid& sessionID, const QString& ra return avatar->getDataRate(rateName); } +float AvatarManager::getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName) { + auto avatar = std::static_pointer_cast(getAvatarBySessionID(sessionID)); + return avatar ? avatar->getSimulationRate(rateName) : 0.0f; +} + + + class AvatarPriority { public: AvatarPriority(AvatarSharedPointer a, float p) : avatar(a), priority(p) {} diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 787d6f2d83..c80fd14def 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -70,6 +70,8 @@ public: void handleCollisionEvents(const CollisionEvents& collisionEvents); Q_INVOKABLE float getAvatarDataRate(const QUuid& sessionID, const QString& rateName = QString("")); + Q_INVOKABLE float getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName = QString("")); + Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude = QScriptValue(), const QScriptValue& avatarIdsToDiscard = QScriptValue()); diff --git a/scripts/developer/debugging/debugAvatarMixer.js b/scripts/developer/debugging/debugAvatarMixer.js index 6c0a935b70..1c11d308b8 100644 --- a/scripts/developer/debugging/debugAvatarMixer.js +++ b/scripts/developer/debugging/debugAvatarMixer.js @@ -60,7 +60,8 @@ function updateOverlays() { var overlayPosition = avatar.getJointPosition("Head"); overlayPosition.y += 1.05; - var text = " All: " + AvatarManager.getAvatarDataRate(avatarID).toFixed(2) + "\n" + var text = "--- Data from Mixer ----------------------\n" + +"All: " + AvatarManager.getAvatarDataRate(avatarID).toFixed(2) + "\n" +" GP: " + AvatarManager.getAvatarDataRate(avatarID,"globalPosition").toFixed(2) + "\n" +" LP: " + AvatarManager.getAvatarDataRate(avatarID,"localPosition").toFixed(2) + "\n" +" BB: " + AvatarManager.getAvatarDataRate(avatarID,"avatarBoundingBox").toFixed(2) + "\n" @@ -72,7 +73,11 @@ function updateOverlays() { +" AF: " + AvatarManager.getAvatarDataRate(avatarID,"additionalFlags").toFixed(2) + "\n" +" PI: " + AvatarManager.getAvatarDataRate(avatarID,"parentInfo").toFixed(2) + "\n" +" FT: " + AvatarManager.getAvatarDataRate(avatarID,"faceTracker").toFixed(2) + "\n" - +" JD: " + AvatarManager.getAvatarDataRate(avatarID,"jointData").toFixed(2); + +" JD: " + AvatarManager.getAvatarDataRate(avatarID,"jointData").toFixed(2) + +"--- Simulation ----------------------\n" + +"All: " + AvatarManager.getAvatarSimulationRate(avatarID,"avatar").toFixed(2) + "\n" + +" SM: " + AvatarManager.getAvatarSimulationRate(avatarID,"skeletonModel").toFixed(2) + "\n" + +" JS: " + AvatarManager.getAvatarSimulationRate(avatarID,"jointData").toFixed(2) + "\n" if (avatarID in debugOverlays) { // keep the overlay above the current position of this avatar From 6c41a2503246e2e8ab3278963261433ed0c7e6db Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 8 Feb 2017 16:51:00 -0800 Subject: [PATCH 2/7] more stats --- interface/src/avatar/Avatar.cpp | 1 + interface/src/avatar/AvatarManager.cpp | 7 ++- interface/src/avatar/AvatarManager.h | 1 + libraries/avatars/src/AvatarData.cpp | 46 ++++++++++++++++++- libraries/avatars/src/AvatarData.h | 20 +++++++- .../developer/debugging/debugAvatarMixer.js | 36 +++++++-------- 6 files changed, 89 insertions(+), 22 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index f8105eca16..cb381024ba 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -373,6 +373,7 @@ float Avatar::getSimulationRate(const QString& rateName) { } else if (rateName == "jointData") { return _jointDataSimulationRate.rate(); } + return 0.0f; } bool Avatar::isLookingAtMe(AvatarSharedPointer avatar) const { diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 136d7cc016..aff9ec3add 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -134,7 +134,12 @@ Q_LOGGING_CATEGORY(trace_simulation_avatar, "trace.simulation.avatar"); float AvatarManager::getAvatarDataRate(const QUuid& sessionID, const QString& rateName) { auto avatar = getAvatarBySessionID(sessionID); - return avatar->getDataRate(rateName); + return avatar ? avatar->getDataRate(rateName) : 0.0f; +} + +float AvatarManager::getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName) { + auto avatar = getAvatarBySessionID(sessionID); + return avatar ? avatar->getUpdateRate(rateName) : 0.0f; } float AvatarManager::getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName) { diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index c80fd14def..00ae745c98 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -70,6 +70,7 @@ public: void handleCollisionEvents(const CollisionEvents& collisionEvents); Q_INVOKABLE float getAvatarDataRate(const QUuid& sessionID, const QString& rateName = QString("")); + Q_INVOKABLE float getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName = QString("")); Q_INVOKABLE float getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName = QString("")); Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b25140d0a8..146b193a69 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -670,6 +670,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { sourceBuffer += sizeof(AvatarDataPacket::AvatarGlobalPosition); int numBytesRead = sourceBuffer - startSection; _globalPositionRate.increment(numBytesRead); + _globalPositionUpdateRate.increment(); // if we don't have a parent, make sure to also set our local position if (!hasParent()) { @@ -698,6 +699,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { sourceBuffer += sizeof(AvatarDataPacket::AvatarBoundingBox); int numBytesRead = sourceBuffer - startSection; _avatarBoundingBoxRate.increment(numBytesRead); + _avatarBoundingBoxUpdateRate.increment(); } if (hasAvatarOrientation) { @@ -713,6 +715,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } int numBytesRead = sourceBuffer - startSection; _avatarOrientationRate.increment(numBytesRead); + _avatarOrientationUpdateRate.increment(); } if (hasAvatarScale) { @@ -732,6 +735,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { sourceBuffer += sizeof(AvatarDataPacket::AvatarScale); int numBytesRead = sourceBuffer - startSection; _avatarScaleRate.increment(numBytesRead); + _avatarScaleUpdateRate.increment(); } if (hasLookAtPosition) { @@ -750,6 +754,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { sourceBuffer += sizeof(AvatarDataPacket::LookAtPosition); int numBytesRead = sourceBuffer - startSection; _lookAtPositionRate.increment(numBytesRead); + _lookAtPositionUpdateRate.increment(); } if (hasAudioLoudness) { @@ -770,6 +775,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { _headData->setAudioLoudness(audioLoudness); int numBytesRead = sourceBuffer - startSection; _audioLoudnessRate.increment(numBytesRead); + _audioLoudnessUpdateRate.increment(); } if (hasSensorToWorldMatrix) { @@ -790,6 +796,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { sourceBuffer += sizeof(AvatarDataPacket::SensorToWorldMatrix); int numBytesRead = sourceBuffer - startSection; _sensorToWorldRate.increment(numBytesRead); + _sensorToWorldUpdateRate.increment(); } if (hasAdditionalFlags) { @@ -833,6 +840,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { } int numBytesRead = sourceBuffer - startSection; _additionalFlagsRate.increment(numBytesRead); + _additionalFlagsUpdateRate.increment(); } // FIXME -- make sure to handle the existance of a parent vs a change in the parent... @@ -855,7 +863,9 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { int numBytesRead = sourceBuffer - startSection; _parentInfoRate.increment(numBytesRead); - } else { + _parentInfoUpdateRate.increment(); + } + else { // FIXME - this aint totally right, for switching to parent/no-parent _parentID = QUuid(); } @@ -877,6 +887,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { sourceBuffer += sizeof(AvatarDataPacket::AvatarLocalPosition); int numBytesRead = sourceBuffer - startSection; _localPositionRate.increment(numBytesRead); + _localPositionUpdateRate.increment(); } if (hasFaceTrackerInfo) { @@ -899,6 +910,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { sourceBuffer += coefficientsSize; int numBytesRead = sourceBuffer - startSection; _faceTrackerRate.increment(numBytesRead); + _faceTrackerUpdateRate.increment(); } if (hasJointData) { @@ -991,12 +1003,14 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { int numBytesRead = sourceBuffer - startSection; _jointDataRate.increment(numBytesRead); + _jointDataUpdateRate.increment(); } int numBytesRead = sourceBuffer - startPosition; _averageBytesReceived.updateAverage(numBytesRead); _parseBufferRate.increment(numBytesRead); + _parseBufferUpdateRate.increment(); return numBytesRead; } @@ -1032,6 +1046,36 @@ float AvatarData::getDataRate(const QString& rateName) { return 0.0f; } +float AvatarData::getUpdateRate(const QString& rateName) { + if (rateName == "") { + return _parseBufferUpdateRate.rate(); + } else if (rateName == "globalPosition") { + return _globalPositionUpdateRate.rate(); + } else if (rateName == "localPosition") { + return _localPositionUpdateRate.rate(); + } else if (rateName == "avatarBoundingBox") { + return _avatarBoundingBoxUpdateRate.rate(); + } else if (rateName == "avatarOrientation") { + return _avatarOrientationUpdateRate.rate(); + } else if (rateName == "avatarScale") { + return _avatarScaleUpdateRate.rate(); + } else if (rateName == "lookAtPosition") { + return _lookAtPositionUpdateRate.rate(); + } else if (rateName == "audioLoudness") { + return _audioLoudnessUpdateRate.rate(); + } else if (rateName == "sensorToWorkMatrix") { + return _sensorToWorldUpdateRate.rate(); + } else if (rateName == "additionalFlags") { + return _additionalFlagsUpdateRate.rate(); + } else if (rateName == "parentInfo") { + return _parentInfoUpdateRate.rate(); + } else if (rateName == "faceTracker") { + return _faceTrackerUpdateRate.rate(); + } else if (rateName == "jointData") { + return _jointDataUpdateRate.rate(); + } + return 0.0f; +} int AvatarData::getAverageBytesReceivedPerSecond() const { return lrint(_averageBytesReceived.getAverageSampleValuePerSecond()); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 52cf81798e..4c24cf6ea6 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -528,7 +528,8 @@ public: Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix() const; Q_INVOKABLE glm::mat4 getControllerRightHandMatrix() const; - float getDataRate(const QString& rateName = QString("")); + Q_INVOKABLE float getDataRate(const QString& rateName = QString("")); + Q_INVOKABLE float getUpdateRate(const QString& rateName = QString("")); int getJointCount() { return _jointData.size(); } @@ -644,7 +645,7 @@ protected: quint64 _lastToByteArray { 0 }; // tracks the last time we did a toByteArray - // Some rate data for incoming data + // Some rate data for incoming data in bytes RateCounter<> _parseBufferRate; RateCounter<> _globalPositionRate; RateCounter<> _localPositionRate; @@ -659,6 +660,21 @@ protected: RateCounter<> _faceTrackerRate; RateCounter<> _jointDataRate; + // Some rate data for incoming data updates + RateCounter<> _parseBufferUpdateRate; + RateCounter<> _globalPositionUpdateRate; + RateCounter<> _localPositionUpdateRate; + RateCounter<> _avatarBoundingBoxUpdateRate; + RateCounter<> _avatarOrientationUpdateRate; + RateCounter<> _avatarScaleUpdateRate; + RateCounter<> _lookAtPositionUpdateRate; + RateCounter<> _audioLoudnessUpdateRate; + RateCounter<> _sensorToWorldUpdateRate; + RateCounter<> _additionalFlagsUpdateRate; + RateCounter<> _parentInfoUpdateRate; + RateCounter<> _faceTrackerUpdateRate; + RateCounter<> _jointDataUpdateRate; + glm::vec3 _globalBoundingBoxDimensions; glm::vec3 _globalBoundingBoxOffset; diff --git a/scripts/developer/debugging/debugAvatarMixer.js b/scripts/developer/debugging/debugAvatarMixer.js index 1c11d308b8..fadab96f89 100644 --- a/scripts/developer/debugging/debugAvatarMixer.js +++ b/scripts/developer/debugging/debugAvatarMixer.js @@ -60,24 +60,24 @@ function updateOverlays() { var overlayPosition = avatar.getJointPosition("Head"); overlayPosition.y += 1.05; - var text = "--- Data from Mixer ----------------------\n" - +"All: " + AvatarManager.getAvatarDataRate(avatarID).toFixed(2) + "\n" - +" GP: " + AvatarManager.getAvatarDataRate(avatarID,"globalPosition").toFixed(2) + "\n" - +" LP: " + AvatarManager.getAvatarDataRate(avatarID,"localPosition").toFixed(2) + "\n" - +" BB: " + AvatarManager.getAvatarDataRate(avatarID,"avatarBoundingBox").toFixed(2) + "\n" - +" AO: " + AvatarManager.getAvatarDataRate(avatarID,"avatarOrientation").toFixed(2) + "\n" - +" AS: " + AvatarManager.getAvatarDataRate(avatarID,"avatarScale").toFixed(2) + "\n" - +" LA: " + AvatarManager.getAvatarDataRate(avatarID,"lookAtPosition").toFixed(2) + "\n" - +" AL: " + AvatarManager.getAvatarDataRate(avatarID,"audioLoudness").toFixed(2) + "\n" - +" SW: " + AvatarManager.getAvatarDataRate(avatarID,"sensorToWorkMatrix").toFixed(2) + "\n" - +" AF: " + AvatarManager.getAvatarDataRate(avatarID,"additionalFlags").toFixed(2) + "\n" - +" PI: " + AvatarManager.getAvatarDataRate(avatarID,"parentInfo").toFixed(2) + "\n" - +" FT: " + AvatarManager.getAvatarDataRate(avatarID,"faceTracker").toFixed(2) + "\n" - +" JD: " + AvatarManager.getAvatarDataRate(avatarID,"jointData").toFixed(2) - +"--- Simulation ----------------------\n" + var text = "--- Data from Mixer ---\n" + +"All: " + AvatarManager.getAvatarDataRate(avatarID).toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID).toFixed(2) + "hz)" + "\n" + +" GP: " + AvatarManager.getAvatarDataRate(avatarID,"globalPosition").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"globalPosition").toFixed(2) + "hz)" + "\n" + +" LP: " + AvatarManager.getAvatarDataRate(avatarID,"localPosition").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"localPosition").toFixed(2) + "hz)" + "\n" + +" BB: " + AvatarManager.getAvatarDataRate(avatarID,"avatarBoundingBox").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"avatarBoundingBox").toFixed(2) + "hz)" + "\n" + +" AO: " + AvatarManager.getAvatarDataRate(avatarID,"avatarOrientation").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"avatarOrientation").toFixed(2) + "hz)" + "\n" + +" AS: " + AvatarManager.getAvatarDataRate(avatarID,"avatarScale").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"avatarScale").toFixed(2) + "hz)" + "\n" + +" LA: " + AvatarManager.getAvatarDataRate(avatarID,"lookAtPosition").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"lookAtPosition").toFixed(2) + "hz)" + "\n" + +" AL: " + AvatarManager.getAvatarDataRate(avatarID,"audioLoudness").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"audioLoudness").toFixed(2) + "hz)" + "\n" + +" SW: " + AvatarManager.getAvatarDataRate(avatarID,"sensorToWorkMatrix").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"sensorToWorkMatrix").toFixed(2) + "hz)" + "\n" + +" AF: " + AvatarManager.getAvatarDataRate(avatarID,"additionalFlags").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"additionalFlags").toFixed(2) + "hz)" + "\n" + +" PI: " + AvatarManager.getAvatarDataRate(avatarID,"parentInfo").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"parentInfo").toFixed(2) + "hz)" + "\n" + +" FT: " + AvatarManager.getAvatarDataRate(avatarID,"faceTracker").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"faceTracker").toFixed(2) + "hz)" + "\n" + +" JD: " + AvatarManager.getAvatarDataRate(avatarID,"jointData").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"jointData").toFixed(2) + "hz)" + "\n" + +"--- Simulation ---\n" +"All: " + AvatarManager.getAvatarSimulationRate(avatarID,"avatar").toFixed(2) + "\n" +" SM: " + AvatarManager.getAvatarSimulationRate(avatarID,"skeletonModel").toFixed(2) + "\n" - +" JS: " + AvatarManager.getAvatarSimulationRate(avatarID,"jointData").toFixed(2) + "\n" + +" JD: " + AvatarManager.getAvatarSimulationRate(avatarID,"jointData").toFixed(2) + "\n" if (avatarID in debugOverlays) { // keep the overlay above the current position of this avatar @@ -90,8 +90,8 @@ function updateOverlays() { var newOverlay = Overlays.addOverlay("text3d", { position: overlayPosition, dimensions: { - x: 1, - y: 13 * 0.13 + x: 1.25, + y: 18 * 0.13 }, lineHeight: 0.1, font:{size:0.1}, From 41dc4988884cc83b9f57026802f0f5df6775a89d Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 8 Feb 2017 18:32:39 -0800 Subject: [PATCH 3/7] add inView simulation stats --- interface/src/avatar/Avatar.cpp | 5 +++++ interface/src/avatar/Avatar.h | 1 + scripts/developer/debugging/debugAvatarMixer.js | 7 ++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index a881bb960b..509f6c794a 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -307,6 +307,9 @@ bool Avatar::shouldDie() const { void Avatar::simulate(float deltaTime, bool inView) { _simulationRate.increment(); + if (inView) { + _simulationInViewRate.increment(); + } PROFILE_RANGE(simulation, "simulate"); PerformanceTimer perfTimer("simulate"); @@ -368,6 +371,8 @@ float Avatar::getSimulationRate(const QString& rateName) { return _simulationRate.rate(); } else if (rateName == "avatar") { return _simulationRate.rate(); + } else if (rateName == "avatarInView") { + return _simulationInViewRate.rate(); } else if (rateName == "skeletonModel") { return _skeletonModelSimulationRate.rate(); } else if (rateName == "jointData") { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index e0d19fcbc1..a1c081e327 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -263,6 +263,7 @@ protected: // Some rate tracking support RateCounter<> _simulationRate; + RateCounter<> _simulationInViewRate; RateCounter<> _skeletonModelSimulationRate; RateCounter<> _jointDataSimulationRate; diff --git a/scripts/developer/debugging/debugAvatarMixer.js b/scripts/developer/debugging/debugAvatarMixer.js index fadab96f89..6b5b0d810e 100644 --- a/scripts/developer/debugging/debugAvatarMixer.js +++ b/scripts/developer/debugging/debugAvatarMixer.js @@ -75,9 +75,10 @@ function updateOverlays() { +" FT: " + AvatarManager.getAvatarDataRate(avatarID,"faceTracker").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"faceTracker").toFixed(2) + "hz)" + "\n" +" JD: " + AvatarManager.getAvatarDataRate(avatarID,"jointData").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"jointData").toFixed(2) + "hz)" + "\n" +"--- Simulation ---\n" - +"All: " + AvatarManager.getAvatarSimulationRate(avatarID,"avatar").toFixed(2) + "\n" - +" SM: " + AvatarManager.getAvatarSimulationRate(avatarID,"skeletonModel").toFixed(2) + "\n" - +" JD: " + AvatarManager.getAvatarSimulationRate(avatarID,"jointData").toFixed(2) + "\n" + +"All: " + AvatarManager.getAvatarSimulationRate(avatarID,"avatar").toFixed(2) + "hz \n" + +" inView: " + AvatarManager.getAvatarSimulationRate(avatarID,"avatarInView").toFixed(2) + "hz \n" + +" SM: " + AvatarManager.getAvatarSimulationRate(avatarID,"skeletonModel").toFixed(2) + "hz \n" + +" JD: " + AvatarManager.getAvatarSimulationRate(avatarID,"jointData").toFixed(2) + "hz \n" if (avatarID in debugOverlays) { // keep the overlay above the current position of this avatar From ae071aec0d078df3a58d6d32ef19fdf79f3d13de Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 9 Feb 2017 09:52:09 -0800 Subject: [PATCH 4/7] add a bunch more stats for avatar processing --- interface/resources/qml/Stats.qml | 13 ++++++++++++- interface/src/avatar/AvatarManager.cpp | 12 ++++++++++++ interface/src/avatar/AvatarManager.h | 7 +++++++ interface/src/ui/Stats.cpp | 4 ++++ interface/src/ui/Stats.h | 6 ++++++ scripts/developer/debugging/debugAvatarMixer.js | 5 +++-- 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 086c1d15d2..faf37d5366 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -105,6 +105,14 @@ Item { visible: root.expanded text: "Asset Mbps In/Out: " + root.assetMbpsIn.toFixed(2) + "/" + root.assetMbpsOut.toFixed(2) } + StatText { + visible: root.expanded + text: "Fully Simulated Avatars: " + root.fullySimulatedAvatarCount + } + StatText { + visible: root.expanded + text: "Partially Simulated Avatars: " + root.partiallySimulatedAvatarCount + } } } @@ -217,7 +225,10 @@ Item { text: " Batch: " + root.batchFrameTime.toFixed(1) + " ms" } StatText { - text: " GPU: " + root.gpuFrameTime.toFixed(1) + " ms" + text: " GPU: " + root.gpuFrameTime.toFixed(1) + " ms" + } + StatText { + text: " Avatar: " + root.avatarSimulationTime.toFixed(1) + " ms" } StatText { text: "Triangles: " + root.triangles + diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index aff9ec3add..bc5eda60e2 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -230,6 +230,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { const uint64_t MAX_UPDATE_BUDGET = 2000; // usec uint64_t renderExpiry = startTime + RENDER_UPDATE_BUDGET; uint64_t maxExpiry = startTime + MAX_UPDATE_BUDGET; + + int fullySimulatedAvatars = 0; + int partiallySimulatedAvatars = 0; while (!sortedAvatars.empty()) { const AvatarPriority& sortData = sortedAvatars.top(); const auto& avatar = std::static_pointer_cast(sortData.avatar); @@ -258,6 +261,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { avatar->simulate(deltaTime, inView); avatar->updateRenderItem(pendingChanges); avatar->setLastRenderUpdateTime(startTime); + fullySimulatedAvatars++; } else if (now < maxExpiry) { // we've spent most of our time budget, but we still simulate() the avatar as it if were out of view // --> some avatars may freeze until their priority trickles up @@ -271,6 +275,14 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { } sortedAvatars.pop(); } + + uint64_t endSimulation = usecTimestampNow(); + int elapsedTime = endSimulation - startTime; + float elapsedFloat = (float)elapsedTime / (float)USECS_PER_MSEC; + qDebug() << "elapsedTime:" << elapsedTime << "elapsedFloat:" << elapsedFloat; + _avatarSimulationTime = elapsedFloat; + _fullySimulatedAvatars = fullySimulatedAvatars; + _partiallySimulatedAvatars = partiallySimulatedAvatars; qApp->getMain3DScene()->enqueuePendingChanges(pendingChanges); simulateAvatarFades(deltaTime); diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 00ae745c98..098d8ec34d 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -43,6 +43,10 @@ public: std::shared_ptr getMyAvatar() { return _myAvatar; } AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) override; + int getFullySimulatedAvatars() { return _fullySimulatedAvatars; } + int getPartiallySimulatedAvatars() { return _partiallySimulatedAvatars; } + float getAvatarSimulationTime() { return _avatarSimulationTime; } + void updateMyAvatar(float deltaTime); void updateOtherAvatars(float deltaTime); @@ -112,6 +116,9 @@ private: VectorOfMotionStates _motionStatesToRemoveFromPhysics; RateCounter<> _myAvatarSendRate; + int _fullySimulatedAvatars { 0 }; + int _partiallySimulatedAvatars { 0 }; + float _avatarSimulationTime { 0.0f }; }; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ff0028322c..e82f99bed2 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -121,6 +121,8 @@ void Stats::updateStats(bool force) { auto avatarManager = DependencyManager::get(); // we need to take one avatar out so we don't include ourselves STAT_UPDATE(avatarCount, avatarManager->size() - 1); + STAT_UPDATE(fullySimulatedAvatarCount, avatarManager->getFullySimulatedAvatars()); + STAT_UPDATE(partiallySimulatedAvatarCount, avatarManager->getPartiallySimulatedAvatars()); STAT_UPDATE(serverCount, (int)nodeList->size()); STAT_UPDATE(framerate, qApp->getFps()); if (qApp->getActiveDisplayPlugin()) { @@ -306,6 +308,8 @@ void Stats::updateStats(bool force) { // Update Frame timing (in ms) STAT_UPDATE(gpuFrameTime, (float)gpuContext->getFrameTimerGPUAverage()); STAT_UPDATE(batchFrameTime, (float)gpuContext->getFrameTimerBatchAverage()); + STAT_UPDATE(avatarSimulationTime, (float)avatarManager->getAvatarSimulationTime()); + STAT_UPDATE(gpuBuffers, (int)gpu::Context::getBufferGPUCount()); STAT_UPDATE(gpuBufferMemory, (int)BYTES_TO_MB(gpu::Context::getBufferGPUMemoryUsage())); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 3fe851494c..f501f4b09a 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -49,6 +49,8 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, simrate, 0) STATS_PROPERTY(int, avatarSimrate, 0) STATS_PROPERTY(int, avatarCount, 0) + STATS_PROPERTY(int, fullySimulatedAvatarCount, 0) + STATS_PROPERTY(int, partiallySimulatedAvatarCount, 0) STATS_PROPERTY(int, packetInCount, 0) STATS_PROPERTY(int, packetOutCount, 0) STATS_PROPERTY(float, mbpsIn, 0) @@ -111,6 +113,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, gpuFreeMemory, 0) STATS_PROPERTY(float, gpuFrameTime, 0) STATS_PROPERTY(float, batchFrameTime, 0) + STATS_PROPERTY(float, avatarSimulationTime, 0) public: static Stats* getInstance(); @@ -156,6 +159,8 @@ signals: void simrateChanged(); void avatarSimrateChanged(); void avatarCountChanged(); + void fullySimulatedAvatarCountChanged(); + void partiallySimulatedAvatarCountChanged(); void packetInCountChanged(); void packetOutCountChanged(); void mbpsInChanged(); @@ -216,6 +221,7 @@ signals: void gpuFreeMemoryChanged(); void gpuFrameTimeChanged(); void batchFrameTimeChanged(); + void avatarSimulationTimeChanged(); void rectifiedTextureCountChanged(); void decimatedTextureCountChanged(); diff --git a/scripts/developer/debugging/debugAvatarMixer.js b/scripts/developer/debugging/debugAvatarMixer.js index 6b5b0d810e..ebd43fc2f0 100644 --- a/scripts/developer/debugging/debugAvatarMixer.js +++ b/scripts/developer/debugging/debugAvatarMixer.js @@ -60,7 +60,8 @@ function updateOverlays() { var overlayPosition = avatar.getJointPosition("Head"); overlayPosition.y += 1.05; - var text = "--- Data from Mixer ---\n" + var text = avatarID + "\n" + +"--- Data from Mixer ---\n" +"All: " + AvatarManager.getAvatarDataRate(avatarID).toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID).toFixed(2) + "hz)" + "\n" +" GP: " + AvatarManager.getAvatarDataRate(avatarID,"globalPosition").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"globalPosition").toFixed(2) + "hz)" + "\n" +" LP: " + AvatarManager.getAvatarDataRate(avatarID,"localPosition").toFixed(2) + "kbps (" + AvatarManager.getAvatarUpdateRate(avatarID,"localPosition").toFixed(2) + "hz)" + "\n" @@ -92,7 +93,7 @@ function updateOverlays() { position: overlayPosition, dimensions: { x: 1.25, - y: 18 * 0.13 + y: 19 * 0.13 }, lineHeight: 0.1, font:{size:0.1}, From dd2ddcc291831c01d7734551f48715c707c23ebc Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 9 Feb 2017 09:57:32 -0800 Subject: [PATCH 5/7] cleanup --- interface/src/avatar/AvatarManager.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index bc5eda60e2..5a1fb7056f 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -276,11 +276,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { sortedAvatars.pop(); } - uint64_t endSimulation = usecTimestampNow(); - int elapsedTime = endSimulation - startTime; - float elapsedFloat = (float)elapsedTime / (float)USECS_PER_MSEC; - qDebug() << "elapsedTime:" << elapsedTime << "elapsedFloat:" << elapsedFloat; - _avatarSimulationTime = elapsedFloat; + _avatarSimulationTime = (float)(usecTimestampNow() - startTime) / (float)USECS_PER_MSEC; _fullySimulatedAvatars = fullySimulatedAvatars; _partiallySimulatedAvatars = partiallySimulatedAvatars; qApp->getMain3DScene()->enqueuePendingChanges(pendingChanges); From 57e0dadd65927aef0071840bed23a2b6e9472d09 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 9 Feb 2017 11:35:00 -0800 Subject: [PATCH 6/7] CR --- interface/src/avatar/Avatar.cpp | 2 +- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/AvatarManager.cpp | 9 +++++---- interface/src/avatar/AvatarManager.h | 14 +++++++------- libraries/avatars/src/AvatarData.cpp | 4 ++-- libraries/avatars/src/AvatarData.h | 4 ++-- libraries/avatars/src/AvatarHashMap.cpp | 2 +- libraries/avatars/src/AvatarHashMap.h | 6 +++--- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 509f6c794a..aa7221f4f0 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -366,7 +366,7 @@ void Avatar::simulate(float deltaTime, bool inView) { } } -float Avatar::getSimulationRate(const QString& rateName) { +float Avatar::getSimulationRate(const QString& rateName) const { if (rateName == "") { return _simulationRate.rate(); } else if (rateName == "avatar") { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index a1c081e327..5c05702e92 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -182,7 +182,7 @@ public: void animateScaleChanges(float deltaTime); void setTargetScale(float targetScale) override; - Q_INVOKABLE float getSimulationRate(const QString& rateName = QString("")); + Q_INVOKABLE float getSimulationRate(const QString& rateName = QString("")) const; public slots: diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 5a1fb7056f..c3fc974365 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -132,17 +132,17 @@ void AvatarManager::updateMyAvatar(float deltaTime) { Q_LOGGING_CATEGORY(trace_simulation_avatar, "trace.simulation.avatar"); -float AvatarManager::getAvatarDataRate(const QUuid& sessionID, const QString& rateName) { +float AvatarManager::getAvatarDataRate(const QUuid& sessionID, const QString& rateName) const { auto avatar = getAvatarBySessionID(sessionID); return avatar ? avatar->getDataRate(rateName) : 0.0f; } -float AvatarManager::getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName) { +float AvatarManager::getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName) const { auto avatar = getAvatarBySessionID(sessionID); return avatar ? avatar->getUpdateRate(rateName) : 0.0f; } -float AvatarManager::getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName) { +float AvatarManager::getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName) const { auto avatar = std::static_pointer_cast(getAvatarBySessionID(sessionID)); return avatar ? avatar->getSimulationRate(rateName) : 0.0f; } @@ -267,6 +267,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { // --> some avatars may freeze until their priority trickles up const bool inView = false; avatar->simulate(deltaTime, inView); + partiallySimulatedAvatars++; } else { // we've spent ALL of our time budget --> bail on the rest of the avatar updates // --> some scale or fade animations may glitch @@ -512,7 +513,7 @@ void AvatarManager::updateAvatarRenderStatus(bool shouldRenderAvatars) { } -AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) { +AvatarSharedPointer AvatarManager::getAvatarBySessionID(const QUuid& sessionID) const { if (sessionID == AVATAR_SELF_ID || sessionID == _myAvatar->getSessionUUID()) { return _myAvatar; } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 098d8ec34d..4d503842b9 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -41,11 +41,11 @@ public: void init(); std::shared_ptr getMyAvatar() { return _myAvatar; } - AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) override; + AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const override; - int getFullySimulatedAvatars() { return _fullySimulatedAvatars; } - int getPartiallySimulatedAvatars() { return _partiallySimulatedAvatars; } - float getAvatarSimulationTime() { return _avatarSimulationTime; } + int getFullySimulatedAvatars() const { return _fullySimulatedAvatars; } + int getPartiallySimulatedAvatars() const { return _partiallySimulatedAvatars; } + float getAvatarSimulationTime() const { return _avatarSimulationTime; } void updateMyAvatar(float deltaTime); void updateOtherAvatars(float deltaTime); @@ -73,9 +73,9 @@ public: void handleOutgoingChanges(const VectorOfMotionStates& motionStates); void handleCollisionEvents(const CollisionEvents& collisionEvents); - Q_INVOKABLE float getAvatarDataRate(const QUuid& sessionID, const QString& rateName = QString("")); - Q_INVOKABLE float getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName = QString("")); - Q_INVOKABLE float getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName = QString("")); + Q_INVOKABLE float getAvatarDataRate(const QUuid& sessionID, const QString& rateName = QString("")) const; + Q_INVOKABLE float getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName = QString("")) const; + Q_INVOKABLE float getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName = QString("")) const; Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray, const QScriptValue& avatarIdsToInclude = QScriptValue(), diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index aaf5a639a6..af060429af 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -1064,7 +1064,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) { return numBytesRead; } -float AvatarData::getDataRate(const QString& rateName) { +float AvatarData::getDataRate(const QString& rateName) const { if (rateName == "") { return _parseBufferRate.rate() / BYTES_PER_KILOBIT; } else if (rateName == "globalPosition") { @@ -1119,7 +1119,7 @@ float AvatarData::getDataRate(const QString& rateName) { return 0.0f; } -float AvatarData::getUpdateRate(const QString& rateName) { +float AvatarData::getUpdateRate(const QString& rateName) const { if (rateName == "") { return _parseBufferUpdateRate.rate(); } else if (rateName == "globalPosition") { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index d23e4f5caf..01cab8b93a 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -547,8 +547,8 @@ public: Q_INVOKABLE glm::mat4 getControllerLeftHandMatrix() const; Q_INVOKABLE glm::mat4 getControllerRightHandMatrix() const; - Q_INVOKABLE float getDataRate(const QString& rateName = QString("")); - Q_INVOKABLE float getUpdateRate(const QString& rateName = QString("")); + Q_INVOKABLE float getDataRate(const QString& rateName = QString("")) const; + Q_INVOKABLE float getUpdateRate(const QString& rateName = QString("")) const; int getJointCount() { return _jointData.size(); } diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 9d43bf438b..00c515a635 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -90,7 +90,7 @@ AvatarSharedPointer AvatarHashMap::newOrExistingAvatar(const QUuid& sessionUUID, return avatar; } -AvatarSharedPointer AvatarHashMap::findAvatar(const QUuid& sessionUUID) { +AvatarSharedPointer AvatarHashMap::findAvatar(const QUuid& sessionUUID) const { QReadLocker locker(&_hashLock); if (_avatarHash.contains(sessionUUID)) { return _avatarHash.value(sessionUUID); diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index eae4026bfc..dd097aef22 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -40,7 +40,7 @@ public: Q_INVOKABLE QVector getAvatarIdentifiers(); Q_INVOKABLE AvatarData* getAvatar(QUuid avatarID); - virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) { return findAvatar(sessionID); } + virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const { return findAvatar(sessionID); } int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters); signals: @@ -65,7 +65,7 @@ protected: virtual AvatarSharedPointer newSharedAvatar(); virtual AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer); AvatarSharedPointer newOrExistingAvatar(const QUuid& sessionUUID, const QWeakPointer& mixerWeakPointer); - virtual AvatarSharedPointer findAvatar(const QUuid& sessionUUID); // uses a QReadLocker on the hashLock + virtual AvatarSharedPointer findAvatar(const QUuid& sessionUUID) const; // uses a QReadLocker on the hashLock virtual void removeAvatar(const QUuid& sessionUUID, KillAvatarReason removalReason = KillAvatarReason::NoReason); virtual void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar, KillAvatarReason removalReason = KillAvatarReason::NoReason); @@ -73,7 +73,7 @@ protected: AvatarHash _avatarHash; // "Case-based safety": Most access to the _avatarHash is on the same thread. Write access is protected by a write-lock. // If you read from a different thread, you must read-lock the _hashLock. (Scripted write access is not supported). - QReadWriteLock _hashLock; + mutable QReadWriteLock _hashLock; private: QUuid _lastOwnerSessionUUID; From bb4654506a18c87838c8595477c59cc4d3c0be8d Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 9 Feb 2017 11:37:21 -0800 Subject: [PATCH 7/7] CR --- interface/src/avatar/Avatar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index aa7221f4f0..ab97f563f6 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -306,12 +306,14 @@ bool Avatar::shouldDie() const { } void Avatar::simulate(float deltaTime, bool inView) { + PROFILE_RANGE(simulation, "simulate"); + _simulationRate.increment(); if (inView) { _simulationInViewRate.increment(); } - PROFILE_RANGE(simulation, "simulate"); + PerformanceTimer perfTimer("simulate"); { PROFILE_RANGE(simulation, "updateJoints");