mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-24 22:44:15 +00:00
reduce number of retransmits
This commit is contained in:
parent
a5e9d9c6a3
commit
cb0801fc16
@ -76,7 +76,7 @@ namespace stream
|
|||||||
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_LocalDestination (local),
|
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_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_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_WindowDropTargetSize (0), m_WindowIncCounter (0), m_RTO (INITIAL_RTO),
|
||||||
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT),
|
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_PrevRTTSample (INITIAL_RTT),
|
||||||
m_Jitter (0), m_MinPacingTime (0),
|
m_Jitter (0), m_MinPacingTime (0),
|
||||||
@ -103,7 +103,7 @@ namespace stream
|
|||||||
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
|
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
|
||||||
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_LocalDestination (local),
|
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_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_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0),
|
||||||
m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
|
m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
|
||||||
m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0),
|
m_PrevRTTSample (INITIAL_RTT), m_Jitter (0), m_MinPacingTime (0),
|
||||||
@ -550,27 +550,34 @@ namespace stream
|
|||||||
{
|
{
|
||||||
m_RTT = rttSample;
|
m_RTT = rttSample;
|
||||||
m_SlowRTT = rttSample;
|
m_SlowRTT = rttSample;
|
||||||
|
m_SlowRTT2 = rttSample;
|
||||||
m_PrevRTTSample = rttSample;
|
m_PrevRTTSample = rttSample;
|
||||||
|
m_Jitter = rttSample / 10; // 10%
|
||||||
|
m_Jitter += 5; // for low-latency connections
|
||||||
m_IsFirstRttSample = false;
|
m_IsFirstRttSample = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_RTT = RTT_EWMA_ALPHA * rttSample + (1.0 - RTT_EWMA_ALPHA) * m_RTT;
|
m_RTT = (m_PrevRTTSample + rttSample) / 2;
|
||||||
// calculate jitter
|
if (!m_IsWinDropped)
|
||||||
double jitter = 0;
|
{
|
||||||
if (rttSample > m_PrevRTTSample)
|
m_SlowRTT = SLOWRTT_EWMA_ALPHA * m_RTT + (1.0 - SLOWRTT_EWMA_ALPHA) * m_SlowRTT;
|
||||||
jitter = rttSample - m_PrevRTTSample;
|
m_SlowRTT2 = RTT_EWMA_ALPHA * m_RTT + (1.0 - RTT_EWMA_ALPHA) * m_SlowRTT2;
|
||||||
else if (rttSample < m_PrevRTTSample)
|
// calculate jitter
|
||||||
jitter = m_PrevRTTSample - rttSample;
|
double jitter = 0;
|
||||||
else
|
if (rttSample > m_PrevRTTSample)
|
||||||
jitter = std::round (rttSample / 10); // 10%
|
jitter = rttSample - m_PrevRTTSample;
|
||||||
jitter += 1; // for low-latency connections
|
else if (rttSample < m_PrevRTTSample)
|
||||||
m_Jitter = (0.025 * jitter) + (1.0 - 0.025) * m_Jitter;
|
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
|
// 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 ();
|
ProcessWindowDrop ();
|
||||||
UpdatePacingTime ();
|
UpdatePacingTime ();
|
||||||
m_SlowRTT = SLOWRTT_EWMA_ALPHA * rttSample + (1.0 - SLOWRTT_EWMA_ALPHA) * m_SlowRTT;
|
|
||||||
m_PrevRTTSample = rttSample;
|
m_PrevRTTSample = rttSample;
|
||||||
|
|
||||||
bool wasInitial = m_RTO == INITIAL_RTO;
|
bool wasInitial = m_RTO == INITIAL_RTO;
|
||||||
@ -579,18 +586,23 @@ namespace stream
|
|||||||
if (wasInitial)
|
if (wasInitial)
|
||||||
ScheduleResend ();
|
ScheduleResend ();
|
||||||
}
|
}
|
||||||
if (ackThrough > m_DropWindowDelaySequenceNumber && m_WindowSize <= m_WindowDropTargetSize)
|
if (m_IsWinDropped && ackThrough > m_DropWindowDelaySequenceNumber)
|
||||||
m_IsWinDropped = false;
|
|
||||||
if (acknowledged && m_IsWinDropped && m_WindowSize > m_WindowDropTargetSize)
|
|
||||||
{
|
{
|
||||||
if (ackCount > 1)
|
m_IsFirstRttSample = true;
|
||||||
m_WindowSize = m_SentPackets.size () + 1;
|
m_IsWinDropped = false;
|
||||||
else
|
}
|
||||||
{
|
if (m_WindowDropTargetSize && m_WindowSize <= m_WindowDropTargetSize)
|
||||||
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 < MIN_WINDOW_SIZE) m_WindowSize = MIN_WINDOW_SIZE;
|
||||||
|
if (m_WindowSize > MAX_WINDOW_SIZE) m_WindowSize = MAX_WINDOW_SIZE;
|
||||||
m_WindowIncCounter = 0;
|
m_WindowIncCounter = 0;
|
||||||
UpdatePacingTime ();
|
UpdatePacingTime ();
|
||||||
}
|
}
|
||||||
@ -598,10 +610,10 @@ namespace stream
|
|||||||
{
|
{
|
||||||
ScheduleResend ();
|
ScheduleResend ();
|
||||||
}
|
}
|
||||||
if ((m_SendBuffer.IsEmpty () && m_SentPackets.size () > 0) // tail loss
|
if (m_SendBuffer.IsEmpty () && m_SentPackets.size () > 0) // tail loss
|
||||||
|| int(m_SentPackets.size ()) > m_WindowSize) // or we drop window
|
|
||||||
{
|
{
|
||||||
m_IsResendNeeded = true;
|
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 ())
|
if (m_SentPackets.empty () && m_SendBuffer.IsEmpty ())
|
||||||
{
|
{
|
||||||
@ -1304,7 +1316,7 @@ namespace stream
|
|||||||
if (m_NumResendAttempts == 1 && m_RTO != INITIAL_RTO)
|
if (m_NumResendAttempts == 1 && m_RTO != INITIAL_RTO)
|
||||||
{
|
{
|
||||||
// loss-based CC
|
// loss-based CC
|
||||||
if (!m_IsWinDropped)
|
if (!m_IsWinDropped && LOSS_BASED_CONTROL_ENABLED)
|
||||||
ProcessWindowDrop ();
|
ProcessWindowDrop ();
|
||||||
}
|
}
|
||||||
else if (m_IsTimeOutResend)
|
else if (m_IsTimeOutResend)
|
||||||
|
@ -56,8 +56,8 @@ namespace stream
|
|||||||
const int INITIAL_WINDOW_SIZE = 10;
|
const int INITIAL_WINDOW_SIZE = 10;
|
||||||
const int MIN_WINDOW_SIZE = 2;
|
const int MIN_WINDOW_SIZE = 2;
|
||||||
const int MAX_WINDOW_SIZE = 512;
|
const int MAX_WINDOW_SIZE = 512;
|
||||||
const double RTT_EWMA_ALPHA = 0.25;
|
const double RTT_EWMA_ALPHA = 0.5;
|
||||||
const double SLOWRTT_EWMA_ALPHA = 0.125;
|
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 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 MIN_RTO = 20; // in milliseconds
|
||||||
const int INITIAL_RTT = 8000; // in milliseconds
|
const int INITIAL_RTT = 8000; // in milliseconds
|
||||||
@ -72,6 +72,7 @@ namespace stream
|
|||||||
const uint64_t SEND_INTERVAL = 1000; // in microseconds
|
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 = 7500; // in milliseconds
|
||||||
const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE = 3200; // in milliseconds
|
const uint64_t REQUEST_IMMEDIATE_ACK_INTERVAL_VARIANCE = 3200; // in milliseconds
|
||||||
|
const bool LOSS_BASED_CONTROL_ENABLED = 1; // 0/1
|
||||||
|
|
||||||
struct Packet
|
struct Packet
|
||||||
{
|
{
|
||||||
@ -282,7 +283,7 @@ namespace stream
|
|||||||
uint16_t m_Port;
|
uint16_t m_Port;
|
||||||
|
|
||||||
SendBufferQueue m_SendBuffer;
|
SendBufferQueue m_SendBuffer;
|
||||||
double m_RTT, m_SlowRTT;
|
double m_RTT, m_SlowRTT, m_SlowRTT2;
|
||||||
float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize;
|
float m_WindowSize, m_LastWindowDropSize, m_WindowDropTargetSize;
|
||||||
int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample;
|
int m_WindowIncCounter, m_RTO, m_AckDelay, m_PrevRTTSample;
|
||||||
double m_Jitter;
|
double m_Jitter;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user