merged swarm startup optimization from libtorrent_aio

This commit is contained in:
Arvid Norberg 2012-11-03 03:50:12 +00:00
parent 37f3a70da0
commit f3ec86169e
4 changed files with 132 additions and 37 deletions

View File

@ -245,6 +245,12 @@ namespace libtorrent
void open_listen_port(int flags, error_code& ec);
// prioritize this torrent to be allocated some connection
// attempts, because this torrent needs more peers.
// this is typically done when a torrent starts out and
// need the initial push to connect peers
void prioritize_connections(boost::weak_ptr<torrent> t);
// if we are listening on an IPv6 interface
// this will return one of the IPv6 addresses on this
// machine, otherwise just an empty endpoint
@ -294,6 +300,11 @@ namespace libtorrent
void stop_dht();
void start_dht(entry const& startup_state);
// this is called for torrents when they are started
// it will prioritize them for announcing to
// the DHT, to get the initial peers quickly
void prioritize_dht(boost::weak_ptr<torrent> t);
#ifndef TORRENT_NO_DEPRECATE
entry dht_state() const;
#endif
@ -556,6 +567,8 @@ namespace libtorrent
void update_connections_limit();
void update_unchoke_limit();
void trigger_auto_manage();
void on_trigger_auto_manage();
void update_rate_settings();
void update_disk_thread_settings();
@ -960,6 +973,9 @@ namespace libtorrent
std::deque<boost::weak_ptr<torrent> > m_dht_torrents;
#endif
// torrents prioritized to get connection attempts
std::deque<std::pair<boost::weak_ptr<torrent>, int> > m_prio_torrents;
// this announce timer is used
// by Local service discovery
deadline_timer m_lsd_announce_timer;
@ -1189,6 +1205,20 @@ namespace libtorrent
size_type m_total_failed_bytes;
size_type m_total_redundant_bytes;
// this is set to true when a torrent auto-manage
// event is triggered, and reset whenever the message
// is delivered and the auto-manage is executed.
// there should never be more than a single pending auto-manage
// message in-flight at any given time.
bool m_pending_auto_manage;
// this is also set to true when triggering an auto-manage
// of the torrents. However, if the normal auto-manage
// timer comes along and executes the auto-management,
// this is set to false, which means the triggered event
// no longer needs to execute the auto-management.
bool m_need_auto_manage;
// redundant bytes per category
size_type m_redundant_bytes[7];

View File

@ -462,6 +462,10 @@ namespace libtorrent
// base64 encoding).
std::string tracker_login() const;
// if we need a connect boost, connect some peers
// immediately
void do_connect_boost();
// returns the absolute time when the next tracker
// announce will take place.
ptime next_announce() const;

View File

@ -670,6 +670,8 @@ namespace aux {
#endif
, m_total_failed_bytes(0)
, m_total_redundant_bytes(0)
, m_pending_auto_manage(false)
, m_need_auto_manage(false)
#if (defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS) && defined BOOST_HAS_PTHREADS
, m_network_thread(0)
#endif
@ -1307,6 +1309,23 @@ namespace aux {
m_thread.reset(new thread(boost::bind(&session_impl::main_thread, this)));
}
void session_impl::trigger_auto_manage()
{
if (m_pending_auto_manage) return;
m_pending_auto_manage = true;
m_need_auto_manage = true;
m_io_service.post(boost::bind(&session_impl::on_trigger_auto_manage, this));
}
void session_impl::on_trigger_auto_manage()
{
assert(m_pending_auto_manage);
m_pending_auto_manage = false;
if (!m_need_auto_manage) return;
recalculate_auto_managed_torrents();
}
void session_impl::update_dht_announce_interval()
{
#ifndef TORRENT_DISABLE_DHT
@ -1665,15 +1684,6 @@ namespace aux {
}
#endif
#ifndef TORRENT_DISABLE_DHT
void session_impl::add_dht_node(udp::endpoint n)
{
TORRENT_ASSERT(is_network_thread());
if (m_dht) m_dht->add_node(n);
}
#endif
feed_handle session_impl::add_feed(feed_settings const& sett)
{
TORRENT_ASSERT(is_network_thread());
@ -3972,8 +3982,37 @@ retry:
m_next_rss_update = min_update;
}
void session_impl::prioritize_connections(boost::weak_ptr<torrent> t)
{
m_prio_torrents.push_back(std::make_pair(t, 10));
}
#ifndef TORRENT_DISABLE_DHT
void session_impl::add_dht_node(udp::endpoint n)
{
TORRENT_ASSERT(is_network_thread());
if (m_dht) m_dht->add_node(n);
}
void session_impl::prioritize_dht(boost::weak_ptr<torrent> t)
{
m_dht_torrents.push_back(t);
// trigger a DHT announce right away if we just
// added a new torrent and there's no back-log
if (m_dht_torrents.size() == 1)
{
#if defined TORRENT_ASIO_DEBUGGING
add_outstanding_async("session_impl::on_dht_announce");
#endif
error_code ec;
m_dht_announce_timer.expires_from_now(seconds(0), ec);
m_dht_announce_timer.async_wait(
bind(&session_impl::on_dht_announce, this, _1));
}
}
void session_impl::on_dht_announce(error_code const& e)
{
#if defined TORRENT_ASIO_DEBUGGING
@ -3990,6 +4029,15 @@ retry:
// announce to DHT every 15 minutes
int delay = (std::max)(m_settings.dht_announce_interval
/ (std::max)(int(m_torrents.size()), 1), 1);
if (!m_dht_torrents.empty())
{
// we have prioritized torrents that need
// an initial DHT announce. Don't wait too long
// until we announce those.
delay = (std::min)(4, delay);
}
error_code ec;
m_dht_announce_timer.expires_from_now(seconds(delay), ec);
m_dht_announce_timer.async_wait(
@ -4125,6 +4173,8 @@ retry:
{
INVARIANT_CHECK;
m_need_auto_manage = false;
// these vectors are filled with auto managed torrents
std::vector<torrent*> downloaders;
downloaders.reserve(m_torrents.size());
@ -5003,7 +5053,7 @@ retry:
// a boat load of torrents, we postpone the recalculation until
// we're done adding them all (since it's kind of an expensive operation)
if (params.flags & add_torrent_params::flag_auto_managed)
m_auto_manage_time_scaler = 2;
trigger_auto_manage();
return torrent_handle(torrent_ptr);
}

View File

@ -2104,6 +2104,9 @@ namespace libtorrent
#endif
pause();
set_error(j.error, j.error_file);
// recalculate auto-managed torrents sooner
// in order to start checking the next torrent
m_ses.trigger_auto_manage();
return;
}
@ -2250,6 +2253,8 @@ namespace libtorrent
std::for_each(peers.begin(), peers.end(), boost::bind(
&policy::add_peer, boost::ref(m_policy), _1, peer_id(0)
, peer_info::dht, 0));
do_connect_boost();
}
#endif
@ -2689,31 +2694,37 @@ namespace libtorrent
}
}
if (m_need_connect_boost)
{
m_need_connect_boost = false;
// this is the first tracker response for this torrent
// instead of waiting one second for session_impl::on_tick()
// to be called, connect to a few peers immediately
int conns = (std::min)((std::min)((std::min)(m_ses.m_settings.torrent_connect_boost
, m_ses.m_settings.connections_limit - m_ses.num_connections())
, m_ses.m_half_open.free_slots())
, m_ses.m_boost_connections - m_ses.m_settings.connection_speed);
while (want_more_peers() && conns > 0)
{
if (!m_policy.connect_one_peer(m_ses.session_time())) break;
// increase m_ses.m_boost_connections for each connection
// attempt. This will be deducted from the connect speed
// the next time session_impl::on_tick() is triggered
--conns;
++m_ses.m_boost_connections;
}
}
do_connect_boost();
state_updated();
}
void torrent::do_connect_boost()
{
if (!m_need_connect_boost) return;
m_need_connect_boost = false;
// this is the first tracker response for this torrent
// instead of waiting one second for session_impl::on_tick()
// to be called, connect to a few peers immediately
int conns = (std::min)((std::min)((std::min)(m_ses.m_settings.torrent_connect_boost
, m_ses.m_settings.connections_limit - m_ses.num_connections())
, m_ses.m_half_open.free_slots())
, m_ses.m_boost_connections - m_ses.m_settings.connection_speed);
while (want_more_peers() && conns > 0)
{
if (!m_policy.connect_one_peer(m_ses.session_time())) break;
// increase m_ses.m_boost_connections for each connection
// attempt. This will be deducted from the connect speed
// the next time session_impl::on_tick() is triggered
--conns;
++m_ses.m_boost_connections;
}
if (want_more_peers()) m_ses.prioritize_connections(shared_from_this());
}
ptime torrent::next_announce() const
{
return m_waiting_tracker?m_tracker_timer.expires_at():min_time();
@ -6184,7 +6195,7 @@ namespace libtorrent
// under a different limit with the auto-manager. Make sure we
// update auto-manage torrents in that case
if (m_auto_managed)
m_ses.m_auto_manage_time_scaler = 2;
m_ses.trigger_auto_manage();
}
// this is called when we were finished, but some files were
@ -6303,7 +6314,7 @@ namespace libtorrent
{
// if this is an auto managed torrent, force a recalculation
// of which torrents to have active
m_ses.m_auto_manage_time_scaler = 2;
m_ses.trigger_auto_manage();
}
if (!is_seed())
@ -6313,7 +6324,7 @@ namespace libtorrent
// if we just finished checking and we're not a seed, we are
// likely to be unpaused
m_ses.m_auto_manage_time_scaler = 2;
m_ses.trigger_auto_manage();
if (is_finished() && m_state != torrent_status::finished)
finished();
@ -6858,7 +6869,7 @@ namespace libtorrent
TORRENT_ASSERT(m_ses.is_network_thread());
if (!m_error) return;
bool checking_files = should_check_files();
m_ses.m_auto_manage_time_scaler = 2;
m_ses.trigger_auto_manage();
m_error = error_code();
m_error_file.clear();
@ -6923,7 +6934,7 @@ namespace libtorrent
// recalculate which torrents should be
// paused
m_ses.m_auto_manage_time_scaler = 2;
m_ses.trigger_auto_manage();
if (!checking_files && should_check_files())
{
@ -7199,7 +7210,7 @@ namespace libtorrent
// if this torrent was just paused
// we might have to resume some other auto-managed torrent
m_ses.m_auto_manage_time_scaler = 2;
m_ses.trigger_auto_manage();
}
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING || defined TORRENT_LOGGING