Browse Source

reduce number of retransmits

pull/2101/head
orignal 2 months ago
parent
commit
cb0801fc16
  1. 66
      libi2pd/Streaming.cpp
  2. 7
      libi2pd/Streaming.h

66
libi2pd/Streaming.cpp

@ -76,7 +76,7 @@ namespace stream @@ -76,7 +76,7 @@ namespace stream
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_LocalDestination (local),
m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service),
m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0),
m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0),
m_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO),
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT),
m_Jitter (0), m_MinPacingTime (0),
@ -103,7 +103,7 @@ namespace stream @@ -103,7 +103,7 @@ namespace stream
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_LocalDestination (local),
m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT),
m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT),
m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0),
m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0),
@ -550,27 +550,34 @@ namespace stream @@ -550,27 +550,34 @@ namespace stream
{
m_RTT = rttSample;
m_SlowRTT = rttSample;
m_SlowRTT2 = rttSample;
m_PrevRTTSample = rttSample;
m_Jitter = rttSample / 10; // 10%
m_Jitter += 5; // for low-latency connections
m_IsFirstRttSample = false;
}
else
m_RTT = RTT_EWMA_ALPHA * rttSample + (1.0 - RTT_EWMA_ALPHA) * m_RTT;
// calculate jitter
double jitter = 0;
if (rttSample > m_PrevRTTSample)
jitter = rttSample - m_PrevRTTSample;
else if (rttSample < m_PrevRTTSample)
jitter = m_PrevRTTSample - rttSample;
else
jitter = std::round (rttSample / 10); // 10%
jitter += 1; // for low-latency connections
m_Jitter = (0.025 * jitter) + (1.0 - 0.025) * m_Jitter;
m_RTT = (m_PrevRTTSample + rttSample) / 2;
if (!m_IsWinDropped)
{
m_SlowRTT = SLOWRTT_EWMA_ALPHA * m_RTT + (1.0 - SLOWRTT_EWMA_ALPHA) * m_SlowRTT;
m_SlowRTT2 = RTT_EWMA_ALPHA * m_RTT + (1.0 - RTT_EWMA_ALPHA) * m_SlowRTT2;
// calculate jitter
double jitter = 0;
if (rttSample > m_PrevRTTSample)
jitter = rttSample - m_PrevRTTSample;
else if (rttSample < m_PrevRTTSample)
jitter = m_PrevRTTSample - rttSample;
else
jitter = rttSample / 10; // 10%
jitter += 5; // for low-latency connections
m_Jitter = (0.05 * jitter) + (1.0 - 0.05) * m_Jitter;
}
//
// delay-based CC
if ((m_RTT > m_SlowRTT + m_Jitter && rttSample > m_RTT && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection
if ((m_SlowRTT2 > m_SlowRTT + m_Jitter && rttSample > m_SlowRTT2 && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection
ProcessWindowDrop ();
UpdatePacingTime ();
m_SlowRTT = SLOWRTT_EWMA_ALPHA * rttSample + (1.0 - SLOWRTT_EWMA_ALPHA) * m_SlowRTT;
m_PrevRTTSample = rttSample;
bool wasInitial = m_RTO == INITIAL_RTO;
@ -579,18 +586,23 @@ namespace stream @@ -579,18 +586,23 @@ namespace stream
if (wasInitial)
ScheduleResend ();
}
if (ackThrough > m_DropWindowDelaySequenceNumber && m_WindowSize <= m_WindowDropTargetSize)
if (m_IsWinDropped && ackThrough > m_DropWindowDelaySequenceNumber)
{
m_IsFirstRttSample = true;
m_IsWinDropped = false;
if (acknowledged && m_IsWinDropped && m_WindowSize > m_WindowDropTargetSize)
}
if (m_WindowDropTargetSize && m_WindowSize <= m_WindowDropTargetSize)
{
if (ackCount > 1)
m_WindowSize = m_SentPackets.size () + 1;
else
{
m_WindowSize = m_SentPackets.size ();
m_IsResendNeeded = true;
}
m_WindowDropTargetSize = 0;
m_DropWindowDelaySequenceNumber = m_SequenceNumber;
}
if (acknowledged && m_WindowDropTargetSize && m_WindowSize > m_WindowDropTargetSize)
{
m_RTO = std::max (MIN_RTO, (int)(m_RTT * 1.5 + m_Jitter)); // we assume that the next rtt sample may be much larger than the current
m_IsResendNeeded = true;
m_WindowSize = m_SentPackets.size () + 1; // if there are no packets to resend, just send one regular packet
if (m_WindowSize < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE;
if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE;
m_WindowIncCounter = 0;
UpdatePacingTime ();
}
@ -598,10 +610,10 @@ namespace stream @@ -598,10 +610,10 @@ namespace stream
{
ScheduleResend ();
}
if ((m_SendBuffer.IsEmpty () && m_SentPackets.size () > 0) // tail loss
|| int(m_SentPackets.size ()) > m_WindowSize) // or we drop window
if (m_SendBuffer.IsEmpty () && m_SentPackets.size () > 0) // tail loss
{
m_IsResendNeeded = true;
m_RTO = std::max (MIN_RTO, (int)(m_RTT * 1.5 + m_Jitter)); // to prevent spurious retransmit
}
if (m_SentPackets.empty () && m_SendBuffer.IsEmpty ())
{
@ -1304,7 +1316,7 @@ namespace stream @@ -1304,7 +1316,7 @@ namespace stream
if (m_NumResendAttempts == 1 && m_RTO != INITIAL_RTO)
{
// loss-based CC
if (!m_IsWinDropped)
if (!m_IsWinDropped && LOSS_BASED_CONTROL_ENABLED)
ProcessWindowDrop ();
}
else if (m_IsTimeOutResend)

7
libi2pd/Streaming.h

@ -56,8 +56,8 @@ namespace stream @@ -56,8 +56,8 @@ namespace stream
const int INITIAL_WINDOW_SIZE = 10;
const int MIN_WINDOW_SIZE = 2;
const int MAX_WINDOW_SIZE = 512;
const double RTT_EWMA_ALPHA = 0.25;
const double SLOWRTT_EWMA_ALPHA = 0.125;
const double RTT_EWMA_ALPHA = 0.5;
const double SLOWRTT_EWMA_ALPHA = 0.05;
const double PREV_SPEED_KEEP_TIME_COEFF = 0.35; // 0.1 - 1 // how long will the window size stay around the previous drop level, less is longer
const int MIN_RTO = 20; // in milliseconds
const int INITIAL_RTT = 8000; // in milliseconds
@ -72,6 +72,7 @@ namespace stream @@ -72,6 +72,7 @@ namespace stream
const uint64_t SEND_INTERVAL = 1000; // in microseconds
const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL = 7500; // in milliseconds
const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE = 3200; // in milliseconds
const bool LOSS_BASED_CONTROL_ENABLED = 1; // 0/1
struct Packet
{
@ -282,7 +283,7 @@ namespace stream @@ -282,7 +283,7 @@ namespace stream
uint16_t m_Port;
SendBufferQueue m_SendBuffer;
double m_RTT, m_SlowRTT;
double m_RTT, m_SlowRTT, m_SlowRTT2;
float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize;
int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample;
double m_Jitter;

Loading…
Cancel
Save