From 351e34f9d1d5d698a2572e8a89340f169925b756 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Thu, 21 Jun 2012 16:41:05 +0000 Subject: [PATCH] polish uTP slow start --- src/utp_stream.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/utp_stream.cpp b/src/utp_stream.cpp index 7531a2788..e0e1ac834 100644 --- a/src/utp_stream.cpp +++ b/src/utp_stream.cpp @@ -257,8 +257,7 @@ struct utp_socket_impl , m_eof(false) , m_attached(true) , m_nagle(true) - // TODO: make slow start work - , m_slow_start(false) + , m_slow_start(true) , m_cwnd_full(false) , m_deferred_ack(false) { @@ -592,7 +591,11 @@ struct utp_socket_impl 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 + // only in slow-start during the start-up phase. Slow start + // (contrary to what its name suggest) means that we're growing + // the congestion window (cwnd) exponetially rather than linearly. + // this is done at startup of a socket in order to find its + // link capacity faster. This behaves similar to TCP slow start bool m_slow_start:1; // this is true as long as we have as many packets in @@ -2784,7 +2787,7 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime boost::int64_t delay_factor = (boost::int64_t(target_delay - delay) << 16) / target_delay; boost::int64_t scaled_gain; - if (delay >= target_delay / 2) + if (delay >= target_delay) { UTP_LOGV("%8p: off_target: %d slow_start -> 0\n", this, target_delay - delay); m_slow_start = false; @@ -2802,6 +2805,10 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime scaled_gain = linear_gain; } + // make sure we don't wrap the cwnd + if (scaled_gain >= INT64_MAX - m_cwnd) + scaled_gain = INT64_MAX - m_cwnd - 1; + if (scaled_gain > 0 && !m_cwnd_full && m_last_cwnd_hit + milliseconds((std::max)(m_rtt.mean(), 500)) < now) { @@ -2811,6 +2818,7 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime // this probably means we have a send rate limit, so we shouldn't make // the cwnd size any larger scaled_gain = 0; + m_slow_start = false; } UTP_LOGV("%8p: do_ledbat delay:%d off_target: %d window_factor:%f target_factor:%f " @@ -2831,6 +2839,7 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime TORRENT_ASSERT(m_cwnd > 0); } + 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) @@ -2839,6 +2848,9 @@ void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime , this, m_mtu, in_flight, int(m_adv_wnd), int(m_cwnd >> 16), acked_bytes); m_cwnd_full = false; } + + if ((m_cwnd >> 16) >= m_adv_wnd) + m_slow_start = false; } void utp_stream::bind(endpoint_type const& ep, error_code& ec) { } @@ -2906,6 +2918,8 @@ void utp_socket_impl::tick(ptime const& now) m_cwnd = boost::int64_t(m_mtu) << 16; } + TORRENT_ASSERT(m_cwnd >= 0); + if (m_outbuf.size()) ++m_num_timeouts; if (m_num_timeouts > m_sm->num_resends())