some uTP tweaks. experimental slow start mode (disabled)

This commit is contained in:
Arvid Norberg
2011-11-05 09:30:38 +00:00
parent 3507e5f909
commit 4a6e012a5f

View File

@@ -135,7 +135,7 @@ struct packet
// the last time this packet was sent
ptime send_time;
// the size of the buffer 'buf' pointst to
// the size of the buffer 'buf' points to
boost::uint16_t size;
// this is the offset to the payload inside the buffer
@@ -144,7 +144,7 @@ struct packet
boost::uint16_t header_size;
// the number of times this packet has been sent
boost::uint8_t num_transmissions:7;
boost::uint8_t num_transmissions:6;
// true if we need to send this packet again. All
// outstanding packets are marked as needing to be
@@ -220,7 +220,7 @@ struct utp_socket_impl
, m_read_timeout()
, m_write_timeout()
, m_timeout(time_now_hires() + milliseconds(m_sm->connect_timeout()))
, m_last_cwnd_hit(min_time())
, m_last_cwnd_hit(time_now())
, m_ack_timer(time_now() + minutes(10))
, m_last_history_step(time_now_hires())
, m_cwnd(TORRENT_ETHERNET_MTU << 16)
@@ -258,6 +258,8 @@ struct utp_socket_impl
, m_eof(false)
, m_attached(true)
, m_nagle(true)
, m_slow_start(false)
, m_cwnd_full(false)
{
TORRENT_ASSERT(m_userdata);
for (int i = 0; i != num_delay_hist; ++i)
@@ -412,7 +414,7 @@ struct utp_socket_impl
// the max number of bytes in-flight. This is a fixed point
// value, to get the true number of bytes, shift right 16 bits
// the value is always >= 0, but the calculations performed on
// it in do_ledbat() is signed.
// it in do_ledbat() are signed.
boost::int64_t m_cwnd;
timestamp_history m_delay_hist;
@@ -591,6 +593,14 @@ struct utp_socket_impl
// this is true if nagle is enabled (which it is by default)
// TODO: support the option to turn it off
bool m_nagle:1;
// this is true while the socket is in slow start mode. It's
// only in slow-start during the start-up phase
bool m_slow_start:1;
// this is true as long as we have as many packets in
// flight as allowed by the congestion window (cwnd)
bool m_cwnd_full:1;
};
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
@@ -1082,7 +1092,7 @@ void utp_socket_impl::maybe_trigger_send_callback(ptime now)
// nothing has been written or there's no outstanding write operation
if (m_written == 0 || m_write_handler == 0) return;
if (m_written > m_write_buffer_size / 2 || now >= m_write_timeout)
if (m_written > m_write_buffer_size * 2 / 3 || now >= m_write_timeout)
{
UTP_LOGV("%8p: calling write handler written:%d\n", this, m_written);
@@ -1422,8 +1432,8 @@ void utp_socket_impl::write_payload(char* ptr, int size)
size -= to_copy;
if (m_written == 0)
{
m_write_timeout = now + milliseconds(100);
UTP_LOGV("%8p: setting write timeout to 100 ms from now\n", this);
m_write_timeout = now + milliseconds(300);
UTP_LOGV("%8p: setting write timeout to 300 ms from now\n", this);
}
m_written += to_copy;
ptr += to_copy;
@@ -1507,15 +1517,17 @@ bool utp_socket_impl::send_pkt(bool ack)
// if we have one MSS worth of data, make sure it fits in our
// congestion window and the advertized receive window from
// the other end.
if (m_bytes_in_flight + payload_size > (std::min)(int(m_cwnd >> 16), int(m_adv_wnd - m_bytes_in_flight)))
if (m_bytes_in_flight + payload_size > (std::min)(int(m_cwnd >> 16)
, int(m_adv_wnd - m_bytes_in_flight)))
{
// this means there's not enough room in the send window for
// another packet. We have to hold off sending this data.
// we still need to send an ACK though
payload_size = 0;
// we're restrained by the window size
// we're constrained by the window size
m_last_cwnd_hit = time_now_hires();
m_cwnd_full = true;
// there's no more space in the cwnd, no need to
// try to send more right now
@@ -1720,9 +1732,10 @@ bool utp_socket_impl::resend_packet(packet* p, bool fast_resend)
// we can only resend the packet if there's
// enough space in our congestion window
int window_size_left = (std::min)(int(m_cwnd >> 16), int(m_adv_wnd)) - m_bytes_in_flight;
if (!fast_resend&& p->size - p->header_size > window_size_left)
if (!fast_resend && p->size - p->header_size > window_size_left)
{
m_last_cwnd_hit = time_now_hires();
m_cwnd_full = true;
return false;
}
@@ -1793,6 +1806,9 @@ void utp_socket_impl::experienced_loss(int seq_nr)
// the window size could go below one MMS here, if it does,
// we'll get a timeout in about one second
// if we happen to be in slow-start mode, we need to leave it
m_slow_start = false;
}
void utp_socket_impl::maybe_inc_acked_seq_nr()
@@ -2744,11 +2760,31 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime
// all of these are fixed points with 16 bits fraction portion
boost::int64_t window_factor = (boost::int64_t(acked_bytes) << 16) / in_flight;
boost::int64_t delay_factor = (boost::int64_t(target_delay - delay) << 16) / target_delay;
boost::int64_t scaled_gain = (window_factor * delay_factor) >> 16;
scaled_gain *= boost::int64_t(m_sm->gain_factor());
if (scaled_gain > 0 && m_last_cwnd_hit + milliseconds((std::max)(m_rtt.mean(), 10)) < now)
boost::int64_t scaled_gain;
if (delay >= target_delay / 2)
{
UTP_LOGV("%8p: off_target: %d slow_start -> 0\n", this, target_delay - delay);
m_slow_start = false;
}
boost::int64_t linear_gain = (window_factor * delay_factor) >> 16;
linear_gain *= boost::int64_t(m_sm->gain_factor());
if (m_slow_start)
{
scaled_gain = (std::max)((window_factor * m_cwnd) >> 16, linear_gain);
}
else
{
scaled_gain = linear_gain;
}
if (scaled_gain > 0 && !m_cwnd_full
&& m_last_cwnd_hit + milliseconds((std::max)(m_rtt.mean(), 500)) < now)
{
UTP_LOGV("%8p: last_cwnd_hit:%d full_cwnd:%d scaled_gain -> 0, slow_start -> 0\n", this
, total_milliseconds(now - m_last_cwnd_hit), int(m_cwnd_full));
// we haven't bumped into the cwnd limit size in the last second
// this probably means we have a send rate limit, so we shouldn't make
// the cwnd size any larger
@@ -2756,10 +2792,11 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime
}
UTP_LOGV("%8p: do_ledbat delay:%d off_target: %d window_factor:%f target_factor:%f "
"scaled_gain:%f cwnd:%d\n"
"scaled_gain:%f cwnd:%d slow_start:%d\n"
, this, delay, target_delay - delay, window_factor / float(1 << 16)
, delay_factor / float(1 << 16)
, scaled_gain / float(1 << 16), int(m_cwnd >> 16));
, scaled_gain / float(1 << 16), int(m_cwnd >> 16)
, int(m_slow_start));
// if scaled_gain + m_cwnd <= 0, set m_cwnd to 0
if (-scaled_gain >= m_cwnd)
@@ -2771,6 +2808,15 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime
m_cwnd += scaled_gain;
TORRENT_ASSERT(m_cwnd > 0);
}
int window_size_left = (std::min)(int(m_cwnd >> 16), int(m_adv_wnd)) - in_flight + acked_bytes;
if (window_size_left >= m_mtu)
{
UTP_LOGV("%8p: mtu:%d in_flight:%d adv_wnd:%d cwnd:%d acked_bytes:%d cwnd_full -> 0\n"
, this, m_mtu, in_flight, m_adv_wnd, m_cwnd >> 16, acked_bytes);
m_cwnd_full = false;
}
}
void utp_stream::bind(endpoint_type const& ep, error_code& ec) { }