added feature to set a separate global rate limit for local peers

This commit is contained in:
Arvid Norberg 2009-05-14 17:21:19 +00:00
parent 28c334fb35
commit 31c422df0a
7 changed files with 170 additions and 46 deletions

View File

@ -1,3 +1,4 @@
* added feature to set a separate global rate limit for local peers
* added preset settings for low memory environments and seed machines * added preset settings for low memory environments and seed machines
min_memory_usage() and high_performance_seeder() min_memory_usage() and high_performance_seeder()
* optimized overall memory usage for DHT nodes and requests, peer * optimized overall memory usage for DHT nodes and requests, peer

View File

@ -229,6 +229,11 @@ namespace libtorrent
int upload_rate_limit() const; int upload_rate_limit() const;
int download_rate_limit() const; int download_rate_limit() const;
int local_upload_rate_limit() const;
int local_download_rate_limit() const;
void set_local_download_rate_limit(int bytes_per_second);
void set_local_upload_rate_limit(int bytes_per_second);
void set_download_rate_limit(int bytes_per_second); void set_download_rate_limit(int bytes_per_second);
void set_upload_rate_limit(int bytes_per_second); void set_upload_rate_limit(int bytes_per_second);
@ -426,9 +431,18 @@ namespace libtorrent
bandwidth_manager<peer_connection> m_download_rate; bandwidth_manager<peer_connection> m_download_rate;
bandwidth_manager<peer_connection> m_upload_rate; bandwidth_manager<peer_connection> m_upload_rate;
// the global rate limiter bandwidth channels
bandwidth_channel m_download_channel; bandwidth_channel m_download_channel;
bandwidth_channel m_upload_channel; bandwidth_channel m_upload_channel;
// bandwidth channels for local peers when
// rate limits are ignored. They are only
// throttled by these global rate limiters
// and they don't have a rate limit set by
// default
bandwidth_channel m_local_download_channel;
bandwidth_channel m_local_upload_channel;
bandwidth_channel* m_bandwidth_channel[2]; bandwidth_channel* m_bandwidth_channel[2];
tracker_manager m_tracker_manager; tracker_manager m_tracker_manager;

View File

@ -634,6 +634,16 @@ namespace libtorrent
void on_disk_read_complete(int ret, disk_io_job const& j, peer_request r); void on_disk_read_complete(int ret, disk_io_job const& j, peer_request r);
void on_disk_write_complete(int ret, disk_io_job const& j void on_disk_write_complete(int ret, disk_io_job const& j
, peer_request r, boost::shared_ptr<torrent> t); , peer_request r, boost::shared_ptr<torrent> t);
void request_upload_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2 = 0
, bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 0);
void request_download_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2 = 0
, bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 0);
// keep the io_service running as long as we // keep the io_service running as long as we
// have peer connections // have peer connections

View File

@ -370,8 +370,12 @@ namespace libtorrent
int upload_rate_limit() const; int upload_rate_limit() const;
int download_rate_limit() const; int download_rate_limit() const;
int local_upload_rate_limit() const;
int local_download_rate_limit() const;
int max_half_open_connections() const; int max_half_open_connections() const;
void set_local_upload_rate_limit(int bytes_per_second);
void set_local_download_rate_limit(int bytes_per_second);
void set_upload_rate_limit(int bytes_per_second); void set_upload_rate_limit(int bytes_per_second);
void set_download_rate_limit(int bytes_per_second); void set_download_rate_limit(int bytes_per_second);
void set_max_uploads(int limit); void set_max_uploads(int limit);

View File

@ -3565,6 +3565,47 @@ namespace libtorrent
} }
} }
void peer_connection::request_upload_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2
, bandwidth_channel* bwc3
, bandwidth_channel* bwc4)
{
shared_ptr<torrent> t = m_torrent.lock();
int priority = 1 + is_interesting() * 2 + m_requests_in_buffer.size();
// peers that we are not interested in are non-prioritized
m_channel_state[upload_channel] = peer_info::bw_limit;
m_ses.m_upload_rate.request_bandwidth(self()
, m_send_buffer.size(), priority
, bwc1, bwc2, bwc3, bwc4);
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ "
"upload: " << m_send_buffer.size()
<< " prio: " << priority << "]\n";
#endif
}
void peer_connection::request_download_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2
, bandwidth_channel* bwc3
, bandwidth_channel* bwc4)
{
shared_ptr<torrent> t = m_torrent.lock();
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ "
"download: " << (m_download_queue.size() * 16 * 1024 + 30)
<< " prio: " << m_priority << " ]\n";
#endif
TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle);
TORRENT_ASSERT(m_outstanding_bytes >= 0);
m_channel_state[download_channel] = peer_info::bw_limit;
m_ses.m_download_rate.request_bandwidth(self()
, m_outstanding_bytes + 30, m_priority
, bwc1, bwc2, bwc3, bwc4);
}
void peer_connection::setup_send() void peer_connection::setup_send()
{ {
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
@ -3576,26 +3617,27 @@ namespace libtorrent
if (m_quota[upload_channel] == 0 if (m_quota[upload_channel] == 0
&& !m_send_buffer.empty() && !m_send_buffer.empty()
&& !m_connecting && !m_connecting
&& t && t)
&& !m_ignore_bandwidth_limits)
{ {
// in this case, we have data to send, but no if (!m_ignore_bandwidth_limits)
// bandwidth. So, we simply request bandwidth {
// from the torrent // in this case, we have data to send, but no
TORRENT_ASSERT(t); // bandwidth. So, we simply request bandwidth
int priority = 1 + is_interesting() * 2 + m_requests_in_buffer.size(); // from the bandwidth manager
// peers that we are not interested in are non-prioritized request_upload_bandwidth(
m_channel_state[upload_channel] = peer_info::bw_limit; &m_ses.m_upload_channel
m_ses.m_upload_rate.request_bandwidth(self() , &t->m_bandwidth_channel[upload_channel]
, m_send_buffer.size(), priority , &m_bandwidth_channel[upload_channel]);
, &m_ses.m_upload_channel }
, &t->m_bandwidth_channel[upload_channel] else
, &m_bandwidth_channel[upload_channel]); {
#ifdef TORRENT_VERBOSE_LOGGING // in this case, we're a local peer, and the settings
(*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ " // are set to ignore rate limits for local peers. So,
"upload: " << m_send_buffer.size() // instead we rate limit ourself against the special
<< " prio: " << priority << "]\n"; // global bandwidth channel for local peers, which defaults
#endif // to unthrottled
request_upload_bandwidth(&m_ses.m_local_upload_channel);
}
return; return;
} }
@ -3656,22 +3698,27 @@ namespace libtorrent
if (m_quota[download_channel] == 0 if (m_quota[download_channel] == 0
&& !m_connecting && !m_connecting
&& t && t)
&& !m_ignore_bandwidth_limits)
{ {
#ifdef TORRENT_VERBOSE_LOGGING if (!m_ignore_bandwidth_limits)
(*m_logger) << time_now_string() << " *** REQUEST_BANDWIDTH [ " {
"download: " << (m_download_queue.size() * 16 * 1024 + 30) // in this case, we have outstanding data to
<< " prio: " << m_priority << " ]\n"; // receive, but no bandwidth quota. So, we simply
#endif // request bandwidth from the bandwidth manager
TORRENT_ASSERT(m_channel_state[download_channel] == peer_info::bw_idle); request_download_bandwidth(
TORRENT_ASSERT(m_outstanding_bytes >= 0); &m_ses.m_download_channel
m_channel_state[download_channel] = peer_info::bw_limit; , &t->m_bandwidth_channel[download_channel]
m_ses.m_download_rate.request_bandwidth(self() , &m_bandwidth_channel[download_channel]);
, m_outstanding_bytes + 30, m_priority }
, &m_ses.m_download_channel else
, &t->m_bandwidth_channel[download_channel] {
, &m_bandwidth_channel[download_channel]); // in this case, we're a local peer, and the settings
// are set to ignore rate limits for local peers. So,
// instead we rate limit ourself against the special
// global bandwidth channel for local peers, which defaults
// to unthrottled
request_download_bandwidth(&m_ses.m_local_download_channel);
}
return; return;
} }

View File

@ -652,6 +652,16 @@ namespace libtorrent
m_impl->set_max_half_open_connections(limit); m_impl->set_max_half_open_connections(limit);
} }
int session::local_upload_rate_limit() const
{
return m_impl->local_upload_rate_limit();
}
int session::local_download_rate_limit() const
{
return m_impl->local_download_rate_limit();
}
int session::upload_rate_limit() const int session::upload_rate_limit() const
{ {
return m_impl->upload_rate_limit(); return m_impl->upload_rate_limit();
@ -662,6 +672,16 @@ namespace libtorrent
return m_impl->download_rate_limit(); return m_impl->download_rate_limit();
} }
void session::set_local_upload_rate_limit(int bytes_per_second)
{
m_impl->set_local_upload_rate_limit(bytes_per_second);
}
void session::set_local_download_rate_limit(int bytes_per_second)
{
m_impl->set_local_download_rate_limit(bytes_per_second);
}
void session::set_upload_rate_limit(int bytes_per_second) void session::set_upload_rate_limit(int bytes_per_second)
{ {
m_impl->set_upload_rate_limit(bytes_per_second); m_impl->set_upload_rate_limit(bytes_per_second);

View File

@ -1772,7 +1772,8 @@ namespace aux {
// assume a reasonable rate is 3 kB/s, unless there's an upload limit and // assume a reasonable rate is 3 kB/s, unless there's an upload limit and
// a max number of slots, in which case we assume each upload slot gets // a max number of slots, in which case we assume each upload slot gets
// roughly the same amount of bandwidth // roughly the same amount of bandwidth
if (m_upload_channel.throttle() != bandwidth_channel::inf && m_max_uploads > 0) TORRENT_ASSERT(m_upload_channel.throttle() != bandwidth_channel::inf);
if (m_upload_channel.throttle() > 0 && m_max_uploads > 0)
rate = (std::max)(m_upload_channel.throttle() / m_max_uploads, 1); rate = (std::max)(m_upload_channel.throttle() / m_max_uploads, 1);
// the time it takes to download one piece at this rate (in seconds) // the time it takes to download one piece at this rate (in seconds)
@ -2665,14 +2666,34 @@ namespace aux {
m_half_open.limit(limit); m_half_open.limit(limit);
} }
void session_impl::set_local_download_rate_limit(int bytes_per_second)
{
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK;
if (bytes_per_second <= 0) bytes_per_second = 0;
m_local_download_channel.throttle(bytes_per_second);
}
void session_impl::set_local_upload_rate_limit(int bytes_per_second)
{
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK;
if (bytes_per_second <= 0) bytes_per_second = 0;
m_local_upload_channel.throttle(bytes_per_second);
}
void session_impl::set_download_rate_limit(int bytes_per_second) void session_impl::set_download_rate_limit(int bytes_per_second)
{ {
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK; INVARIANT_CHECK;
if (bytes_per_second <= 0) bytes_per_second = bandwidth_channel::inf; if (bytes_per_second <= 0) bytes_per_second = 0;
m_bandwidth_channel[peer_connection::download_channel]->throttle(bytes_per_second); m_download_channel.throttle(bytes_per_second);
} }
void session_impl::set_upload_rate_limit(int bytes_per_second) void session_impl::set_upload_rate_limit(int bytes_per_second)
@ -2681,8 +2702,8 @@ namespace aux {
INVARIANT_CHECK; INVARIANT_CHECK;
if (bytes_per_second <= 0) bytes_per_second = bandwidth_channel::inf; if (bytes_per_second <= 0) bytes_per_second = 0;
m_bandwidth_channel[peer_connection::upload_channel]->throttle(bytes_per_second); m_upload_channel.throttle(bytes_per_second);
} }
void session_impl::set_alert_dispatch(boost::function<void(alert const&)> const& fun) void session_impl::set_alert_dispatch(boost::function<void(alert const&)> const& fun)
@ -2720,21 +2741,28 @@ namespace aux {
return m_alerts.set_alert_queue_size_limit(queue_size_limit_); return m_alerts.set_alert_queue_size_limit(queue_size_limit_);
} }
int session_impl::local_upload_rate_limit() const
{
mutex_t::scoped_lock l(m_mutex);
return m_local_upload_channel.throttle();
}
int session_impl::local_download_rate_limit() const
{
mutex_t::scoped_lock l(m_mutex);
return m_local_download_channel.throttle();
}
int session_impl::upload_rate_limit() const int session_impl::upload_rate_limit() const
{ {
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
return m_upload_channel.throttle();
INVARIANT_CHECK;
int ret = m_bandwidth_channel[peer_connection::upload_channel]->throttle();
return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
} }
int session_impl::download_rate_limit() const int session_impl::download_rate_limit() const
{ {
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
int ret = m_bandwidth_channel[peer_connection::download_channel]->throttle(); return m_download_channel.throttle();
return ret == (std::numeric_limits<int>::max)() ? -1 : ret;
} }
void session_impl::start_lsd() void session_impl::start_lsd()