From f6a42863e39b32b759ef0323501f585d1904b567 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 27 Mar 2011 20:35:38 +0000 Subject: [PATCH] try to optimize disk write performance by raising the low watermark (for disk thread queue) to start reading from sockets and also post the start-reading event earlier. Also implement fair round-robin of which peers get to start downloading on this event --- src/disk_io_thread.cpp | 16 +++----------- src/session_impl.cpp | 49 ++++++++++++++++++++---------------------- 2 files changed, 26 insertions(+), 39 deletions(-) diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index a7c98dd85..7fa98fd4e 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -1583,10 +1583,6 @@ namespace libtorrent for (;;) { - // used to indicate whether or not we should post the - // 'restart download' event or not. - bool post = false; - #ifdef TORRENT_DISK_STATS m_log << log_time() << " idle" << std::endl; #endif @@ -1675,10 +1671,10 @@ namespace libtorrent if (m_exceeded_write_queue) { int low_watermark = m_settings.max_queued_disk_bytes_low_watermark == 0 - ? m_settings.max_queued_disk_bytes / 2 + ? m_settings.max_queued_disk_bytes * 7 / 8 : m_settings.max_queued_disk_bytes_low_watermark; if (low_watermark >= m_settings.max_queued_disk_bytes) - low_watermark = m_settings.max_queued_disk_bytes / 2; + low_watermark = m_settings.max_queued_disk_bytes * 7 / 8; if (m_queue_buffer_size < low_watermark || m_settings.max_queued_disk_bytes == 0) @@ -1687,7 +1683,7 @@ namespace libtorrent // we just dropped below the high watermark of number of bytes // queued for writing to the disk. Notify the session so that it // can trigger all the connections waiting for this event - post = true; + if (m_queue_callback) m_ios.post(m_queue_callback); } } } @@ -1797,12 +1793,6 @@ namespace libtorrent disk_buffer_holder holder(*this , operation_has_buffer(j) ? j.buffer : 0); - if (post && m_queue_callback) - { - TORRENT_ASSERT(m_exceeded_write_queue == false); - m_ios.post(m_queue_callback); - } - flush_expired_pieces(); int ret = 0; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index aba4ec202..20931a379 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -566,6 +566,7 @@ namespace aux { #endif m_next_lsd_torrent = m_torrents.begin(); m_next_connect_torrent = m_torrents.begin(); + m_next_disk_peer = m_connections.begin(); if (!listen_interface) listen_interface = "0.0.0.0"; m_listen_interface = tcp::endpoint(address::from_string(listen_interface, ec), listen_port_range.first); @@ -2345,6 +2346,8 @@ namespace aux { c->set_upload_limit(m_settings.default_peer_upload_rate); if (m_settings.default_peer_download_rate) c->set_download_limit(m_settings.default_peer_download_rate); + // update the next disk peer round-robin cursor + if (m_next_disk_peer == m_connections.end()) m_next_disk_peer = m_connections.begin(); } } @@ -2410,7 +2413,10 @@ namespace aux { boost::intrusive_ptr sp((peer_connection*)p); connection_map::iterator i = m_connections.find(sp); + // make sure the next disk peer round-robin cursor stays valid + if (m_next_disk_peer == i) ++m_next_disk_peer; if (i != m_connections.end()) m_connections.erase(i); + if (m_next_disk_peer == m_connections.end()) m_next_disk_peer = m_connections.begin(); } void session_impl::set_peer_id(peer_id const& id) @@ -2466,35 +2472,26 @@ namespace aux { { TORRENT_ASSERT(is_network_thread()); - std::vector conns; - conns.reserve(m_connections.size() / 2); - for (connection_map::iterator i = m_connections.begin(); - i != m_connections.end(); ++i) + // just to play it safe + if (m_next_disk_peer == m_connections.end()) m_next_disk_peer = m_connections.begin(); + + // never loop more times than there are connections + // keep in mind that connections may disconnect + // while we're looping, that's why this is a reliable + // way of limiting it + int limit = m_connections.size(); + + do { - peer_connection* p = i->get(); + --limit; + peer_connection* p = m_next_disk_peer->get(); + ++m_next_disk_peer; + if (m_next_disk_peer == m_connections.end()) m_next_disk_peer = m_connections.begin(); if (p->m_channel_state[peer_connection::download_channel] != peer_info::bw_disk) continue; + p->on_disk(); - conns.push_back(p); - } - - if (conns.empty()) return; - - // pick a random peer to start with, to evenly distribute - // the disk bandwidth - std::vector::iterator peer = conns.begin() + (rand() % conns.size()); - for (int i = 0; i < conns.size(); ++i) - { - // if we can't write to disk anymore, no need - // to keep iterating - if (!can_write_to_disk()) break; - - // setup_receive() may disconnect the connection - // and clear it out from the m_connections list - (*peer)->on_disk(); - ++peer; - if (peer == conns.end()) peer = conns.begin(); - } + } while (m_next_disk_peer != m_connections.end() && limit > 0 && can_write_to_disk()); } // used to cache the current time @@ -2914,7 +2911,7 @@ namespace aux { } int low_watermark = m_settings.max_queued_disk_bytes_low_watermark == 0 - ? m_settings.max_queued_disk_bytes / 2 + ? m_settings.max_queued_disk_bytes * 7 / 8 : m_settings.max_queued_disk_bytes_low_watermark; if (now - m_last_log_rotation > hours(1))