mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 11:13:09 +02:00
fixed >100% loss rate bug in SequenceNumberStats
This commit is contained in:
parent
c4751d7dd7
commit
e1f905cb36
6 changed files with 73 additions and 65 deletions
|
@ -1424,9 +1424,9 @@ void Audio::renderAudioStreamStats(const AudioStreamStats& streamStats, int hori
|
||||||
|
|
||||||
sprintf(stringBuffer, " Packet loss | overall: %5.2f%% (%d lost), last_30s: %5.2f%% (%d lost)",
|
sprintf(stringBuffer, " Packet loss | overall: %5.2f%% (%d lost), last_30s: %5.2f%% (%d lost)",
|
||||||
streamStats._packetStreamStats.getLostRate() * 100.0f,
|
streamStats._packetStreamStats.getLostRate() * 100.0f,
|
||||||
streamStats._packetStreamStats._numLost,
|
streamStats._packetStreamStats._lost,
|
||||||
streamStats._packetStreamWindowStats.getLostRate() * 100.0f,
|
streamStats._packetStreamWindowStats.getLostRate() * 100.0f,
|
||||||
streamStats._packetStreamWindowStats._numLost);
|
streamStats._packetStreamWindowStats._lost);
|
||||||
verticalOffset += STATS_HEIGHT_PER_LINE;
|
verticalOffset += STATS_HEIGHT_PER_LINE;
|
||||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, stringBuffer, color);
|
drawText(horizontalOffset, verticalOffset, scale, rotation, font, stringBuffer, color);
|
||||||
|
|
||||||
|
|
|
@ -366,13 +366,13 @@ void OctreeStatsDialog::showOctreeServersOfType(int& serverCount, NodeType_t ser
|
||||||
QString incomingBytesString = locale.toString((uint)stats.getIncomingBytes());
|
QString incomingBytesString = locale.toString((uint)stats.getIncomingBytes());
|
||||||
QString incomingWastedBytesString = locale.toString((uint)stats.getIncomingWastedBytes());
|
QString incomingWastedBytesString = locale.toString((uint)stats.getIncomingWastedBytes());
|
||||||
const SequenceNumberStats& seqStats = stats.getIncomingOctreeSequenceNumberStats();
|
const SequenceNumberStats& seqStats = stats.getIncomingOctreeSequenceNumberStats();
|
||||||
QString incomingOutOfOrderString = locale.toString((uint)seqStats.getNumOutOfOrder());
|
QString incomingOutOfOrderString = locale.toString((uint)seqStats.getOutOfOrder());
|
||||||
QString incomingLateString = locale.toString((uint)seqStats.getNumLate());
|
QString incomingLateString = locale.toString((uint)seqStats.getLate());
|
||||||
QString incomingUnreasonableString = locale.toString((uint)seqStats.getNumUnreasonable());
|
QString incomingUnreasonableString = locale.toString((uint)seqStats.getUnreasonable());
|
||||||
QString incomingEarlyString = locale.toString((uint)seqStats.getNumEarly());
|
QString incomingEarlyString = locale.toString((uint)seqStats.getEarly());
|
||||||
QString incomingLikelyLostString = locale.toString((uint)seqStats.getNumLost());
|
QString incomingLikelyLostString = locale.toString((uint)seqStats.getLost());
|
||||||
QString incomingRecovered = locale.toString((uint)seqStats.getNumRecovered());
|
QString incomingRecovered = locale.toString((uint)seqStats.getRecovered());
|
||||||
QString incomingDuplicateString = locale.toString((uint)seqStats.getNumDuplicate());
|
QString incomingDuplicateString = locale.toString((uint)seqStats.getDuplicate());
|
||||||
|
|
||||||
int clockSkewInMS = node->getClockSkewUsec() / (int)USECS_PER_MSEC;
|
int clockSkewInMS = node->getClockSkewUsec() / (int)USECS_PER_MSEC;
|
||||||
QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage());
|
QString incomingFlightTimeString = locale.toString((int)stats.getIncomingFlightTimeAverage());
|
||||||
|
|
|
@ -212,7 +212,7 @@ SequenceNumberStats::ArrivalInfo InboundAudioStream::frameReceivedUpdateNetworkS
|
||||||
// discard the first few packets we receive since they usually have gaps that aren't represensative of normal jitter
|
// discard the first few packets we receive since they usually have gaps that aren't represensative of normal jitter
|
||||||
const int NUM_INITIAL_PACKETS_DISCARD = 3;
|
const int NUM_INITIAL_PACKETS_DISCARD = 3;
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
if (_incomingSequenceNumberStats.getNumReceived() > NUM_INITIAL_PACKETS_DISCARD) {
|
if (_incomingSequenceNumberStats.getReceived() > NUM_INITIAL_PACKETS_DISCARD) {
|
||||||
quint64 gap = now - _lastFrameReceivedTime;
|
quint64 gap = now - _lastFrameReceivedTime;
|
||||||
_interframeTimeGapStatsForStatsPacket.update(gap);
|
_interframeTimeGapStatsForStatsPacket.update(gap);
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ public:
|
||||||
int getSilentFramesDropped() const { return _silentFramesDropped; }
|
int getSilentFramesDropped() const { return _silentFramesDropped; }
|
||||||
int getOverflowCount() const { return _ringBuffer.getOverflowCount(); }
|
int getOverflowCount() const { return _ringBuffer.getOverflowCount(); }
|
||||||
|
|
||||||
int getPacketReceived() const { return _incomingSequenceNumberStats.getNumReceived(); }
|
int getPacketsReceived() const { return _incomingSequenceNumberStats.getReceived(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void starved();
|
void starved();
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
SequenceNumberStats::SequenceNumberStats(int statsHistoryLength)
|
SequenceNumberStats::SequenceNumberStats(int statsHistoryLength)
|
||||||
: _lastReceived(std::numeric_limits<quint16>::max()),
|
: _received(0),
|
||||||
|
_lastReceivedSequence(0),
|
||||||
_missingSet(),
|
_missingSet(),
|
||||||
_stats(),
|
_stats(),
|
||||||
_lastSenderUUID(),
|
_lastSenderUUID(),
|
||||||
|
@ -23,8 +24,10 @@ SequenceNumberStats::SequenceNumberStats(int statsHistoryLength)
|
||||||
}
|
}
|
||||||
|
|
||||||
void SequenceNumberStats::reset() {
|
void SequenceNumberStats::reset() {
|
||||||
|
_received = 0;
|
||||||
_missingSet.clear();
|
_missingSet.clear();
|
||||||
_stats = PacketStreamStats();
|
_stats = PacketStreamStats();
|
||||||
|
_lastSenderUUID = QUuid();
|
||||||
_statsHistory.clear();
|
_statsHistory.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +39,7 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
||||||
|
|
||||||
// if the sender node has changed, reset all stats
|
// if the sender node has changed, reset all stats
|
||||||
if (senderUUID != _lastSenderUUID) {
|
if (senderUUID != _lastSenderUUID) {
|
||||||
if (_stats._numReceived > 0) {
|
if (_received > 0) {
|
||||||
qDebug() << "sequence number stats was reset due to new sender node";
|
qDebug() << "sequence number stats was reset due to new sender node";
|
||||||
qDebug() << "previous:" << _lastSenderUUID << "current:" << senderUUID;
|
qDebug() << "previous:" << _lastSenderUUID << "current:" << senderUUID;
|
||||||
reset();
|
reset();
|
||||||
|
@ -45,13 +48,14 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine our expected sequence number... handle rollover appropriately
|
// determine our expected sequence number... handle rollover appropriately
|
||||||
quint16 expected = _stats._numReceived > 0 ? _lastReceived + (quint16)1 : incoming;
|
quint16 expected = _received > 0 ? _lastReceivedSequence + (quint16)1 : incoming;
|
||||||
|
|
||||||
_stats._numReceived++;
|
_received++;
|
||||||
|
|
||||||
if (incoming == expected) { // on time
|
if (incoming == expected) { // on time
|
||||||
arrivalInfo._status = OnTime;
|
arrivalInfo._status = OnTime;
|
||||||
_lastReceived = incoming;
|
_lastReceivedSequence = incoming;
|
||||||
|
_stats._expectedReceived++;
|
||||||
} else { // out of order
|
} else { // out of order
|
||||||
|
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
|
@ -76,8 +80,8 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
||||||
|
|
||||||
// ignore packet if gap is unreasonable
|
// ignore packet if gap is unreasonable
|
||||||
qDebug() << "ignoring unreasonable sequence number:" << incoming
|
qDebug() << "ignoring unreasonable sequence number:" << incoming
|
||||||
<< "previous:" << _lastReceived;
|
<< "previous:" << _lastReceivedSequence;
|
||||||
_stats._numUnreasonable++;
|
_stats._unreasonable++;
|
||||||
|
|
||||||
return arrivalInfo;
|
return arrivalInfo;
|
||||||
}
|
}
|
||||||
|
@ -94,10 +98,11 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
||||||
qDebug() << "this packet is earlier than expected...";
|
qDebug() << "this packet is earlier than expected...";
|
||||||
qDebug() << ">>>>>>>> missing gap=" << (incomingInt - expectedInt);
|
qDebug() << ">>>>>>>> missing gap=" << (incomingInt - expectedInt);
|
||||||
}
|
}
|
||||||
|
int skipped = incomingInt - expectedInt;
|
||||||
_stats._numEarly++;
|
_stats._early++;
|
||||||
_stats._numLost += (incomingInt - expectedInt);
|
_stats._lost += skipped;
|
||||||
_lastReceived = incoming;
|
_stats._expectedReceived += (skipped + 1);
|
||||||
|
_lastReceivedSequence = incoming;
|
||||||
|
|
||||||
// add all sequence numbers that were skipped to the missing sequence numbers list
|
// add all sequence numbers that were skipped to the missing sequence numbers list
|
||||||
for (int missingInt = expectedInt; missingInt < incomingInt; missingInt++) {
|
for (int missingInt = expectedInt; missingInt < incomingInt; missingInt++) {
|
||||||
|
@ -114,7 +119,7 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
||||||
qDebug() << "this packet is later than expected...";
|
qDebug() << "this packet is later than expected...";
|
||||||
}
|
}
|
||||||
|
|
||||||
_stats._numLate++;
|
_stats._late++;
|
||||||
|
|
||||||
// do not update _lastReceived; it shouldn't become smaller
|
// do not update _lastReceived; it shouldn't become smaller
|
||||||
|
|
||||||
|
@ -125,15 +130,15 @@ SequenceNumberStats::ArrivalInfo SequenceNumberStats::sequenceNumberReceived(qui
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "found it in _missingSet";
|
qDebug() << "found it in _missingSet";
|
||||||
}
|
}
|
||||||
_stats._numLost--;
|
_stats._lost--;
|
||||||
_stats._numRecovered++;
|
_stats._recovered++;
|
||||||
} else {
|
} else {
|
||||||
arrivalInfo._status = Duplicate;
|
arrivalInfo._status = Duplicate;
|
||||||
|
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "sequence:" << incoming << "was NOT found in _missingSet and is probably a duplicate";
|
qDebug() << "sequence:" << incoming << "was NOT found in _missingSet and is probably a duplicate";
|
||||||
}
|
}
|
||||||
_stats._numDuplicate++;
|
_stats._duplicate++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,7 +153,7 @@ void SequenceNumberStats::pruneMissingSet(const bool wantExtraDebugging) {
|
||||||
// some older sequence numbers may be from before a rollover point; this must be handled.
|
// some older sequence numbers may be from before a rollover point; this must be handled.
|
||||||
// some sequence numbers in this list may be larger than _incomingLastSequence, indicating that they were received
|
// some sequence numbers in this list may be larger than _incomingLastSequence, indicating that they were received
|
||||||
// before the most recent rollover.
|
// before the most recent rollover.
|
||||||
int cutoff = (int)_lastReceived - MAX_REASONABLE_SEQUENCE_GAP;
|
int cutoff = (int)_lastReceivedSequence - MAX_REASONABLE_SEQUENCE_GAP;
|
||||||
if (cutoff >= 0) {
|
if (cutoff >= 0) {
|
||||||
quint16 nonRolloverCutoff = (quint16)cutoff;
|
quint16 nonRolloverCutoff = (quint16)cutoff;
|
||||||
QSet<quint16>::iterator i = _missingSet.begin();
|
QSet<quint16>::iterator i = _missingSet.begin();
|
||||||
|
@ -159,7 +164,7 @@ void SequenceNumberStats::pruneMissingSet(const bool wantExtraDebugging) {
|
||||||
qDebug() << "old age cutoff:" << nonRolloverCutoff;
|
qDebug() << "old age cutoff:" << nonRolloverCutoff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missing > _lastReceived || missing < nonRolloverCutoff) {
|
if (missing > _lastReceivedSequence || missing < nonRolloverCutoff) {
|
||||||
i = _missingSet.erase(i);
|
i = _missingSet.erase(i);
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "pruning really old missing sequence:" << missing;
|
qDebug() << "pruning really old missing sequence:" << missing;
|
||||||
|
@ -178,7 +183,7 @@ void SequenceNumberStats::pruneMissingSet(const bool wantExtraDebugging) {
|
||||||
qDebug() << "old age cutoff:" << rolloverCutoff;
|
qDebug() << "old age cutoff:" << rolloverCutoff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missing > _lastReceived && missing < rolloverCutoff) {
|
if (missing > _lastReceivedSequence && missing < rolloverCutoff) {
|
||||||
i = _missingSet.erase(i);
|
i = _missingSet.erase(i);
|
||||||
if (wantExtraDebugging) {
|
if (wantExtraDebugging) {
|
||||||
qDebug() << "pruning really old missing sequence:" << missing;
|
qDebug() << "pruning really old missing sequence:" << missing;
|
||||||
|
@ -202,13 +207,13 @@ PacketStreamStats SequenceNumberStats::getStatsForHistoryWindow() const {
|
||||||
|
|
||||||
// calculate difference between newest stats and oldest stats to get window stats
|
// calculate difference between newest stats and oldest stats to get window stats
|
||||||
PacketStreamStats windowStats;
|
PacketStreamStats windowStats;
|
||||||
windowStats._numReceived = newestStats->_numReceived - oldestStats->_numReceived;
|
windowStats._expectedReceived = newestStats->_expectedReceived - oldestStats->_expectedReceived;
|
||||||
windowStats._numUnreasonable = newestStats->_numUnreasonable - oldestStats->_numUnreasonable;
|
windowStats._unreasonable = newestStats->_unreasonable - oldestStats->_unreasonable;
|
||||||
windowStats._numEarly = newestStats->_numEarly - oldestStats->_numEarly;
|
windowStats._early = newestStats->_early - oldestStats->_early;
|
||||||
windowStats._numLate = newestStats->_numLate - oldestStats->_numLate;
|
windowStats._late = newestStats->_late - oldestStats->_late;
|
||||||
windowStats._numLost = newestStats->_numLost - oldestStats->_numLost;
|
windowStats._lost = newestStats->_lost - oldestStats->_lost;
|
||||||
windowStats._numRecovered = newestStats->_numRecovered - oldestStats->_numRecovered;
|
windowStats._recovered = newestStats->_recovered - oldestStats->_recovered;
|
||||||
windowStats._numDuplicate = newestStats->_numDuplicate - oldestStats->_numDuplicate;
|
windowStats._duplicate = newestStats->_duplicate - oldestStats->_duplicate;
|
||||||
|
|
||||||
return windowStats;
|
return windowStats;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,29 +21,27 @@ const int MAX_REASONABLE_SEQUENCE_GAP = 1000;
|
||||||
class PacketStreamStats {
|
class PacketStreamStats {
|
||||||
public:
|
public:
|
||||||
PacketStreamStats()
|
PacketStreamStats()
|
||||||
: _numReceived(0),
|
: _expectedReceived(0),
|
||||||
_numUnreasonable(0),
|
_unreasonable(0),
|
||||||
_numEarly(0),
|
_early(0),
|
||||||
_numLate(0),
|
_late(0),
|
||||||
_numLost(0),
|
_lost(0),
|
||||||
_numRecovered(0),
|
_recovered(0),
|
||||||
_numDuplicate(0)
|
_duplicate(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
float getUnreasonableRate() const { return (float)_numUnreasonable / _numReceived; }
|
float getUnreasonableRate() const { return (float)_unreasonable / _expectedReceived; }
|
||||||
float getNumEaryRate() const { return (float)_numEarly / _numReceived; }
|
float getEaryRate() const { return (float)_early / _expectedReceived; }
|
||||||
float getLateRate() const { return (float)_numLate / _numReceived; }
|
float getLateRate() const { return (float)_late / _expectedReceived; }
|
||||||
float getLostRate() const { return (float)_numLost / _numReceived; }
|
float getLostRate() const { return (float)_lost / _expectedReceived; }
|
||||||
float getRecoveredRate() const { return (float)_numRecovered / _numReceived; }
|
|
||||||
float getDuplicateRate() const { return (float)_numDuplicate / _numReceived; }
|
|
||||||
|
|
||||||
quint32 _numReceived;
|
quint32 _expectedReceived;
|
||||||
quint32 _numUnreasonable;
|
quint32 _unreasonable;
|
||||||
quint32 _numEarly;
|
quint32 _early;
|
||||||
quint32 _numLate;
|
quint32 _late;
|
||||||
quint32 _numLost;
|
quint32 _lost;
|
||||||
quint32 _numRecovered;
|
quint32 _recovered;
|
||||||
quint32 _numDuplicate;
|
quint32 _duplicate;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SequenceNumberStats {
|
class SequenceNumberStats {
|
||||||
|
@ -70,20 +68,25 @@ public:
|
||||||
void pruneMissingSet(const bool wantExtraDebugging = false);
|
void pruneMissingSet(const bool wantExtraDebugging = false);
|
||||||
void pushStatsToHistory() { _statsHistory.insert(_stats); }
|
void pushStatsToHistory() { _statsHistory.insert(_stats); }
|
||||||
|
|
||||||
quint32 getNumReceived() const { return _stats._numReceived; }
|
quint32 getReceived() const { return _received; }
|
||||||
quint32 getNumUnreasonable() const { return _stats._numUnreasonable; }
|
|
||||||
quint32 getNumOutOfOrder() const { return _stats._numEarly + _stats._numLate; }
|
quint32 getExpectedReceived() const { return _stats._expectedReceived; }
|
||||||
quint32 getNumEarly() const { return _stats._numEarly; }
|
quint32 getUnreasonable() const { return _stats._unreasonable; }
|
||||||
quint32 getNumLate() const { return _stats._numLate; }
|
quint32 getOutOfOrder() const { return _stats._early + _stats._late; }
|
||||||
quint32 getNumLost() const { return _stats._numLost; }
|
quint32 getEarly() const { return _stats._early; }
|
||||||
quint32 getNumRecovered() const { return _stats._numRecovered; }
|
quint32 getLate() const { return _stats._late; }
|
||||||
quint32 getNumDuplicate() const { return _stats._numDuplicate; }
|
quint32 getLost() const { return _stats._lost; }
|
||||||
|
quint32 getRecovered() const { return _stats._recovered; }
|
||||||
|
quint32 getDuplicate() const { return _stats._duplicate; }
|
||||||
|
|
||||||
const PacketStreamStats& getStats() const { return _stats; }
|
const PacketStreamStats& getStats() const { return _stats; }
|
||||||
PacketStreamStats getStatsForHistoryWindow() const;
|
PacketStreamStats getStatsForHistoryWindow() const;
|
||||||
const QSet<quint16>& getMissingSet() const { return _missingSet; }
|
const QSet<quint16>& getMissingSet() const { return _missingSet; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
quint16 _lastReceived;
|
int _received;
|
||||||
|
|
||||||
|
quint16 _lastReceivedSequence;
|
||||||
QSet<quint16> _missingSet;
|
QSet<quint16> _missingSet;
|
||||||
|
|
||||||
PacketStreamStats _stats;
|
PacketStreamStats _stats;
|
||||||
|
|
Loading…
Reference in a new issue