diff --git a/docs/manual.rst b/docs/manual.rst index f547f7575..0775a83b3 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -687,9 +687,18 @@ struct has the following members:: int num_unchoked; int allowed_upload_slots; + int up_bandwidth_queue; + int down_bandwidth_queue; + + int up_bandwidth_bytes_queue; + int down_bandwidth_bytes_queue; + int optimistic_unchoke_counter; int unchoke_counter; + int disk_write_queue; + int disk_read_queue; + int dht_nodes; int dht_node_cache; int dht_torrents; @@ -742,11 +751,20 @@ be assigned a torrent yet. ``num_unchoked`` is the current number of unchoked peers. ``allowed_upload_slots`` is the current allowed number of unchoked peers. +``up_bandwidth_queue`` and ``down_bandwidth_queue`` are the number of peers that are +waiting for more bandwidth quota from the torrent rate limiter. +``up_bandwidth_bytes_queue`` and ``down_bandwidth_bytes_queue`` count the number of +bytes the connections are waiting for to be able to send and receive. + ``optimistic_unchoke_counter`` and ``unchoke_counter`` tells the number of seconds until the next optimistic unchoke change and the start of the next unchoke interval. These numbers may be reset prematurely if a peer that is unchoked disconnects or becomes notinterested. +``disk_write_queue`` and ``disk_read_queue`` are the number of peers currently +waiting on a disk write or disk read to complete before it receives or sends +any more data on the socket. It'a a metric of how disk bound you are. + ``dht_nodes``, ``dht_node_cache`` and ``dht_torrents`` are only available when built with DHT support. They are all set to 0 if the DHT isn't running. When the DHT is running, ``dht_nodes`` is set to the number of nodes in the routing diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 963c2090e..56d2f3517 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -1544,7 +1544,8 @@ int main(int argc, char* argv[]) out += str; snprintf(str, sizeof(str), "==== waste: %s fail: %s unchoked: %d / %d " - "bw queues: %8d (%d) | %8d (%d) cache: w: %"PRId64"%% r: %"PRId64"%% size: %s (%s) / %s dq: %"PRId64" ===\n" + "bw queues: %8d (%d) | %8d (%d) disk queues: %d | %d cache: w: %"PRId64"%% r: %"PRId64"%% " + "size: %s (%s) / %s dq: %"PRId64" ===\n" , add_suffix(sess_stat.total_redundant_bytes).c_str() , add_suffix(sess_stat.total_failed_bytes).c_str() , sess_stat.num_unchoked, sess_stat.allowed_upload_slots @@ -1552,6 +1553,8 @@ int main(int argc, char* argv[]) , sess_stat.up_bandwidth_queue , sess_stat.down_bandwidth_bytes_queue , sess_stat.down_bandwidth_queue + , sess_stat.disk_write_queue + , sess_stat.disk_read_queue , (cs.blocks_written - cs.writes) * 100 / cs.blocks_written , cs.blocks_read_hit * 100 / cs.blocks_read , add_suffix(cs.cache_size * 16 * 1024).c_str() diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 3a4e102d5..3f5dde957 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -426,6 +426,19 @@ namespace libtorrent mutable libtorrent::mutex mut; mutable libtorrent::condition cond; + void inc_disk_queue(int channel) + { + TORRENT_ASSERT(channel >= 0 && channel < 2); + ++m_disk_queues[channel]; + } + + void dec_disk_queue(int channel) + { + TORRENT_ASSERT(channel >= 0 && channel < 2); + TORRENT_ASSERT(m_disk_queues[channel] > 0); + --m_disk_queues[channel]; + } + // private: void update_connections_limit(); @@ -560,6 +573,12 @@ namespace libtorrent bandwidth_channel* m_bandwidth_channel[2]; + // the number of peer connections that are waiting + // for the disk. one for each channel. + // upload_channel means waiting to read from disk + // and download_channel is waiting to write to disk + int m_disk_queues[2]; + tracker_manager m_tracker_manager; torrent_map m_torrents; std::map > m_uuids; diff --git a/include/libtorrent/session_status.hpp b/include/libtorrent/session_status.hpp index 347d54be2..c4002434e 100644 --- a/include/libtorrent/session_status.hpp +++ b/include/libtorrent/session_status.hpp @@ -126,6 +126,9 @@ namespace libtorrent int optimistic_unchoke_counter; int unchoke_counter; + int disk_write_queue; + int disk_read_queue; + #ifndef TORRENT_DISABLE_DHT int dht_nodes; int dht_node_cache; diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index a97aae7cf..b481034c2 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -4458,6 +4458,8 @@ namespace libtorrent && m_reading_bytes > 0 && quota_left > 0) { + if (m_channel_state[upload_channel] != peer_info::bw_disk) + m_ses.inc_disk_queue(upload_channel); m_channel_state[upload_channel] = peer_info::bw_disk; if (!m_connecting @@ -4523,6 +4525,8 @@ namespace libtorrent vec, make_write_handler(boost::bind( &peer_connection::on_send_data, self(), _1, _2))); + if (m_channel_state[upload_channel] == peer_info::bw_disk) + m_ses.dec_disk_queue(upload_channel); m_channel_state[upload_channel] = peer_info::bw_network; } @@ -4531,6 +4535,7 @@ namespace libtorrent if (m_channel_state[download_channel] != peer_info::bw_disk) return; boost::intrusive_ptr me(this); + m_ses.dec_disk_queue(download_channel); m_channel_state[download_channel] = peer_info::bw_idle; setup_receive(); } @@ -5018,6 +5023,7 @@ namespace libtorrent if (!disk) { + if (m_channel_state[download_channel] != peer_info::bw_disk) m_ses.inc_disk_queue(download_channel); if (state) *state = peer_info::bw_disk; return false; } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index aed566257..e4263b2ba 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -536,6 +536,9 @@ namespace aux { , m_network_thread(0) #endif { + m_disk_queues[0] = 0; + m_disk_queues[1] = 0; + #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING m_logger = create_log("main_session", listen_port(), false); (*m_logger) << time_now_string() << "\n"; @@ -3999,6 +4002,9 @@ namespace aux { s.up_bandwidth_bytes_queue = m_upload_rate.queued_bytes(); s.down_bandwidth_bytes_queue = m_download_rate.queued_bytes(); + s.disk_write_queue = m_disk_queues[peer_connection::download_channel]; + s.disk_read_queue = m_disk_queues[peer_connection::upload_channel]; + s.has_incoming_connections = m_incoming_connection; // total @@ -4805,6 +4811,7 @@ namespace aux { TORRENT_ASSERT(m_allowed_upload_slots >= m_settings.unchoke_slots_limit); int unchokes = 0; int num_optimistic = 0; + int disk_queue[2] = {0, 0}; for (connection_map::const_iterator i = m_connections.begin(); i != m_connections.end(); ++i) { @@ -4813,6 +4820,9 @@ namespace aux { TORRENT_ASSERT(unique_peers.find(i->get()) == unique_peers.end()); unique_peers.insert(i->get()); + if ((*i)->m_channel_state[0] == peer_info::bw_disk) ++disk_queue[0]; + if ((*i)->m_channel_state[1] == peer_info::bw_disk) ++disk_queue[1]; + peer_connection* p = i->get(); TORRENT_ASSERT(!p->is_disconnecting()); if (p->ignore_unchoke_slots()) continue; @@ -4829,6 +4839,9 @@ namespace aux { } } + TORRENT_ASSERT(disk_queue[0] == m_disk_queues[0]); + TORRENT_ASSERT(disk_queue[1] == m_disk_queues[1]); + if (m_settings.num_optimistic_unchoke_slots) { TORRENT_ASSERT(num_optimistic <= m_settings.num_optimistic_unchoke_slots);