take an estimate of the IP ACK traffic into account when rate limiting (allows setting rate limits closer to the capacity)

This commit is contained in:
Arvid Norberg 2008-05-05 17:08:14 +00:00
parent d15573ecc2
commit e09457e4ab
6 changed files with 61 additions and 2 deletions

View File

@ -76,6 +76,8 @@ struct history_entry
history_entry(intrusive_ptr<PeerConnection> p, weak_ptr<Torrent> t history_entry(intrusive_ptr<PeerConnection> p, weak_ptr<Torrent> t
, int a, ptime exp) , int a, ptime exp)
: expires_at(exp), amount(a), peer(p), tor(t) {} : expires_at(exp), amount(a), peer(p), tor(t) {}
history_entry(int a, ptime exp)
: expires_at(exp), amount(a), peer(), tor() {}
ptime expires_at; ptime expires_at;
int amount; int amount;
intrusive_ptr<PeerConnection> peer; intrusive_ptr<PeerConnection> peer;
@ -111,6 +113,7 @@ struct bandwidth_manager
: m_ios(ios) : m_ios(ios)
, m_history_timer(m_ios) , m_history_timer(m_ios)
, m_limit(bandwidth_limit::inf) , m_limit(bandwidth_limit::inf)
, m_drain_quota(0)
, m_current_quota(0) , m_current_quota(0)
, m_channel(channel) , m_channel(channel)
, m_in_hand_out_bandwidth(false) , m_in_hand_out_bandwidth(false)
@ -123,6 +126,14 @@ struct bandwidth_manager
#endif #endif
} }
void drain(int bytes)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(bytes >= 0);
m_drain_quota += bytes;
if (m_drain_quota > m_limit * 5) m_drain_quota = m_limit * 5;
}
void throttle(int limit) void throttle(int limit)
{ {
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
@ -288,6 +299,7 @@ private:
<< std::endl; << std::endl;
#endif #endif
intrusive_ptr<PeerConnection> c = e.peer; intrusive_ptr<PeerConnection> c = e.peer;
if (!c) continue;
shared_ptr<Torrent> t = e.tor.lock(); shared_ptr<Torrent> t = e.tor.lock();
l.unlock(); l.unlock();
if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount); if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount);
@ -329,6 +341,15 @@ private:
if (amount <= 0) return; if (amount <= 0) return;
if (m_drain_quota > 0)
{
int drain_amount = (std::min)(m_drain_quota, amount);
m_drain_quota -= drain_amount;
amount -= drain_amount;
add_history_entry(history_entry<PeerConnection, Torrent>(
drain_amount, now + bw_window_size));
}
queue_t tmp; queue_t tmp;
while (!m_queue.empty() && amount > 0) while (!m_queue.empty() && amount > 0)
{ {
@ -433,6 +454,10 @@ private:
// the rate limit (bytes per second) // the rate limit (bytes per second)
int m_limit; int m_limit;
// bytes to drain without handing out to a peer
// used to deduct the IP overhead
int m_drain_quota;
// the sum of all recently handed out bandwidth blocks // the sum of all recently handed out bandwidth blocks
int m_current_quota; int m_current_quota;

View File

@ -230,6 +230,8 @@ namespace libtorrent
const stat& statistics() const { return m_statistics; } const stat& statistics() const { return m_statistics; }
void add_stat(size_type downloaded, size_type uploaded); void add_stat(size_type downloaded, size_type uploaded);
void calc_ip_overhead();
// is called once every second by the main loop // is called once every second by the main loop
void second_tick(float tick_interval); void second_tick(float tick_interval);

View File

@ -140,6 +140,24 @@ namespace libtorrent
m_stat[upload_protocol].add(bytes_protocol); m_stat[upload_protocol].add(bytes_protocol);
} }
// calculate ip protocol overhead
void calc_ip_overhead()
{
// traffic balance is the number of bytes we downloaded
// more than we uploaded
int traffic_balance = m_stat[download_protocol].counter()
+ m_stat[download_payload].counter()
- m_stat[upload_protocol].counter()
- m_stat[upload_payload].counter();
if (traffic_balance > 0)
m_stat[upload_ip_protocol].add(traffic_balance / 20);
else
m_stat[download_ip_protocol].add(-traffic_balance / 20);
}
int upload_ip_overhead() const { return m_stat[upload_ip_protocol].counter(); }
int download_ip_overhead() const { return m_stat[download_ip_protocol].counter(); }
// should be called once every second // should be called once every second
void second_tick(float tick_interval) void second_tick(float tick_interval)
{ {
@ -150,13 +168,15 @@ namespace libtorrent
float upload_rate() const float upload_rate() const
{ {
return m_stat[upload_payload].rate() return m_stat[upload_payload].rate()
+ m_stat[upload_protocol].rate(); + m_stat[upload_protocol].rate()
+ m_stat[upload_ip_protocol].rate();
} }
float download_rate() const float download_rate() const
{ {
return m_stat[download_payload].rate() return m_stat[download_payload].rate()
+ m_stat[download_protocol].rate(); + m_stat[download_protocol].rate()
+ m_stat[download_ip_protocol].rate();
} }
float upload_payload_rate() const float upload_payload_rate() const
@ -198,8 +218,10 @@ namespace libtorrent
{ {
upload_payload, upload_payload,
upload_protocol, upload_protocol,
upload_ip_protocol,
download_payload, download_payload,
download_protocol, download_protocol,
download_ip_protocol,
num_channels num_channels
}; };

View File

@ -2413,6 +2413,11 @@ namespace libtorrent
m_packet_size = packet_size; m_packet_size = packet_size;
} }
void peer_connection::calc_ip_overhead()
{
m_statistics.calc_ip_overhead();
}
void peer_connection::second_tick(float tick_interval) void peer_connection::second_tick(float tick_interval)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;

View File

@ -1046,6 +1046,10 @@ namespace aux {
++i; ++i;
} }
// drain the IP overhead from the bandwidth limiters
m_download_channel.drain(m_stat.download_ip_overhead());
m_upload_channel.drain(m_stat.upload_ip_overhead());
m_stat.second_tick(tick_interval); m_stat.second_tick(tick_interval);

View File

@ -3489,6 +3489,7 @@ namespace libtorrent
{ {
peer_connection* p = *i; peer_connection* p = *i;
++i; ++i;
p->calc_ip_overhead();
m_stat += p->statistics(); m_stat += p->statistics();
// updates the peer connection's ul/dl bandwidth // updates the peer connection's ul/dl bandwidth
// resource requests // resource requests