forked from premiere/premiere-libtorrent
added more logging and modified the resource allocation algorithm. A new, looser, upload and download bandwidth limiter is now used, in order to be able to use more of the available bandwidth
This commit is contained in:
parent
dd7aeba978
commit
c52de08421
|
@ -74,6 +74,11 @@ namespace libtorrent
|
|||
return accepted;
|
||||
}
|
||||
|
||||
inline int div_round_up(int numerator, int denominator)
|
||||
{
|
||||
return (numerator + denominator - 1) / denominator;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
template<class It, class T>
|
||||
|
@ -120,7 +125,11 @@ namespace libtorrent
|
|||
sum_max = saturated_add(sum_max, ((*i).*m_res).max);
|
||||
sum_min = saturated_add(sum_min, ((*i).*m_res).min);
|
||||
}
|
||||
assert(sum_given == (std::min)(std::max(m_resources, sum_min), sum_max));
|
||||
if (sum_given != (std::min)(std::max(m_resources, sum_min), sum_max))
|
||||
{
|
||||
std::cerr << sum_given << " " << m_resources << " " << sum_min << " " << sum_max << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -157,19 +166,89 @@ namespace libtorrent
|
|||
|
||||
int sum_max = 0;
|
||||
int sum_min = 0;
|
||||
// the number of consumer that saturated their
|
||||
// quota last time slice
|
||||
int num_saturated = 0;
|
||||
// the total resources those that saturated their
|
||||
// quota used. This is used to calculate the mean
|
||||
// of the saturating consumers, in order to
|
||||
// balance their quotas for the next time slice.
|
||||
size_type saturated_sum = 0;
|
||||
for (It i = start; i != end; ++i)
|
||||
{
|
||||
sum_max = saturated_add(sum_max, ((*i).*res).max);
|
||||
assert(((*i).*res).min < resource_request::inf);
|
||||
assert(((*i).*res).min >= 0);
|
||||
assert(((*i).*res).min <= ((*i).*res).max);
|
||||
sum_min += ((*i).*res).min;
|
||||
((*i).*res).given = ((*i).*res).min;
|
||||
resource_request& r = (*i).*res;
|
||||
sum_max = saturated_add(sum_max, r.max);
|
||||
assert(r.min < resource_request::inf);
|
||||
assert(r.min >= 0);
|
||||
assert(r.min <= r.max);
|
||||
sum_min += r.min;
|
||||
|
||||
// a consumer that uses 95% or more of its assigned
|
||||
// quota is considered saturating
|
||||
size_type used = r.used;
|
||||
if (used * 20 / r.given >= 19)
|
||||
{
|
||||
++num_saturated;
|
||||
saturated_sum += r.given;
|
||||
}
|
||||
}
|
||||
|
||||
if (resources == 0 || sum_max == 0)
|
||||
return;
|
||||
|
||||
if (sum_max <= resources)
|
||||
{
|
||||
// it turns out that there's no competition for resources
|
||||
// after all.
|
||||
for (It i = start; i != end; ++i)
|
||||
{
|
||||
((*i).*res).given = ((*i).*res).max;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (sum_min >= resources)
|
||||
{
|
||||
// the amount of resources is smaller than
|
||||
// the minimum resources to distribute, so
|
||||
// give everyone the minimum
|
||||
for (It i = start; i != end; ++i)
|
||||
{
|
||||
((*i).*res).given = ((*i).*res).min;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// now, the "used" field will be used as a target value.
|
||||
// the algorithm following this loop will then scale the
|
||||
// used values to fit the available resources and store
|
||||
// the scaled values as given. So, the ratios of the
|
||||
// used values will be maintained.
|
||||
for (It i = start; i != end; ++i)
|
||||
{
|
||||
resource_request& r = (*i).*res;
|
||||
|
||||
int target;
|
||||
size_type used = r.used;
|
||||
if (used * 20 / r.given >= 19)
|
||||
{
|
||||
assert(num_saturated > 0);
|
||||
target = div_round_up(saturated_sum, num_saturated);
|
||||
target += div_round_up(target, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
target = r.used;
|
||||
}
|
||||
if (target > r.max) target = r.max;
|
||||
else if (target < r.min) target = r.min;
|
||||
|
||||
// move 50% towards the the target value
|
||||
r.used = r.given + div_round_up(target - r.given, 2);
|
||||
r.given = r.min;
|
||||
}
|
||||
|
||||
|
||||
resources = (std::max)(resources, sum_min);
|
||||
int resources_to_distribute = (std::min)(resources, sum_max) - sum_min;
|
||||
assert(resources_to_distribute >= 0);
|
||||
|
@ -178,12 +257,14 @@ namespace libtorrent
|
|||
#endif
|
||||
while (resources_to_distribute > 0)
|
||||
{
|
||||
// in order to scale, we need to calculate the sum of
|
||||
// all the used values.
|
||||
size_type total_used = 0;
|
||||
size_type max_used = 0;
|
||||
for (It i = start; i != end; ++i)
|
||||
{
|
||||
resource_request& r = (*i).*res;
|
||||
if(r.given == r.max) continue;
|
||||
if (r.given == r.max) continue;
|
||||
|
||||
assert(r.given < r.max);
|
||||
|
||||
|
@ -191,19 +272,18 @@ namespace libtorrent
|
|||
total_used += (size_type)r.used + 1;
|
||||
}
|
||||
|
||||
|
||||
size_type kNumer = resources_to_distribute;
|
||||
size_type kDenom = total_used;
|
||||
assert(kNumer >= 0);
|
||||
assert(kDenom >= 0);
|
||||
assert(kNumer <= (std::numeric_limits<int>::max)());
|
||||
assert(total_used < (std::numeric_limits<int>::max)());
|
||||
|
||||
if (kNumer * max_used <= kDenom)
|
||||
{
|
||||
kNumer = 1;
|
||||
kDenom = max_used;
|
||||
assert(kDenom >= 0);
|
||||
assert(kDenom <= (std::numeric_limits<int>::max)());
|
||||
}
|
||||
|
||||
for (It i = start; i != end && resources_to_distribute > 0; ++i)
|
||||
|
@ -220,7 +300,11 @@ namespace libtorrent
|
|||
to_give = resources_to_distribute;
|
||||
assert(to_give >= 0);
|
||||
assert(to_give <= resources_to_distribute);
|
||||
#ifndef NDEBUG
|
||||
int tmp = resources_to_distribute;
|
||||
#endif
|
||||
resources_to_distribute -= give(r, (int)to_give);
|
||||
assert(resources_to_distribute <= tmp);
|
||||
assert(resources_to_distribute >= 0);
|
||||
}
|
||||
|
||||
|
@ -230,6 +314,7 @@ namespace libtorrent
|
|||
prev_resources_to_distribute = resources_to_distribute;
|
||||
#endif
|
||||
}
|
||||
assert(resources_to_distribute == 0);
|
||||
}
|
||||
|
||||
} // namespace libtorrent::aux
|
||||
|
|
|
@ -567,6 +567,12 @@ namespace libtorrent
|
|||
// can upload per second
|
||||
int m_upload_bandwidth_limit;
|
||||
int m_download_bandwidth_limit;
|
||||
|
||||
// the accumulated excess upload and download
|
||||
// bandwidth used. Used to balance out the
|
||||
// bandwidth to match the limit over time
|
||||
int m_excess_ul;
|
||||
int m_excess_dl;
|
||||
|
||||
boost::filesystem::path m_save_path;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2003, Magnus Jonsson, Arvid Norberg
|
||||
Copyright (c) 2006, Magnus Jonsson, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -742,13 +742,13 @@ namespace libtorrent
|
|||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGIGN
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "invalid extended handshake: " << exc.what() << "\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGIGN
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
std::stringstream ext;
|
||||
root.print(ext);
|
||||
(*m_logger) << "<== EXTENDED HANDSHAKE: \n" << ext.str();
|
||||
|
|
|
@ -218,6 +218,8 @@ namespace libtorrent { namespace dht
|
|||
}
|
||||
catch (std::exception& exc)
|
||||
{
|
||||
std::cerr << "exception-type: " << typeid(exc).name() << std::endl;
|
||||
std::cerr << "what: " << exc.what() << std::endl;
|
||||
assert(false);
|
||||
};
|
||||
|
||||
|
|
|
@ -351,7 +351,18 @@ namespace libtorrent
|
|||
// optimization, don't send have messages
|
||||
// to peers that already have the piece
|
||||
if (has_piece(index)) return;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
using namespace boost::posix_time;
|
||||
(*m_logger) << to_simple_string(second_clock::universal_time())
|
||||
<< " ==> HAVE [ piece: " << index << "]\n";
|
||||
#endif
|
||||
write_have(index);
|
||||
#ifndef NDEBUG
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
assert(t);
|
||||
assert(t->have_piece(index));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool peer_connection::has_piece(int i) const
|
||||
|
@ -866,6 +877,11 @@ namespace libtorrent
|
|||
&& r.length + r.start <= t->torrent_file().piece_size(r.piece)
|
||||
&& m_peer_interested)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
using namespace boost::posix_time;
|
||||
(*m_logger) << to_simple_string(second_clock::universal_time())
|
||||
<< " <== REQUEST [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
|
||||
#endif
|
||||
// if we have choked the client
|
||||
// ignore the request
|
||||
if (m_choked)
|
||||
|
@ -873,11 +889,6 @@ namespace libtorrent
|
|||
|
||||
m_requests.push_back(r);
|
||||
fill_send_buffer();
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
using namespace boost::posix_time;
|
||||
(*m_logger) << to_simple_string(second_clock::universal_time())
|
||||
<< " <== REQUEST [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n";
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -890,7 +901,8 @@ namespace libtorrent
|
|||
"l: " << r.length << " | "
|
||||
"i: " << m_peer_interested << " | "
|
||||
"t: " << (int)t->torrent_file().piece_size(r.piece) << " | "
|
||||
"n: " << t->torrent_file().num_pieces() << " ]\n";
|
||||
"n: " << t->torrent_file().num_pieces() << " | "
|
||||
"h: " << t->have_piece(r.piece) << " ]\n";
|
||||
#endif
|
||||
|
||||
++m_num_invalid_requests;
|
||||
|
|
|
@ -732,7 +732,7 @@ namespace libtorrent { namespace detail
|
|||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << endp << " <== INCOMING CONNECTION\n";
|
||||
#endif
|
||||
if (m_ip_filter.access(endp.address().to_v4()) & ip_filter::blocked)
|
||||
if (m_ip_filter.access(endp.address()) & ip_filter::blocked)
|
||||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_logger) << "filtered blocked ip\n";
|
||||
|
|
|
@ -233,6 +233,8 @@ namespace libtorrent
|
|||
, m_net_interface(net_interface.address(), 0)
|
||||
, m_upload_bandwidth_limit(std::numeric_limits<int>::max())
|
||||
, m_download_bandwidth_limit(std::numeric_limits<int>::max())
|
||||
, m_excess_ul(0)
|
||||
, m_excess_dl(0)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_compact_mode(compact_mode)
|
||||
, m_default_block_size(block_size)
|
||||
|
@ -331,6 +333,8 @@ namespace libtorrent
|
|||
, m_net_interface(net_interface.address(), 0)
|
||||
, m_upload_bandwidth_limit(std::numeric_limits<int>::max())
|
||||
, m_download_bandwidth_limit(std::numeric_limits<int>::max())
|
||||
, m_excess_ul(0)
|
||||
, m_excess_dl(0)
|
||||
, m_save_path(complete(save_path))
|
||||
, m_compact_mode(compact_mode)
|
||||
, m_default_block_size(block_size)
|
||||
|
@ -520,7 +524,7 @@ namespace libtorrent
|
|||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
m_failed_trackers = 0;
|
||||
// less than 5 minutes announce intervals
|
||||
// announce intervals less than 5 minutes
|
||||
// are insane.
|
||||
if (interval < 60 * 5) interval = 60 * 5;
|
||||
|
||||
|
@ -1125,6 +1129,13 @@ namespace libtorrent
|
|||
boost::shared_ptr<stream_socket> s(new stream_socket(m_ses.m_selector));
|
||||
boost::intrusive_ptr<peer_connection> c(new web_peer_connection(
|
||||
m_ses, shared_from_this(), s, a, url));
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_ses.m_logger) << "add url seed (" << c->m_dl_bandwidth_quota.given << ", "
|
||||
<< c->m_dl_bandwidth_quota.used << ") ";
|
||||
(*m_ses.m_logger) << "\n";
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
c->m_in_constructor = false;
|
||||
#endif
|
||||
|
@ -1176,6 +1187,14 @@ namespace libtorrent
|
|||
boost::shared_ptr<stream_socket> s(new stream_socket(m_ses.m_selector));
|
||||
boost::intrusive_ptr<peer_connection> c(new bt_peer_connection(
|
||||
m_ses, shared_from_this(), s, a));
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
(*m_ses.m_logger) << "connect_to_peer (" << c->m_dl_bandwidth_quota.given << ", "
|
||||
<< c->m_dl_bandwidth_quota.used << ") ";
|
||||
(*m_ses.m_logger) << "\n";
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
c->m_in_constructor = false;
|
||||
#endif
|
||||
|
@ -1797,13 +1816,44 @@ namespace libtorrent
|
|||
assert(m_ul_bandwidth_quota.given >= 0);
|
||||
assert(m_dl_bandwidth_quota.given >= 0);
|
||||
|
||||
int ul_used = 0;
|
||||
int dl_used = 0;
|
||||
for (peer_iterator i = m_connections.begin();
|
||||
i != m_connections.end(); ++i)
|
||||
{
|
||||
ul_used += i->second->m_ul_bandwidth_quota.used;
|
||||
dl_used += i->second->m_dl_bandwidth_quota.used;
|
||||
}
|
||||
|
||||
m_excess_ul += ul_used - m_ul_bandwidth_quota.given;
|
||||
m_excess_dl += dl_used - m_dl_bandwidth_quota.given;
|
||||
|
||||
m_excess_ul = std::max(m_excess_ul, 0);
|
||||
m_excess_dl = std::max(m_excess_dl, 0);
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
/* for (peer_iterator i = m_connections.begin();
|
||||
i != m_connections.end(); ++i)
|
||||
{
|
||||
(*m_ses.m_logger) << i->second->remote() << " (" << i->second->m_dl_bandwidth_quota.given << ", "
|
||||
<< i->second->m_dl_bandwidth_quota.used << ") ";
|
||||
}
|
||||
*/
|
||||
(*m_ses.m_logger) << m_excess_ul << " " << m_excess_dl << "\n";
|
||||
#endif
|
||||
|
||||
int ul_to_distribute = int((m_ul_bandwidth_quota.given
|
||||
- m_excess_ul) * 1.3f);
|
||||
int dl_to_distribute = int((m_dl_bandwidth_quota.given
|
||||
- m_excess_dl) * 1.3f);
|
||||
|
||||
// distribute allowed upload among the peers
|
||||
allocate_resources(m_ul_bandwidth_quota.given
|
||||
allocate_resources(ul_to_distribute
|
||||
, m_connections
|
||||
, &peer_connection::m_ul_bandwidth_quota);
|
||||
|
||||
// distribute allowed download among the peers
|
||||
allocate_resources(m_dl_bandwidth_quota.given
|
||||
allocate_resources(dl_to_distribute
|
||||
, m_connections
|
||||
, &peer_connection::m_dl_bandwidth_quota);
|
||||
|
||||
|
|
Loading…
Reference in New Issue