forked from premiere/premiere-libtorrent
made a bias to give connection attempts to downloading torrents with few peers. Should accelerate downloads on windows (where there's a half-open connection limit)
This commit is contained in:
parent
2014e312b1
commit
ffecb32b81
|
@ -1,3 +1,5 @@
|
|||
* Better bias to give connections to downloading torrents
|
||||
with fewer peers.
|
||||
* Optimized resource usage (removed the checking thread)
|
||||
* Support to bind outgoing connections to specific ports
|
||||
* Disk cache support.
|
||||
|
|
|
@ -280,6 +280,7 @@ namespace libtorrent
|
|||
|
||||
bool want_more_peers() const;
|
||||
bool try_connect_peer();
|
||||
void give_connect_points(int points);
|
||||
|
||||
// the number of peers that belong to this torrent
|
||||
int num_peers() const { return (int)m_connections.size(); }
|
||||
|
@ -816,6 +817,19 @@ namespace libtorrent
|
|||
// total_done - m_initial_done <= total_payload_download
|
||||
size_type m_initial_done;
|
||||
#endif
|
||||
// this is the deficit counter in the Deficit Round Robin
|
||||
// used to determine which torrent gets the next
|
||||
// connection attempt. See:
|
||||
// http://www.ecs.umass.edu/ece/wolf/courses/ECE697J/papers/DRR.pdf
|
||||
// The quanta assigned to each torrent depends on the torrents
|
||||
// priority, whether it's seed and the number of connected
|
||||
// peers it has. This has the effect that some torrents
|
||||
// will have more connection attempts than other. Each
|
||||
// connection attempt costs 100 points from the deficit
|
||||
// counter. points are deducted in try_connect_peer and
|
||||
// increased in give_connect_points. Outside of the
|
||||
// torrent object, these points are called connect_points.
|
||||
int m_deficit_counter;
|
||||
|
||||
policy m_policy;
|
||||
};
|
||||
|
|
|
@ -847,7 +847,72 @@ namespace aux {
|
|||
<< std::endl;
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// second_tick every torrent
|
||||
// --------------------------------------------------------------
|
||||
|
||||
int congested_torrents = 0;
|
||||
int uncongested_torrents = 0;
|
||||
|
||||
// count the number of seeding torrents vs. downloading
|
||||
// torrents we are running
|
||||
int num_seeds = 0;
|
||||
int num_downloads = 0;
|
||||
|
||||
// count the number of peers of downloading torrents
|
||||
int num_downloads_peers = 0;
|
||||
|
||||
// check each torrent for tracker updates
|
||||
// TODO: do this in a timer-event in each torrent instead
|
||||
for (torrent_map::iterator i = m_torrents.begin();
|
||||
i != m_torrents.end();)
|
||||
{
|
||||
torrent& t = *i->second;
|
||||
TORRENT_ASSERT(!t.is_aborted());
|
||||
if (t.bandwidth_queue_size(peer_connection::upload_channel))
|
||||
++congested_torrents;
|
||||
else
|
||||
++uncongested_torrents;
|
||||
|
||||
if (t.is_finished())
|
||||
{
|
||||
++num_seeds;
|
||||
}
|
||||
else
|
||||
{
|
||||
++num_downloads;
|
||||
num_downloads_peers += t.num_peers();
|
||||
}
|
||||
|
||||
if (t.should_request())
|
||||
{
|
||||
tracker_request req = t.generate_tracker_request();
|
||||
req.listen_port = 0;
|
||||
if (!m_listen_sockets.empty())
|
||||
req.listen_port = m_listen_sockets.front().external_port;
|
||||
req.key = m_key;
|
||||
m_tracker_manager.queue_request(m_io_service, m_half_open, req
|
||||
, t.tracker_login(), m_listen_interface.address(), i->second);
|
||||
|
||||
if (m_alerts.should_post(alert::info))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
tracker_announce_alert(
|
||||
t.get_handle(), "tracker announce"));
|
||||
}
|
||||
}
|
||||
|
||||
t.second_tick(m_stat, tick_interval);
|
||||
++i;
|
||||
}
|
||||
|
||||
m_stat.second_tick(tick_interval);
|
||||
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// connect new peers
|
||||
// --------------------------------------------------------------
|
||||
|
||||
// let torrents connect to peers if they want to
|
||||
// if there are any torrents and any free slots
|
||||
|
||||
|
@ -864,6 +929,9 @@ namespace aux {
|
|||
// this is the maximum number of connections we will
|
||||
// attempt this tick
|
||||
int max_connections = m_settings.connection_speed;
|
||||
int average_peers = 0;
|
||||
if (num_downloads > 0)
|
||||
average_peers = num_downloads_peers / num_downloads;
|
||||
|
||||
torrent_map::iterator i = m_torrents.begin();
|
||||
if (m_next_connect_torrent < int(m_torrents.size()))
|
||||
|
@ -877,6 +945,21 @@ namespace aux {
|
|||
torrent& t = *i->second;
|
||||
if (t.want_more_peers())
|
||||
{
|
||||
int connect_points = 100;
|
||||
// have a bias against torrents with more peers
|
||||
// than average
|
||||
if (!t.is_seed() && t.num_peers() > average_peers)
|
||||
connect_points /= 2;
|
||||
// if this is a seed and there is a torrent that
|
||||
// is downloading, lower the rate at which this
|
||||
// torrent gets connections.
|
||||
// dividing by num_seeds will have the effect
|
||||
// that all seed will get as many connections
|
||||
// together, as a single downloading torrent.
|
||||
if (t.is_seed() && num_downloads > 0)
|
||||
connect_points /= num_seeds + 1;
|
||||
if (connect_points <= 0) connect_points = 1;
|
||||
t.give_connect_points(connect_points);
|
||||
try
|
||||
{
|
||||
if (t.try_connect_peer())
|
||||
|
@ -904,9 +987,9 @@ namespace aux {
|
|||
i = m_torrents.begin();
|
||||
m_next_connect_torrent = 0;
|
||||
}
|
||||
// if we have gone one whole loop without
|
||||
// if we have gone two whole loops without
|
||||
// handing out a single connection, break
|
||||
if (steps_since_last_connect > num_torrents) break;
|
||||
if (steps_since_last_connect > num_torrents * 2) break;
|
||||
// if there are no more free connection slots, abort
|
||||
if (free_slots <= -m_half_open.limit()) break;
|
||||
// if we should not make any more connections
|
||||
|
@ -953,45 +1036,6 @@ namespace aux {
|
|||
c.keep_alive();
|
||||
}
|
||||
|
||||
int congested_torrents = 0;
|
||||
int uncongested_torrents = 0;
|
||||
// check each torrent for tracker updates
|
||||
// TODO: do this in a timer-event in each torrent instead
|
||||
for (torrent_map::iterator i = m_torrents.begin();
|
||||
i != m_torrents.end();)
|
||||
{
|
||||
torrent& t = *i->second;
|
||||
TORRENT_ASSERT(!t.is_aborted());
|
||||
if (t.bandwidth_queue_size(peer_connection::upload_channel))
|
||||
++congested_torrents;
|
||||
else
|
||||
++uncongested_torrents;
|
||||
|
||||
if (t.should_request())
|
||||
{
|
||||
tracker_request req = t.generate_tracker_request();
|
||||
req.listen_port = 0;
|
||||
if (!m_listen_sockets.empty())
|
||||
req.listen_port = m_listen_sockets.front().external_port;
|
||||
req.key = m_key;
|
||||
m_tracker_manager.queue_request(m_io_service, m_half_open, req
|
||||
, t.tracker_login(), m_listen_interface.address(), i->second);
|
||||
|
||||
if (m_alerts.should_post(alert::info))
|
||||
{
|
||||
m_alerts.post_alert(
|
||||
tracker_announce_alert(
|
||||
t.get_handle(), "tracker announce"));
|
||||
}
|
||||
}
|
||||
|
||||
// second_tick() will set the used upload quota
|
||||
t.second_tick(m_stat, tick_interval);
|
||||
++i;
|
||||
}
|
||||
|
||||
m_stat.second_tick(tick_interval);
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// unchoke set and optimistic unchoke calculations
|
||||
// --------------------------------------------------------------
|
||||
|
|
|
@ -204,6 +204,7 @@ namespace libtorrent
|
|||
, m_max_uploads((std::numeric_limits<int>::max)())
|
||||
, m_num_uploads(0)
|
||||
, m_max_connections((std::numeric_limits<int>::max)())
|
||||
, m_deficit_counter(0)
|
||||
, m_policy(this)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
|
@ -268,6 +269,7 @@ namespace libtorrent
|
|||
, m_max_uploads((std::numeric_limits<int>::max)())
|
||||
, m_num_uploads(0)
|
||||
, m_max_connections((std::numeric_limits<int>::max)())
|
||||
, m_deficit_counter(0)
|
||||
, m_policy(this)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
|
@ -2312,6 +2314,7 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(peerinfo);
|
||||
TORRENT_ASSERT(peerinfo->connection == 0);
|
||||
|
||||
peerinfo->connected = time_now();
|
||||
#ifndef NDEBUG
|
||||
// this asserts that we don't have duplicates in the policy's peer list
|
||||
|
@ -3269,7 +3272,18 @@ namespace libtorrent
|
|||
bool torrent::try_connect_peer()
|
||||
{
|
||||
TORRENT_ASSERT(want_more_peers());
|
||||
return m_policy.connect_one_peer();
|
||||
if (m_deficit_counter < 100) return false;
|
||||
m_deficit_counter -= 100;
|
||||
bool ret = m_policy.connect_one_peer();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void torrent::give_connect_points(int points)
|
||||
{
|
||||
TORRENT_ASSERT(points <= 100);
|
||||
TORRENT_ASSERT(points > 0);
|
||||
TORRENT_ASSERT(want_more_peers());
|
||||
m_deficit_counter += points;
|
||||
}
|
||||
|
||||
void torrent::async_verify_piece(int piece_index, boost::function<void(bool)> const& f)
|
||||
|
|
Loading…
Reference in New Issue