From 12becb9d19777de3f63c2365bc81de140d853305 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 11 Mar 2014 16:22:35 -0700 Subject: [PATCH] improve octree stats display --- interface/src/ui/OctreeStatsDialog.cpp | 57 ++++++----- libraries/octree/src/Octree.cpp | 2 - libraries/octree/src/OctreeSceneStats.cpp | 114 +++++++++++++++++++--- libraries/octree/src/OctreeSceneStats.h | 22 ++++- libraries/voxels/src/VoxelTree.cpp | 2 - 5 files changed, 152 insertions(+), 45 deletions(-) diff --git a/interface/src/ui/OctreeStatsDialog.cpp b/interface/src/ui/OctreeStatsDialog.cpp index 974964da04..92578b6b34 100644 --- a/interface/src/ui/OctreeStatsDialog.cpp +++ b/interface/src/ui/OctreeStatsDialog.cpp @@ -157,9 +157,9 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { statsValue.str(""); statsValue << - "Total: " << localTotalString.toLocal8Bit().constData() << " / " << - "Internal: " << localInternalString.toLocal8Bit().constData() << " / " << - "Leaves: " << localLeavesString.toLocal8Bit().constData() << ""; + "Total: " << qPrintable(localTotalString) << " / " << + "Internal: " << qPrintable(localInternalString) << " / " << + "Leaves: " << qPrintable(localLeavesString) << ""; label->setText(statsValue.str().c_str()); // iterate all the current voxel stats, and list their sending modes, total their voxels, etc... @@ -212,9 +212,9 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) { label = _labels[_serverVoxels]; statsValue.str(""); statsValue << - "Total: " << serversTotalString.toLocal8Bit().constData() << " / " << - "Internal: " << serversInternalString.toLocal8Bit().constData() << " / " << - "Leaves: " << serversLeavesString.toLocal8Bit().constData() << ""; + "Total: " << qPrintable(serversTotalString) << " / " << + "Internal: " << qPrintable(serversInternalString) << " / " << + "Leaves: " << qPrintable(serversLeavesString) << ""; label->setText(statsValue.str().c_str()); showAllOctreeServers(); @@ -290,7 +290,7 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser AABox serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); serverBounds.scale(TREE_SCALE); serverDetails << " jurisdiction: " - << rootCodeHex.toLocal8Bit().constData() + << qPrintable(rootCodeHex) << " [" << rootDetails.x << ", " << rootDetails.y << ", " @@ -320,8 +320,8 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser QString lastFullSendString = locale.toString(lastFullSend); extraDetails << "
" << "Last Full Scene... " << - "Encode Time: " << lastFullEncodeString.toLocal8Bit().constData() << " ms " << - "Send Time: " << lastFullSendString.toLocal8Bit().constData() << " ms "; + "Encode Time: " << qPrintable(lastFullEncodeString) << " ms " << + "Send Time: " << qPrintable(lastFullSendString) << " ms "; for (int i = 0; i < OctreeSceneStats::ITEM_COUNT; i++) { OctreeSceneStats::Item item = (OctreeSceneStats::Item)(i); @@ -334,42 +334,51 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser QString internalString = locale.toString((uint)stats.getTotalInternal()); QString leavesString = locale.toString((uint)stats.getTotalLeaves()); - serverDetails << "
" << "Node UUID: " << - nodeUUID.toString().toLocal8Bit().constData() << " "; + serverDetails << "
" << "Node UUID: " << qPrintable(nodeUUID.toString()) << " "; serverDetails << "
" << "Voxels: " << - totalString.toLocal8Bit().constData() << " total " << - internalString.toLocal8Bit().constData() << " internal " << - leavesString.toLocal8Bit().constData() << " leaves "; + qPrintable(totalString) << " total " << + qPrintable(internalString) << " internal " << + qPrintable(leavesString) << " leaves "; QString incomingPacketsString = locale.toString((uint)stats.getIncomingPackets()); QString incomingBytesString = locale.toString((uint)stats.getIncomingBytes()); QString incomingWastedBytesString = locale.toString((uint)stats.getIncomingWastedBytes()); QString incomingOutOfOrderString = locale.toString((uint)stats.getIncomingOutOfOrder()); + QString incomingLateString = locale.toString((uint)stats.getIncomingLate()); + QString incomingReallyLateString = locale.toString((uint)stats.getIncomingReallyLate()); + QString incomingEarlyString = locale.toString((uint)stats.getIncomingEarly()); QString incomingLikelyLostString = locale.toString((uint)stats.getIncomingLikelyLost()); + QString incomingRecovered = locale.toString((uint)stats.getIncomingRecovered()); + QString incomingDuplicateString = locale.toString((uint)stats.getIncomingPossibleDuplicate()); int clockSkewInMS = node->getClockSkewUsec() / (int)USECS_PER_MSEC; QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage()); QString incomingPingTimeString = locale.toString(node->getPingMs()); QString incomingClockSkewString = locale.toString(clockSkewInMS); - serverDetails << "
" << "Incoming Packets: " << - incomingPacketsString.toLocal8Bit().constData() << - " Out of Order: " << incomingOutOfOrderString.toLocal8Bit().constData() << - " Likely Lost: " << incomingLikelyLostString.toLocal8Bit().constData(); + serverDetails << "
" << "Incoming Packets: " << qPrintable(incomingPacketsString) << + "/ Lost: " << qPrintable(incomingLikelyLostString) << + "/ Recovered: " << qPrintable(incomingRecovered); + + serverDetails << "
" << " Out of Order: " << qPrintable(incomingOutOfOrderString) << + "/ Early: " << qPrintable(incomingEarlyString) << + "/ Late: " << qPrintable(incomingLateString) << + "/ Really Late: " << qPrintable(incomingReallyLateString) << + "/ Duplicate: " << qPrintable(incomingDuplicateString); serverDetails << "
" << - " Average Flight Time: " << incomingFlightTimeString.toLocal8Bit().constData() << " msecs"; + " Average Flight Time: " << qPrintable(incomingFlightTimeString) << " msecs"; serverDetails << "
" << - " Average Ping Time: " << incomingPingTimeString.toLocal8Bit().constData() << " msecs"; + " Average Ping Time: " << qPrintable(incomingPingTimeString) << " msecs"; serverDetails << "
" << - " Average Clock Skew: " << incomingClockSkewString.toLocal8Bit().constData() << " msecs"; - + " Average Clock Skew: " << qPrintable(incomingClockSkewString) << " msecs"; + serverDetails << "
" << "Incoming" << - " Bytes: " << incomingBytesString.toLocal8Bit().constData() << - " Wasted Bytes: " << incomingWastedBytesString.toLocal8Bit().constData(); + " Bytes: " << qPrintable(incomingBytesString) << + " Wasted Bytes: " << qPrintable(incomingWastedBytesString); serverDetails << extraDetails.str(); if (_extraServerDetails[serverCount-1] == MORE) { diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index f85ed7f487..4c8ed8c9f6 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -15,8 +15,6 @@ #include #include // to load voxels from file -#include - #include #include "CoverageMap.h" diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 794884334f..7d1f3f0cec 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -30,8 +30,13 @@ OctreeSceneStats::OctreeSceneStats() : _incomingBytes(0), _incomingWastedBytes(0), _incomingLastSequence(0), - _incomingOutOfOrder(0), _incomingLikelyLost(0), + _incomingRecovered(0), + _incomingEarly(0), + _incomingLate(0), + _incomingReallyLate(0), + _incomingPossibleDuplicate(0), + _missingSequenceNumbers(), _incomingFlightTimeAverage(samples), _jurisdictionRoot(NULL) { @@ -134,8 +139,14 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) { _incomingBytes = other._incomingBytes; _incomingWastedBytes = other._incomingWastedBytes; _incomingLastSequence = other._incomingLastSequence; - _incomingOutOfOrder = other._incomingOutOfOrder; _incomingLikelyLost = other._incomingLikelyLost; + _incomingRecovered = other._incomingRecovered; + _incomingEarly = other._incomingEarly; + _incomingLate = other._incomingLate; + _incomingReallyLate = other._incomingReallyLate; + _incomingPossibleDuplicate = other._incomingPossibleDuplicate; + + _missingSequenceNumbers = other._missingSequenceNumbers; } @@ -823,18 +834,95 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, float flightTimeMsecs = flightTime / USECS_PER_MSEC; _incomingFlightTimeAverage.updateAverage(flightTimeMsecs); + // track out of order and possibly lost packets... + const bool wantExtraDebugging = false; + if (sequence == _incomingLastSequence) { + if (wantExtraDebugging) { + qDebug() << "last packet duplicate got:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; + } + } else { + OCTREE_PACKET_SEQUENCE expected = _incomingLastSequence+1; + if (sequence != expected) { + if (wantExtraDebugging) { + qDebug() << "out of order... got:" << sequence << "expected:" << expected; + } + + // if the sequence is less than our expected, then this might be a packet + // that was delayed and so we should find it in our lostSequence list + if (sequence < expected) { + if (wantExtraDebugging) { + qDebug() << "this packet is later than expected..."; + } + if (sequence < std::max(0, (expected - MAX_MISSING_SEQUENCE_OLD_AGE))) { + _incomingReallyLate++; + } else { + _incomingLate++; + } + + if (_missingSequenceNumbers.contains(sequence)) { + if (wantExtraDebugging) { + qDebug() << "found it in _missingSequenceNumbers"; + } + _missingSequenceNumbers.remove(sequence); + _incomingLikelyLost--; + _incomingRecovered++; + } else { + // if we're still in our pruning window, and we didn't find it in our missing list, + // than this is really unexpected and can probably only happen if the packet was a + // duplicate + if (sequence >= std::max(0, (expected - MAX_MISSING_SEQUENCE_OLD_AGE))) { + if (wantExtraDebugging) { + qDebug() << "sequence:" << sequence << "WAS NOT found in _missingSequenceNumbers, and not that old... (expected - MAX_MISSING_SEQUENCE_OLD_AGE):" << (expected - MAX_MISSING_SEQUENCE_OLD_AGE); + } + _incomingPossibleDuplicate++; + } + } + } + + if (sequence > expected) { + if (wantExtraDebugging) { + qDebug() << "this packet is earlier than expected..."; + } + _incomingEarly++; + + // hmm... so, we either didn't get some packets, or this guy came early... + unsigned int missing = sequence - expected; + if (wantExtraDebugging) { + qDebug() << ">>>>>>>> missing gap=" << missing; + } + _incomingLikelyLost += missing; + for(unsigned int missingSequence = expected; missingSequence < sequence; missingSequence++) { + _missingSequenceNumbers << missingSequence; + } + } + } + } + + // only bump the last sequence if it was greater than our previous last sequence, this will keep us from + // accidentally going backwards when an out of order (recovered) packet comes in + if (sequence > _incomingLastSequence) { + _incomingLastSequence = sequence; + } - // detect out of order packets - if (sequence < _incomingLastSequence) { - _incomingOutOfOrder++; + // do some garbage collecting on our _missingSequenceNumbers + if (_missingSequenceNumbers.size() > MAX_MISSING_SEQUENCE) { + if (wantExtraDebugging) { + qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size(); + } + foreach(unsigned int missingItem, _missingSequenceNumbers) { + if (wantExtraDebugging) { + qDebug() << "checking item:" << missingItem << "is it in need of pruning?"; + qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):" + << (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE); + } + if (missingItem <= std::max(0, (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE))) { + if (wantExtraDebugging) { + qDebug() << "pruning really old missing sequence:" << missingItem; + } + _missingSequenceNumbers.remove(missingItem); + } + } } - - // detect likely lost packets - OCTREE_PACKET_SEQUENCE expected = _incomingLastSequence+1; - if (sequence > expected) { - _incomingLikelyLost++; - } - - _incomingLastSequence = sequence; + } diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index e106f53589..25bc5e2c21 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -159,8 +159,13 @@ public: unsigned int getIncomingPackets() const { return _incomingPacket; } unsigned long getIncomingBytes() const { return _incomingBytes; } unsigned long getIncomingWastedBytes() const { return _incomingWastedBytes; } - unsigned int getIncomingOutOfOrder() const { return _incomingOutOfOrder; } + unsigned int getIncomingOutOfOrder() const { return _incomingLate + _incomingEarly; } unsigned int getIncomingLikelyLost() const { return _incomingLikelyLost; } + unsigned int getIncomingRecovered() const { return _incomingRecovered; } + unsigned int getIncomingEarly() const { return _incomingEarly; } + unsigned int getIncomingLate() const { return _incomingLate; } + unsigned int getIncomingReallyLate() const { return _incomingReallyLate; } + unsigned int getIncomingPossibleDuplicate() const { return _incomingPossibleDuplicate; } float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); } private: @@ -251,9 +256,18 @@ private: unsigned int _incomingPacket; unsigned long _incomingBytes; unsigned long _incomingWastedBytes; - unsigned int _incomingLastSequence; - unsigned int _incomingOutOfOrder; - unsigned int _incomingLikelyLost; + + const uint16_t MAX_MISSING_SEQUENCE = 100; /// how many items in our _missingSequenceNumbers before we start to prune them + const uint16_t MAX_MISSING_SEQUENCE_OLD_AGE = 1000; /// age we allow items in _missingSequenceNumbers to be before pruning + + uint16_t _incomingLastSequence; /// last incoming sequence number + unsigned int _incomingLikelyLost; /// count of packets likely lost, may be off by _incomingReallyLate count + unsigned int _incomingRecovered; /// packets that were late, and we had in our missing list, we consider recovered + unsigned int _incomingEarly; /// out of order earlier than expected + unsigned int _incomingLate; /// out of order later than expected + unsigned int _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late + unsigned int _incomingPossibleDuplicate; /// out of order possibly a duplicate + QSet _missingSequenceNumbers; SimpleMovingAverage _incomingFlightTimeAverage; // features related items diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 4c756c2257..5c48244a39 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -8,8 +8,6 @@ #include -#include - #include #include #include