forked from premiere/premiere-libtorrent
merged DHT optimization from RC_0_16
This commit is contained in:
parent
5e57b13ac3
commit
2f0800523c
|
@ -9,6 +9,7 @@
|
||||||
* fix uTP edge case where udp socket buffer fills up
|
* fix uTP edge case where udp socket buffer fills up
|
||||||
* fix nagle implementation in uTP
|
* fix nagle implementation in uTP
|
||||||
|
|
||||||
|
* DHT performance improvement
|
||||||
* attempt to handle ERROR_CANT_WAIT disk error on windows
|
* attempt to handle ERROR_CANT_WAIT disk error on windows
|
||||||
* improve peers exchanged over PEX
|
* improve peers exchanged over PEX
|
||||||
* fixed rare crash in ut_metadata extension
|
* fixed rare crash in ut_metadata extension
|
||||||
|
|
|
@ -268,19 +268,13 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
rate_limited_udp_socket(io_service& ios, connection_queue& cc);
|
rate_limited_udp_socket(io_service& ios, connection_queue& cc);
|
||||||
void set_rate_limit(int limit) { m_rate_limit = limit; }
|
void set_rate_limit(int limit) { m_rate_limit = limit; }
|
||||||
bool can_send() const { return int(m_queue.size()) >= m_queue_size_limit; }
|
|
||||||
bool send(udp::endpoint const& ep, char const* p, int len, error_code& ec, int flags = 0);
|
bool send(udp::endpoint const& ep, char const* p, int len, error_code& ec, int flags = 0);
|
||||||
void close();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void on_tick(error_code const& e);
|
|
||||||
|
|
||||||
deadline_timer m_timer;
|
|
||||||
int m_queue_size_limit;
|
|
||||||
int m_rate_limit;
|
int m_rate_limit;
|
||||||
int m_quota;
|
int m_quota;
|
||||||
ptime m_last_tick;
|
ptime m_last_tick;
|
||||||
std::deque<queued_packet> m_queue;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1332,77 +1332,35 @@ void udp_socket::hung_up(error_code const& e)
|
||||||
rate_limited_udp_socket::rate_limited_udp_socket(io_service& ios
|
rate_limited_udp_socket::rate_limited_udp_socket(io_service& ios
|
||||||
, connection_queue& cc)
|
, connection_queue& cc)
|
||||||
: udp_socket(ios, cc)
|
: udp_socket(ios, cc)
|
||||||
, m_timer(ios)
|
, m_rate_limit(8000)
|
||||||
, m_queue_size_limit(200)
|
, m_quota(8000)
|
||||||
, m_rate_limit(4000)
|
|
||||||
, m_quota(4000)
|
|
||||||
, m_last_tick(time_now())
|
, m_last_tick(time_now())
|
||||||
{
|
{
|
||||||
#if defined TORRENT_ASIO_DEBUGGING
|
#if defined TORRENT_ASIO_DEBUGGING
|
||||||
add_outstanding_async("rate_limited_udp_socket::on_tick");
|
add_outstanding_async("rate_limited_udp_socket::on_tick");
|
||||||
#endif
|
#endif
|
||||||
error_code ec;
|
|
||||||
m_timer.expires_from_now(seconds(1), ec);
|
|
||||||
m_timer.async_wait(boost::bind(&rate_limited_udp_socket::on_tick, this, _1));
|
|
||||||
TORRENT_ASSERT_VAL(!ec, ec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rate_limited_udp_socket::send(udp::endpoint const& ep, char const* p
|
bool rate_limited_udp_socket::send(udp::endpoint const& ep, char const* p
|
||||||
, int len, error_code& ec, int flags)
|
, int len, error_code& ec, int flags)
|
||||||
{
|
{
|
||||||
if (m_quota < len)
|
ptime now = time_now_hires();
|
||||||
{
|
time_duration delta = now - m_last_tick;
|
||||||
if (int(m_queue.size()) >= m_queue_size_limit && (flags & dont_drop) == 0)
|
m_last_tick = now;
|
||||||
return false;
|
|
||||||
m_queue.push_back(queued_packet());
|
// add any new quota we've accrued since last time
|
||||||
queued_packet& qp = m_queue.back();
|
m_quota += boost::uint64_t(m_rate_limit) * total_microseconds(delta) / 1000000;
|
||||||
qp.ep = ep;
|
|
||||||
qp.flags = flags;
|
// allow 3 seconds worth of burst
|
||||||
qp.buf.insert(qp.buf.begin(), p, p + len);
|
if (m_quota > 3 * m_rate_limit) m_quota = 3 * m_rate_limit;
|
||||||
return true;
|
|
||||||
}
|
// if there's no quota, and it's OK to drop, just
|
||||||
|
// drop the packet
|
||||||
|
if (m_quota < len && (flags & dont_drop) == 0) return false;
|
||||||
|
|
||||||
m_quota -= len;
|
m_quota -= len;
|
||||||
|
if (m_quota < 0) m_quota = 0;
|
||||||
udp_socket::send(ep, p, len, ec, flags);
|
udp_socket::send(ep, p, len, ec, flags);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rate_limited_udp_socket::on_tick(error_code const& e)
|
|
||||||
{
|
|
||||||
#if defined TORRENT_ASIO_DEBUGGING
|
|
||||||
complete_async("rate_limited_udp_socket::on_tick");
|
|
||||||
#endif
|
|
||||||
if (e) return;
|
|
||||||
if (is_closed()) return;
|
|
||||||
error_code ec;
|
|
||||||
ptime now = time_now_hires();
|
|
||||||
#if defined TORRENT_ASIO_DEBUGGING
|
|
||||||
add_outstanding_async("rate_limited_udp_socket::on_tick");
|
|
||||||
#endif
|
|
||||||
m_timer.expires_at(now + seconds(1), ec);
|
|
||||||
m_timer.async_wait(boost::bind(&rate_limited_udp_socket::on_tick, this, _1));
|
|
||||||
|
|
||||||
time_duration delta = now - m_last_tick;
|
|
||||||
m_last_tick = now;
|
|
||||||
if (m_quota < m_rate_limit) m_quota += boost::uint64_t(m_rate_limit) * total_milliseconds(delta) / 1000;
|
|
||||||
|
|
||||||
if (m_queue.empty()) return;
|
|
||||||
|
|
||||||
while (!m_queue.empty() && int(m_queue.front().buf.size()) <= m_quota)
|
|
||||||
{
|
|
||||||
queued_packet const& p = m_queue.front();
|
|
||||||
TORRENT_ASSERT(m_quota >= int(p.buf.size()));
|
|
||||||
m_quota -= p.buf.size();
|
|
||||||
error_code ec;
|
|
||||||
udp_socket::send(p.ep, &p.buf[0], p.buf.size(), ec, p.flags);
|
|
||||||
m_queue.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void rate_limited_udp_socket::close()
|
|
||||||
{
|
|
||||||
error_code ec;
|
|
||||||
m_timer.cancel(ec);
|
|
||||||
udp_socket::close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue