improved LSD performance and made the interval configurable

This commit is contained in:
Arvid Norberg 2010-02-05 08:23:17 +00:00
parent 7b0555ae45
commit 088f4bf700
8 changed files with 135 additions and 77 deletions

View File

@ -100,6 +100,7 @@
* fixed magnet link issue when using resume data
* support disk I/O priority settings
* added info_hash to torrent_deleted_alert
* improved LSD performance and made the interval configurable
release 0.14.9

View File

@ -106,6 +106,7 @@ void bind_session_settings()
.def_readwrite("max_suggest_pieces", &session_settings::max_suggest_pieces)
.def_readwrite("drop_skipped_requests", &session_settings::drop_skipped_requests)
.def_readwrite("low_prio_disk", &session_settings::low_prio_disk)
.def_readwrite("local_service_announce_interval", &session_settings::local_service_announce_interval)
.def_readwrite("volatile_read_cache", &session_settings::volatile_read_cache)
.def_readwrite("guided_read_cache", &guided_read_cache)
;

View File

@ -3721,6 +3721,7 @@ session_settings
bool drop_skipped_requests;
bool low_prio_disk;
int local_service_announce_interval;
bool volatile_read_cache;
bool guided_read_cache;
bool default_min_cache_age;
@ -4194,6 +4195,11 @@ overall responsiveness of the system while downloading in the
background. For high-performance server setups, this might not
be desirable.
``local_service_announce_interval`` is the time between local
network announces for a torrent. By default, when local service
discovery is enabled a torrent announces itself every 5 minutes.
This interval is specified in seconds.
``volatile_read_cache``, if this is set to true, read cache blocks
that are hit by peer read requests are removed from the disk cache
to free up more space. This is useful if you don't expect the disk

View File

@ -205,6 +205,8 @@ namespace libtorrent
void on_port_map_log(char const* msg, int map_transport);
void on_lsd_announce(error_code const& e);
// called when a port mapping is successful, or a router returns
// a failure to map a port
void on_port_mapping(int mapping, int port, error_code const& ec
@ -709,10 +711,20 @@ namespace libtorrent
// the timer used to fire the tick
deadline_timer m_timer;
// torrents are announced on the local network in a
// round-robin fashion. All torrents are cycled through
// within the LSD announce interval (which defaults to
// 5 minutes)
torrent_map::iterator m_next_lsd_torrent;
// this announce timer is used
// by Local service discovery
deadline_timer m_lsd_announce_timer;
// the index of the torrent that will be offered to
// connect to a peer next time on_tick is called.
// This implements a round robin.
int m_next_connect_torrent;
torrent_map::iterator m_next_connect_torrent;
#ifdef TORRENT_DEBUG
void check_invariant() const;
#endif

View File

@ -186,6 +186,7 @@ namespace libtorrent
, max_suggest_pieces(10)
, drop_skipped_requests(false)
, low_prio_disk(true)
, local_service_announce_interval(5 * 60)
, volatile_read_cache(false)
, guided_read_cache(true)
, default_cache_min_age(1)
@ -689,6 +690,10 @@ namespace libtorrent
// in the background
bool low_prio_disk;
// number of seconds between local service announces for
// torrents. Defaults to 5 minutes
int local_service_announce_interval;
// if this is set to true, any block read from the
// disk cache will be dropped from the cache immediately
// following. This may be useful if the block is not

View File

@ -723,6 +723,10 @@ namespace libtorrent
bool add_merkle_nodes(std::map<int, sha1_hash> const& n, int piece);
// this is called once periodically for torrents
// that are not private
void lsd_announce();
private:
void on_files_deleted(int ret, disk_io_job const& j);
@ -838,10 +842,12 @@ namespace libtorrent
// used to resolve the names of web seeds
mutable tcp::resolver m_host_resolver;
#ifndef TORRENT_DISABLE_DHT
// this announce timer is used both
// by Local service discovery and
// by the DHT.
deadline_timer m_lsd_announce_timer;
deadline_timer m_dht_announce_timer;
#endif
// used for tracker announces
deadline_timer m_tracker_timer;
@ -853,18 +859,14 @@ namespace libtorrent
void on_tracker_announce();
static void on_lsd_announce_disp(boost::weak_ptr<torrent> p
, error_code const& e);
// this is called once every 5 minutes for torrents
// that are not private
void on_lsd_announce();
void dht_announce();
#ifndef TORRENT_DISABLE_DHT
static void on_dht_announce_response_disp(boost::weak_ptr<torrent> t
, std::vector<tcp::endpoint> const& peers);
void on_dht_announce_response(std::vector<tcp::endpoint> const& peers);
bool should_announce_dht() const;
void on_dht_announce(error_code const& e);
// the time when the DHT was last announced of our
// presence on this torrent

View File

@ -285,6 +285,7 @@ namespace aux {
TORRENT_SETTING(integer, max_suggest_pieces)
TORRENT_SETTING(boolean, drop_skipped_requests)
TORRENT_SETTING(boolean, low_prio_disk)
TORRENT_SETTING(boolean, local_service_announce_interval)
};
#undef TORRENT_SETTING
@ -443,7 +444,7 @@ namespace aux {
, m_half_open)
#endif
, m_timer(m_io_service)
, m_next_connect_torrent(0)
, m_lsd_announce_timer(m_io_service)
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
, m_logpath(logpath)
#endif
@ -454,6 +455,9 @@ namespace aux {
, m_total_failed_bytes(0)
, m_total_redundant_bytes(0)
{
m_next_lsd_torrent = m_torrents.begin();
m_next_connect_torrent = m_torrents.begin();
TORRENT_ASSERT(listen_interface);
error_code ec;
m_listen_interface = tcp::endpoint(address::from_string(listen_interface, ec), listen_port_range.first);
@ -590,6 +594,12 @@ namespace aux {
m_timer.expires_from_now(milliseconds(100), ec);
m_timer.async_wait(bind(&session_impl::on_tick, this, _1));
int delay = (std::max)(m_settings.local_service_announce_interval
/ (std::max)(int(m_torrents.size()), 1), 1);
m_lsd_announce_timer.expires_from_now(seconds(delay), ec);
m_lsd_announce_timer.async_wait(
bind(&session_impl::on_lsd_announce, this, _1));
m_thread.reset(new thread(boost::bind(&session_impl::main_thread, this)));
}
@ -900,6 +910,7 @@ namespace aux {
m_dht_socket.close();
#endif
m_timer.cancel(ec);
m_lsd_announce_timer.cancel(ec);
// close the listen sockets
for (std::list<listen_socket_t>::iterator i = m_listen_sockets.begin()
@ -1963,16 +1974,14 @@ namespace aux {
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()))
std::advance(i, m_next_connect_torrent);
else
m_next_connect_torrent = 0;
if (m_next_connect_torrent == m_torrents.end())
m_next_connect_torrent = m_torrents.begin();
int steps_since_last_connect = 0;
int num_torrents = int(m_torrents.size());
for (;;)
{
torrent& t = *i->second;
torrent& t = *m_next_connect_torrent->second;
if (t.want_more_peers())
{
int connect_points = 100;
@ -2012,15 +2021,12 @@ namespace aux {
}
#endif
}
++m_next_connect_torrent;
++steps_since_last_connect;
++i;
if (i == m_torrents.end())
{
TORRENT_ASSERT(m_next_connect_torrent == num_torrents);
i = m_torrents.begin();
m_next_connect_torrent = 0;
}
if (m_next_connect_torrent == m_torrents.end())
m_next_connect_torrent = m_torrents.begin();
// if we have gone two whole loops without
// handing out a single connection, break
if (steps_since_last_connect > num_torrents * 2) break;
@ -2111,6 +2117,27 @@ namespace aux {
// m_peer_pool.release_memory();
}
void session_impl::on_lsd_announce(error_code const& e)
{
if (e) return;
mutex::scoped_lock l(m_mutex);
// announce on local network every 5 minutes
int delay = (std::max)(m_settings.local_service_announce_interval
/ (std::max)(int(m_torrents.size()), 1), 1);
error_code ec;
m_lsd_announce_timer.expires_from_now(seconds(delay), ec);
m_lsd_announce_timer.async_wait(
bind(&session_impl::on_lsd_announce, this, _1));
if (m_next_lsd_torrent == m_torrents.end()) return;
m_next_lsd_torrent->second->lsd_announce();
++m_next_lsd_torrent;
if (m_next_lsd_torrent == m_torrents.end())
m_next_lsd_torrent = m_torrents.begin();
}
namespace
{
bool is_active(torrent* t, session_settings const& s)
@ -2729,8 +2756,19 @@ namespace aux {
#ifdef TORRENT_DEBUG
sha1_hash i_hash = t.torrent_file().info_hash();
#endif
if (i == m_next_lsd_torrent)
++m_next_lsd_torrent;
if (i == m_next_connect_torrent)
++m_next_connect_torrent;
t.set_queue_position(-1);
m_torrents.erase(i);
if (m_next_lsd_torrent == m_torrents.end())
m_next_lsd_torrent = m_torrents.begin();
if (m_next_connect_torrent == m_torrents.end())
m_next_connect_torrent = m_torrents.begin();
std::list<boost::shared_ptr<torrent> >::iterator k
= std::find(m_queued_for_checking.begin(), m_queued_for_checking.end(), tptr);
if (k != m_queued_for_checking.end()) m_queued_for_checking.erase(k);

View File

@ -214,7 +214,9 @@ namespace libtorrent
, m_torrent_file(p.ti ? p.ti : new torrent_info(p.info_hash))
, m_storage(0)
, m_host_resolver(ses.m_io_service)
, m_lsd_announce_timer(ses.m_io_service)
#ifndef TORRENT_DISABLE_DHT
, m_dht_announce_timer(ses.m_io_service)
#endif
, m_tracker_timer(ses.m_io_service)
#ifndef TORRENT_DISABLE_DHT
, m_last_dht_announce(time_now() - minutes(15))
@ -368,10 +370,9 @@ namespace libtorrent
// DHT announces are done on the local service
// discovery timer. Trigger it.
error_code ec;
boost::weak_ptr<torrent> self(shared_from_this());
m_lsd_announce_timer.expires_from_now(seconds(1), ec);
m_lsd_announce_timer.async_wait(
bind(&torrent::on_lsd_announce_disp, self, _1));
m_dht_announce_timer.expires_from_now(seconds(1), ec);
m_dht_announce_timer.async_wait(
bind(&torrent::on_dht_announce, shared_from_this(), _1));
}
#endif
@ -1175,30 +1176,14 @@ namespace libtorrent
announce_with_tracker();
}
void torrent::on_lsd_announce_disp(boost::weak_ptr<torrent> p
, error_code const& e)
void torrent::lsd_announce()
{
#if defined TORRENT_LOGGING
if (e)
{
boost::shared_ptr<torrent> t = p.lock();
if (!t) return;
(*t->session().m_logger) << time_now_string() << " on_lsd_announce_disp: " << e.message() << "\n";
}
#else
if (e) return;
#endif
boost::shared_ptr<torrent> t = p.lock();
if (!t) return;
t->on_lsd_announce();
}
void torrent::on_lsd_announce()
{
mutex::scoped_lock l(m_ses.m_mutex);
if (m_abort) return;
// if the files haven't been checked yet, we're
// not ready for peers
if (!m_files_checked) return;
TORRENT_ASSERT(!m_torrent_file->priv());
if (m_torrent_file->is_valid()
&& (m_torrent_file->priv()
@ -1206,36 +1191,39 @@ namespace libtorrent
&& !m_settings.allow_i2p_mixed)))
return;
if (is_paused()) return;
boost::weak_ptr<torrent> self(shared_from_this());
error_code ec;
// announce on local network every 5 minutes
m_lsd_announce_timer.expires_from_now(minutes(5), ec);
m_lsd_announce_timer.async_wait(
bind(&torrent::on_lsd_announce_disp, self, _1));
// announce with the local discovery service
m_ses.announce_lsd(m_torrent_file->info_hash());
#ifndef TORRENT_DISABLE_DHT
if (!m_ses.m_dht) return;
ptime now = time_now();
if (should_announce_dht() && now - m_last_dht_announce > minutes(14))
{
m_last_dht_announce = now;
m_ses.m_dht->announce(m_torrent_file->info_hash()
, m_ses.listen_port()
, bind(&torrent::on_dht_announce_response_disp, self, _1));
}
#endif
}
#ifndef TORRENT_DISABLE_DHT
void torrent::on_dht_announce(error_code const& e)
{
if (e) return;
mutex::scoped_lock l(m_ses.m_mutex);
if (m_abort) return;
error_code ec;
m_dht_announce_timer.expires_from_now(minutes(15), ec);
m_dht_announce_timer.async_wait(
bind(&torrent::on_dht_announce, shared_from_this(), _1));
if (m_torrent_file->is_valid() && m_torrent_file->priv())
return;
if (is_paused()) return;
if (!m_ses.m_dht) return;
if (!should_announce_dht()) return;
m_last_dht_announce = time_now();
boost::weak_ptr<torrent> self(shared_from_this());
m_ses.m_dht->announce(m_torrent_file->info_hash()
, m_ses.listen_port()
, bind(&torrent::on_dht_announce_response_disp, self, _1));
}
void torrent::on_dht_announce_response_disp(boost::weak_ptr<libtorrent::torrent> t
, std::vector<tcp::endpoint> const& peers)
{
@ -1617,7 +1605,7 @@ namespace libtorrent
#if defined TORRENT_LOGGING
if (ec)
*m_ses.m_logger << time_now_string() << " on_i2p_resolve: " << e.message() << "\n";
*m_ses.m_logger << time_now_string() << " on_i2p_resolve: " << ec.message() << "\n";
#endif
if (ec || m_ses.is_aborted()) return;
@ -1633,7 +1621,7 @@ namespace libtorrent
INVARIANT_CHECK;
#if defined TORRENT_LOGGING
if (ec)
if (e)
*m_ses.m_logger << time_now_string() << " on_peer_name_lookup: " << e.message() << "\n";
#endif
if (e || host == tcp::resolver::iterator() ||
@ -5270,11 +5258,14 @@ namespace libtorrent
&& (!m_torrent_file->is_i2p()
|| m_settings.allow_i2p_mixed)))
{
if (m_ses.m_lsd) lsd_announce();
#ifndef TORRENT_DISABLE_DHT
error_code ec;
boost::weak_ptr<torrent> self(shared_from_this());
m_lsd_announce_timer.expires_from_now(seconds(1), ec);
m_lsd_announce_timer.async_wait(
bind(&torrent::on_lsd_announce_disp, self, _1));
m_dht_announce_timer.expires_from_now(seconds(1), ec);
m_dht_announce_timer.async_wait(
bind(&torrent::on_dht_announce, shared_from_this(), _1));
#endif
}
}
@ -5283,7 +5274,9 @@ namespace libtorrent
if (!m_announcing) return;
error_code ec;
m_lsd_announce_timer.cancel(ec);
#ifndef TORRENT_DISABLE_DHT
m_dht_announce_timer.cancel(ec);
#endif
m_tracker_timer.cancel(ec);
m_announcing = false;