mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-06-05 04:32:09 +02:00
add output of connection stats in UDTTest
This commit is contained in:
parent
e346dbcfee
commit
ce21204151
8 changed files with 98 additions and 5 deletions
|
@ -126,9 +126,17 @@ void Connection::sendACK(bool wasCausedBySyncTimeout) {
|
||||||
ackPacket->writePrimitive((int32_t) udt::CONNECTION_RECEIVE_BUFFER_SIZE_PACKETS);
|
ackPacket->writePrimitive((int32_t) udt::CONNECTION_RECEIVE_BUFFER_SIZE_PACKETS);
|
||||||
|
|
||||||
if (wasCausedBySyncTimeout) {
|
if (wasCausedBySyncTimeout) {
|
||||||
|
// grab the up to date packet receive speed and estimated bandwidth
|
||||||
|
int32_t packetReceiveSpeed = _receiveWindow.getPacketReceiveSpeed();
|
||||||
|
int32_t estimatedBandwidth = _receiveWindow.getEstimatedBandwidth();
|
||||||
|
|
||||||
|
// update those values in our connection stats
|
||||||
|
_stats.recordReceiveRate(packetReceiveSpeed);
|
||||||
|
_stats.recordEstimatedBandwidth(estimatedBandwidth);
|
||||||
|
|
||||||
// pack in the receive speed and estimatedBandwidth
|
// pack in the receive speed and estimatedBandwidth
|
||||||
ackPacket->writePrimitive(_receiveWindow.getPacketReceiveSpeed());
|
ackPacket->writePrimitive(packetReceiveSpeed);
|
||||||
ackPacket->writePrimitive(_receiveWindow.getEstimatedBandwidth());
|
ackPacket->writePrimitive(estimatedBandwidth);
|
||||||
|
|
||||||
// record this as the last ACK send time
|
// record this as the last ACK send time
|
||||||
lastACKSendTime = high_resolution_clock::now();
|
lastACKSendTime = high_resolution_clock::now();
|
||||||
|
@ -261,6 +269,7 @@ bool Connection::processReceivedSequenceNumber(SequenceNumber sequenceNumber) {
|
||||||
_nakInterval = (_rtt + 4 * _rttVariance);
|
_nakInterval = (_rtt + 4 * _rttVariance);
|
||||||
|
|
||||||
int receivedPacketsPerSecond = _receiveWindow.getPacketReceiveSpeed();
|
int receivedPacketsPerSecond = _receiveWindow.getPacketReceiveSpeed();
|
||||||
|
|
||||||
if (receivedPacketsPerSecond > 0) {
|
if (receivedPacketsPerSecond > 0) {
|
||||||
// the NAK interval is at least the _minNAKInterval
|
// the NAK interval is at least the _minNAKInterval
|
||||||
// but might be the time required for all lost packets to be retransmitted
|
// but might be the time required for all lost packets to be retransmitted
|
||||||
|
@ -371,10 +380,12 @@ void Connection::processACK(std::unique_ptr<ControlPacket> controlPacket) {
|
||||||
// ACK the send queue so it knows what was received
|
// ACK the send queue so it knows what was received
|
||||||
_sendQueue->ack(ack);
|
_sendQueue->ack(ack);
|
||||||
|
|
||||||
|
|
||||||
// update the RTT
|
// update the RTT
|
||||||
updateRTT(rtt);
|
updateRTT(rtt);
|
||||||
|
|
||||||
|
// write this RTT to stats
|
||||||
|
_stats.recordRTT(rtt);
|
||||||
|
|
||||||
// set the RTT for congestion control
|
// set the RTT for congestion control
|
||||||
_congestionControl->setRTT(_rtt);
|
_congestionControl->setRTT(_rtt);
|
||||||
|
|
||||||
|
@ -387,6 +398,10 @@ void Connection::processACK(std::unique_ptr<ControlPacket> controlPacket) {
|
||||||
// these are calculated using an EWMA
|
// these are calculated using an EWMA
|
||||||
static const int EMWA_ALPHA_NUMERATOR = 8;
|
static const int EMWA_ALPHA_NUMERATOR = 8;
|
||||||
|
|
||||||
|
// record these samples in connection stats
|
||||||
|
_stats.recordReceiveRate(receiveRate);
|
||||||
|
_stats.recordEstimatedBandwidth(bandwidth);
|
||||||
|
|
||||||
_deliveryRate = (_deliveryRate * (EMWA_ALPHA_NUMERATOR - 1) + _deliveryRate) / EMWA_ALPHA_NUMERATOR;
|
_deliveryRate = (_deliveryRate * (EMWA_ALPHA_NUMERATOR - 1) + _deliveryRate) / EMWA_ALPHA_NUMERATOR;
|
||||||
_bandwidth = (_bandwidth * (EMWA_ALPHA_NUMERATOR - 1) + _bandwidth) / EMWA_ALPHA_NUMERATOR;
|
_bandwidth = (_bandwidth * (EMWA_ALPHA_NUMERATOR - 1) + _bandwidth) / EMWA_ALPHA_NUMERATOR;
|
||||||
|
|
||||||
|
@ -515,4 +530,8 @@ void Connection::updateCongestionControlAndSendQueue(std::function<void ()> cong
|
||||||
// now that we've update the congestion control, update the packet send period and flow window size
|
// now that we've update the congestion control, update the packet send period and flow window size
|
||||||
_sendQueue->setPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
_sendQueue->setPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
||||||
_sendQueue->setFlowWindowSize(std::min(_flowWindowSize, (int) _congestionControl->_congestionWindowSize));
|
_sendQueue->setFlowWindowSize(std::min(_flowWindowSize, (int) _congestionControl->_congestionWindowSize));
|
||||||
|
|
||||||
|
// record connection stats
|
||||||
|
_stats.recordPacketSendPeriod(_congestionControl->_packetSendPeriod);
|
||||||
|
_stats.recordCongestionWindowSize(_congestionControl->_congestionWindowSize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ public:
|
||||||
|
|
||||||
bool processReceivedSequenceNumber(SequenceNumber sequenceNumber); // returns indicates if this packet was a duplicate
|
bool processReceivedSequenceNumber(SequenceNumber sequenceNumber); // returns indicates if this packet was a duplicate
|
||||||
void processControl(std::unique_ptr<ControlPacket> controlPacket);
|
void processControl(std::unique_ptr<ControlPacket> controlPacket);
|
||||||
|
|
||||||
|
ConnectionStats::Stats sampleStats() { return _stats.sample(); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void packetSent();
|
void packetSent();
|
||||||
|
|
|
@ -89,4 +89,32 @@ void ConnectionStats::recordSentPackets() {
|
||||||
void ConnectionStats::recordReceivedPackets() {
|
void ConnectionStats::recordReceivedPackets() {
|
||||||
++_currentSample.recievedPackets;
|
++_currentSample.recievedPackets;
|
||||||
++_total.recievedPackets;
|
++_total.recievedPackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const double EWMA_CURRENT_SAMPLE_WEIGHT = 0.125;
|
||||||
|
static const double EWMA_PREVIOUS_SAMPLES_WEIGHT = 1 - 0.125;
|
||||||
|
|
||||||
|
void ConnectionStats::recordReceiveRate(int sample) {
|
||||||
|
_currentSample.receiveRate = sample;
|
||||||
|
_total.receiveRate = (_total.receiveRate * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectionStats::recordEstimatedBandwidth(int sample) {
|
||||||
|
_currentSample.estimatedBandwith = sample;
|
||||||
|
_total.estimatedBandwith = (_total.estimatedBandwith * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectionStats::recordRTT(int sample) {
|
||||||
|
_currentSample.rtt = sample;
|
||||||
|
_total.rtt = (_total.rtt * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectionStats::recordCongestionWindowSize(int sample) {
|
||||||
|
_currentSample.congestionWindowSize = sample;
|
||||||
|
_total.congestionWindowSize = (_total.congestionWindowSize * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectionStats::recordPacketSendPeriod(int sample) {
|
||||||
|
_currentSample.packetSendPeriod = sample;
|
||||||
|
_total.packetSendPeriod = (_total.packetSendPeriod * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT);
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,13 @@ public:
|
||||||
|
|
||||||
int sentPackets { 0 };
|
int sentPackets { 0 };
|
||||||
int recievedPackets { 0 };
|
int recievedPackets { 0 };
|
||||||
|
|
||||||
|
// the following stats are trailing averages in the result, not totals
|
||||||
|
int receiveRate { 0 };
|
||||||
|
int estimatedBandwith { 0 };
|
||||||
|
int rtt { 0 };
|
||||||
|
int congestionWindowSize { 0 };
|
||||||
|
int packetSendPeriod { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
ConnectionStats();
|
ConnectionStats();
|
||||||
|
@ -57,6 +64,12 @@ public:
|
||||||
void recordSentPackets();
|
void recordSentPackets();
|
||||||
void recordReceivedPackets();
|
void recordReceivedPackets();
|
||||||
|
|
||||||
|
void recordReceiveRate(int sample);
|
||||||
|
void recordEstimatedBandwidth(int sample);
|
||||||
|
void recordRTT(int sample);
|
||||||
|
void recordCongestionWindowSize(int sample);
|
||||||
|
void recordPacketSendPeriod(int sample);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Stats _currentSample;
|
Stats _currentSample;
|
||||||
Stats _total;
|
Stats _total;
|
||||||
|
@ -64,4 +77,4 @@ private:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // hifi_ConnectionStats_h
|
#endif // hifi_ConnectionStats_h
|
||||||
|
|
|
@ -213,3 +213,20 @@ void Socket::setCongestionControlFactory(std::unique_ptr<CongestionControlVirtua
|
||||||
// update the _synInterval to the value from the factory
|
// update the _synInterval to the value from the factory
|
||||||
_synInterval = _ccFactory->synInterval();
|
_synInterval = _ccFactory->synInterval();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Socket::sampleAndPrintConnectionStats() {
|
||||||
|
if (thread() != QThread::currentThread()) {
|
||||||
|
QMetaObject::invokeMethod(this, "sampleAndPrintConnectionStats");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& connection : _connectionsHash) {
|
||||||
|
ConnectionStats::Stats sampleStats = connection.second->sampleStats();
|
||||||
|
|
||||||
|
qDebug() << connection.first
|
||||||
|
<< sampleStats.receiveRate << sampleStats.rtt
|
||||||
|
<< sampleStats.congestionWindowSize << sampleStats.packetSendPeriod
|
||||||
|
<< sampleStats.sentPackets
|
||||||
|
<< sampleStats.receivedACKs << sampleStats.receivedLightACKs << sampleStats.receivedNAKs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -63,6 +63,8 @@ public:
|
||||||
void setCongestionControlFactory(std::unique_ptr<CongestionControlVirtualFactory> ccFactory);
|
void setCongestionControlFactory(std::unique_ptr<CongestionControlVirtualFactory> ccFactory);
|
||||||
|
|
||||||
void connectToSendSignal(const HifiSockAddr& destinationAddr, QObject* receiver, const char* slot);
|
void connectToSendSignal(const HifiSockAddr& destinationAddr, QObject* receiver, const char* slot);
|
||||||
|
|
||||||
|
void sampleAndPrintConnectionStats();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void readPendingDatagrams();
|
void readPendingDatagrams();
|
||||||
|
|
|
@ -116,6 +116,13 @@ UDTTest::UDTTest(int& argc, char** argv) :
|
||||||
|
|
||||||
if (!_target.isNull()) {
|
if (!_target.isNull()) {
|
||||||
sendInitialPackets();
|
sendInitialPackets();
|
||||||
|
|
||||||
|
// the sender reports stats every 1 second
|
||||||
|
static const int STATS_SAMPLE_INTERVAL = 1000;
|
||||||
|
|
||||||
|
QTimer* statsTimer = new QTimer(this);
|
||||||
|
connect(statsTimer, &QTimer::timeout, this, &UDTTest::sampleStats);
|
||||||
|
statsTimer->start(STATS_SAMPLE_INTERVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,3 +205,7 @@ void UDTTest::sendPacket() {
|
||||||
|
|
||||||
++_totalQueuedPackets;
|
++_totalQueuedPackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UDTTest::sampleStats() {
|
||||||
|
_socket.sampleAndPrintConnectionStats();
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void refillPacket() { sendPacket(); } // adds a new packet to the queue when we are told one is sent
|
void refillPacket() { sendPacket(); } // adds a new packet to the queue when we are told one is sent
|
||||||
|
void sampleStats();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parseArguments();
|
void parseArguments();
|
||||||
|
|
Loading…
Reference in a new issue