From 08ba535c384a62a09ca67583409405694038e9df Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 2 Dec 2015 13:43:05 -0800 Subject: [PATCH] add some basic send tracking --- .../src/entities/EntityServer.cpp | 46 +++++++++++++++++++ assignment-client/src/entities/EntityServer.h | 6 +++ .../src/octree/OctreeSendThread.cpp | 6 +++ assignment-client/src/octree/OctreeServer.cpp | 5 ++ assignment-client/src/octree/OctreeServer.h | 2 + libraries/entities/src/EntityItem.cpp | 5 ++ libraries/octree/src/Octree.h | 2 + 7 files changed, 72 insertions(+) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 6508f09f72..28e852af6a 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -266,3 +266,49 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio tree->setWantEditLogging(wantEditLogging); tree->setWantTerseEditLogging(wantTerseEditLogging); } + +void EntityServer::trackSend(const QUuid& dataID, const QUuid& viewerNode) { + QWriteLocker locker(&_viewerSendingStatsLock); + _viewerSendingStats[viewerNode] = usecTimestampNow(); +} + + +QString EntityServer::serverSubclassStats() { + QLocale locale(QLocale::English); + QString statsString; + + // display memory usage stats + statsString += "Entity Server Memory Statistics\r\n"; + statsString += QString().sprintf("EntityTreeElement size... %ld bytes\r\n", sizeof(EntityTreeElement)); + statsString += QString().sprintf(" EntityItem size... %ld bytes\r\n", sizeof(EntityItem)); + statsString += "\r\n\r\n"; + + statsString += "Entity Server Sending to Viewer Statistics\r\n"; + statsString += "----- Viewer Node ID ----------------- ---------- Last Sent To ----------\r\n"; + + int viewers = 0; + const int COLUMN_WIDTH = 24; + + { + QReadLocker locker(&_viewerSendingStatsLock); + quint64 now = usecTimestampNow(); + + for (auto key : _viewerSendingStats.keys()) { + quint64 lastSentAt = _viewerSendingStats[key]; + quint64 elapsed = now - lastSentAt; + double msecsAgo = (double)(elapsed / USECS_PER_MSEC); + statsString += key.toString(); + statsString += " "; + statsString += QString("%1 msecs ago\r\n") + .arg(locale.toString((double)msecsAgo).rightJustified(COLUMN_WIDTH, ' ')); + + viewers++; + } + } + if (viewers < 1) { + statsString += " no viewers... \r\n"; + } + statsString += "\r\n\r\n"; + + return statsString; +} diff --git a/assignment-client/src/entities/EntityServer.h b/assignment-client/src/entities/EntityServer.h index d9795316c4..ab7ca038cf 100644 --- a/assignment-client/src/entities/EntityServer.h +++ b/assignment-client/src/entities/EntityServer.h @@ -44,6 +44,9 @@ public: virtual void entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) override; virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) override; + virtual QString serverSubclassStats(); + + virtual void trackSend(const QUuid& dataID, const QUuid& viewerNode); public slots: void pruneDeletedEntities(); @@ -57,6 +60,9 @@ private slots: private: EntitySimulation* _entitySimulation; QTimer* _pruneDeletedEntitiesTimer = nullptr; + + QReadWriteLock _viewerSendingStatsLock; + QMap _viewerSendingStats; }; #endif // hifi_EntityServer_h diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 94d82b463e..fc3731f063 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -467,6 +467,12 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus isFullScene, &nodeData->stats, _myServer->getJurisdiction(), &nodeData->extraEncodeData); + // Our trackSend() function is implemented by the server subclass, and will be called back + // during the encodeTreeBitstream() as new entities/data elements are sent + params.trackSend = [this](const QUuid& id) { + _myServer->trackSend(id, _nodeUUID); + }; + // TODO: should this include the lock time or not? This stat is sent down to the client, // it seems like it may be a good idea to include the lock time as part of the encode time // are reported to client. Since you can encode without the lock diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 7cd3e59edf..c5072d0175 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -821,6 +821,11 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url .arg(locale.toString((uint)checkSum).rightJustified(16, ' ')); statsString += "\r\n\r\n"; + + statsString += serverSubclassStats(); + + statsString += "\r\n\r\n"; + statsString += "\r\n"; statsString += ""; diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 1aea9c960e..6c11a53bd2 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -79,6 +79,8 @@ public: virtual void beforeRun() { } virtual bool hasSpecialPacketsToSend(const SharedNodePointer& node) { return false; } virtual int sendSpecialPackets(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) { return 0; } + virtual QString serverSubclassStats() { return QString(); } + virtual void trackSend(const QUuid& dataID, const QUuid& viewerNode) { } static float SKIP_TIME; // use this for trackXXXTime() calls for non-times diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index a70a8c0428..cde1012fb0 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -311,6 +311,11 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet entityTreeElementExtraEncodeData->entities.insert(getEntityItemID(), propertiesDidntFit); } + // if any part of our entity was sent, call trackSend + if (appendState != OctreeElement::NONE) { + params.trackSend(getID()); + } + return appendState; } diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index d9cf17d7de..118ea79b6e 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -176,6 +176,8 @@ public: case OCCLUDED: return QString("OCCLUDED"); break; } } + + std::function trackSend { [](const QUuid&){} }; }; class ReadElementBufferToTreeArgs {