add edit times and entity ids to the viewer stats

This commit is contained in:
Brad Hefta-Gaub 2015-12-02 14:37:41 -08:00
parent 08ba535c38
commit 1e51a90204
6 changed files with 43 additions and 18 deletions

View file

@ -267,9 +267,14 @@ void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectio
tree->setWantTerseEditLogging(wantTerseEditLogging);
}
void EntityServer::trackSend(const QUuid& dataID, const QUuid& viewerNode) {
// FIXME - this stats tracking is somewhat temporary to debug the Whiteboard issues. It's not a bad
// set of stats to have, but we'd probably want a different data-structure if we keep it very long.
// Since this version uses a single shared QMap for all senders, there can be a fair amount of lock
// contention on this QWriteLocker
void EntityServer::trackSend(const QUuid& dataID, quint64 dataLastEdited, const QUuid& viewerNode) {
QWriteLocker locker(&_viewerSendingStatsLock);
_viewerSendingStats[viewerNode] = usecTimestampNow();
_viewerSendingStats[viewerNode][dataID] = { usecTimestampNow(), dataLastEdited };
}
@ -284,7 +289,8 @@ QString EntityServer::serverSubclassStats() {
statsString += "\r\n\r\n";
statsString += "<b>Entity Server Sending to Viewer Statistics</b>\r\n";
statsString += "----- Viewer Node ID ----------------- ---------- Last Sent To ----------\r\n";
statsString += "----- Viewer Node ID ----------------- ----- Entity ID ---------------------- "
"---------- Last Sent To ---------- ---------- Last Edited -----------\r\n";
int viewers = 0;
const int COLUMN_WIDTH = 24;
@ -293,15 +299,28 @@ QString EntityServer::serverSubclassStats() {
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, ' '));
for (auto viewerID : _viewerSendingStats.keys()) {
statsString += viewerID.toString() + "\r\n";
auto viewerData = _viewerSendingStats[viewerID];
for (auto entityID : viewerData.keys()) {
ViewerSendingStats stats = viewerData[entityID];
quint64 elapsedSinceSent = now - stats.lastSent;
double sentMsecsAgo = (double)(elapsedSinceSent / USECS_PER_MSEC);
quint64 elapsedSinceEdit = now - stats.lastEdited;
double editMsecsAgo = (double)(elapsedSinceEdit / USECS_PER_MSEC);
statsString += " "; // the viewerID spacing
statsString += entityID.toString();
statsString += " ";
statsString += QString("%1 msecs ago")
.arg(locale.toString((double)sentMsecsAgo).rightJustified(COLUMN_WIDTH, ' '));
statsString += QString("%1 msecs ago")
.arg(locale.toString((double)editMsecsAgo).rightJustified(COLUMN_WIDTH, ' '));
statsString += "\r\n";
}
viewers++;
}
}

View file

@ -21,6 +21,12 @@
#include "EntityTree.h"
/// Handles assignments of type EntityServer - sending entities to various clients.
struct ViewerSendingStats {
quint64 lastSent;
quint64 lastEdited;
};
class EntityServer : public OctreeServer, public NewlyCreatedEntityHook {
Q_OBJECT
public:
@ -46,7 +52,7 @@ public:
virtual void readAdditionalConfiguration(const QJsonObject& settingsSectionObject) override;
virtual QString serverSubclassStats();
virtual void trackSend(const QUuid& dataID, const QUuid& viewerNode);
virtual void trackSend(const QUuid& dataID, quint64 dataLastEdited, const QUuid& viewerNode);
public slots:
void pruneDeletedEntities();
@ -62,7 +68,7 @@ private:
QTimer* _pruneDeletedEntitiesTimer = nullptr;
QReadWriteLock _viewerSendingStatsLock;
QMap<QUuid,quint64> _viewerSendingStats;
QMap<QUuid, QMap<QUuid, ViewerSendingStats>> _viewerSendingStats;
};
#endif // hifi_EntityServer_h

View file

@ -469,8 +469,8 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
// 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);
params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) {
_myServer->trackSend(dataID, dataEdited, _nodeUUID);
};
// TODO: should this include the lock time or not? This stat is sent down to the client,

View file

@ -80,7 +80,7 @@ public:
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) { }
virtual void trackSend(const QUuid& dataID, quint64 dataLastEdited, const QUuid& viewerNode) { }
static float SKIP_TIME; // use this for trackXXXTime() calls for non-times

View file

@ -313,7 +313,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
// if any part of our entity was sent, call trackSend
if (appendState != OctreeElement::NONE) {
params.trackSend(getID());
params.trackSend(getID(), getLastEdited());
}
return appendState;

View file

@ -177,7 +177,7 @@ public:
}
}
std::function<void(const QUuid&)> trackSend { [](const QUuid&){} };
std::function<void(const QUuid& dataID, quint64 itemLastEdited)> trackSend { [](const QUuid&, quint64){} };
};
class ReadElementBufferToTreeArgs {