/* Copyright (c) 2014-2020, Arvid Norberg Copyright (c) 2016-2017, Alden Torres Copyright (c) 2019, Steven Siloti All rights reserved. You may use, distribute and modify this code under the terms of the BSD license, see LICENSE file. */ #ifndef TORRENT_PERFORMANCE_COUNTERS_HPP_INCLUDED #define TORRENT_PERFORMANCE_COUNTERS_HPP_INCLUDED #include "libtorrent/config.hpp" #include "libtorrent/aux_/array.hpp" #include #include #include namespace libtorrent { // holds the session-wide counters and gauges backing the // ``session_stats_alert`` and ``session_status`` reporting paths. // One instance lives on the session and is incremented from the // network thread; reads from other threads use the lock-free // ``operator[]`` overload when ``ATOMIC_LLONG_LOCK_FREE`` is set, // otherwise a single shared mutex guards the whole array. // // A reference to this object is passed to custom disk I/O // implementations (see disk_interface and the disk_io_constructor // passed via session_params), which update the disk related metrics // through it. The specific counters and gauges are documented under // the session-statistics_ section. struct TORRENT_EXPORT counters { // internal enum stats_counter_t { // the number of peers that were disconnected this // tick due to protocol error error_peers, disconnected_peers, eof_peers, connreset_peers, connrefused_peers, connaborted_peers, notconnected_peers, perm_peers, buffer_peers, unreachable_peers, broken_pipe_peers, addrinuse_peers, no_access_peers, invalid_arg_peers, aborted_peers, piece_requests, max_piece_requests, invalid_piece_requests, choked_piece_requests, cancelled_piece_requests, piece_rejects, error_incoming_peers, error_outgoing_peers, error_rc4_peers, error_encrypted_peers, error_tcp_peers, error_utp_peers, // the number of times the piece picker was // successfully invoked, split by the reason // it was invoked reject_piece_picks, unchoke_piece_picks, incoming_redundant_piece_picks, incoming_piece_picks, end_game_piece_picks, snubbed_piece_picks, interesting_piece_picks, hash_fail_piece_picks, // these counters indicate which parts // of the piece picker CPU is spent in piece_picker_partial_loops, piece_picker_suggest_loops, piece_picker_sequential_loops, piece_picker_reverse_rare_loops, piece_picker_rare_loops, piece_picker_rand_start_loops, piece_picker_rand_loops, piece_picker_busy_loops, // reasons to disconnect peers connect_timeouts, uninteresting_peers, timeout_peers, no_memory_peers, too_many_peers, transport_timeout_peers, num_banned_peers, banned_for_hash_failure, // connection attempts (not necessarily successful) connection_attempts, // the number of iterations over the peer list when finding // a connect candidate connection_attempt_loops, // the number of peer connection attempts made as high // priority connections for new torrents boost_connection_attempts, // calls to torrent::connect_to_peer() that failed missed_connection_attempts, // calls to peer_list::connect_one_peer() resulting in // no peer candidate being found no_peer_connection_attempts, // successful incoming connections (not rejected for any reason) incoming_connections, // counts events where the network // thread wakes up on_read_counter, on_write_counter, on_tick_counter, on_lsd_counter, on_lsd_peer_counter, on_udp_counter, on_accept_counter, on_disk_queue_counter, on_disk_counter, // bittorrent message counters // how about dont-have, share-mode, upload-only num_incoming_choke, num_incoming_unchoke, num_incoming_interested, num_incoming_not_interested, num_incoming_have, num_incoming_bitfield, num_incoming_request, num_incoming_piece, num_incoming_cancel, num_incoming_dht_port, num_incoming_suggest, num_incoming_have_all, num_incoming_have_none, num_incoming_reject, num_incoming_allowed_fast, num_incoming_ext_handshake, num_incoming_pex, num_incoming_metadata, num_incoming_extended, num_outgoing_choke, num_outgoing_unchoke, num_outgoing_interested, num_outgoing_not_interested, num_outgoing_have, num_outgoing_bitfield, num_outgoing_request, num_outgoing_piece, num_outgoing_cancel, num_outgoing_dht_port, num_outgoing_suggest, num_outgoing_have_all, num_outgoing_have_none, num_outgoing_reject, num_outgoing_allowed_fast, num_outgoing_ext_handshake, num_outgoing_pex, num_outgoing_metadata, num_outgoing_extended, num_outgoing_hash_request, num_outgoing_hashes, num_outgoing_hash_reject, num_piece_passed, num_piece_failed, num_have_pieces, num_total_pieces_added, num_blocks_written, num_blocks_read, num_blocks_hashed, num_write_ops, num_read_ops, num_read_back, file_pool_hits, file_pool_misses, file_pool_thread_stall, file_pool_race, disk_read_time, disk_write_time, disk_hash_time, disk_job_time, waste_piece_timed_out, waste_piece_cancelled, waste_piece_unknown, waste_piece_seed, waste_piece_end_game, waste_piece_closing, sent_payload_bytes, sent_bytes, sent_ip_overhead_bytes, sent_tracker_bytes, recv_payload_bytes, recv_bytes, recv_ip_overhead_bytes, recv_tracker_bytes, recv_failed_bytes, recv_redundant_bytes, dht_messages_in, dht_messages_in_dropped, dht_messages_out, dht_messages_out_dropped, dht_bytes_in, dht_bytes_out, dht_ping_in, dht_ping_out, dht_find_node_in, dht_find_node_out, dht_get_peers_in, dht_get_peers_out, dht_announce_peer_in, dht_announce_peer_out, dht_get_in, dht_get_out, dht_put_in, dht_put_out, dht_sample_infohashes_in, dht_sample_infohashes_out, dht_invalid_announce, dht_invalid_get_peers, dht_invalid_find_node, dht_invalid_put, dht_invalid_get, dht_invalid_sample_infohashes, // uTP counters. utp_packet_loss, utp_timeout, utp_packets_in, utp_packets_out, utp_fast_retransmit, utp_packet_resend, utp_samples_above_target, utp_samples_below_target, utp_payload_pkts_in, utp_payload_pkts_out, utp_invalid_pkts_in, utp_redundant_pkts_in, // the buffer sizes accepted by // socket send calls. The larger // the more efficient. The size is // 1 << n, where n is the number // at the end of the counter name // 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, // 16384, 32768, 65536, 131072, 262144, 524288, 1048576 socket_send_size3, socket_send_size4, socket_send_size5, socket_send_size6, socket_send_size7, socket_send_size8, socket_send_size9, socket_send_size10, socket_send_size11, socket_send_size12, socket_send_size13, socket_send_size14, socket_send_size15, socket_send_size16, socket_send_size17, socket_send_size18, socket_send_size19, socket_send_size20, // the buffer sizes returned by // socket recv calls. The larger // the more efficient. The size is // 1 << n, where n is the number // at the end of the counter name // // 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, // 16384, 32768, 65536, 131072, 262144, 524288, 1048576 socket_recv_size3, socket_recv_size4, socket_recv_size5, socket_recv_size6, socket_recv_size7, socket_recv_size8, socket_recv_size9, socket_recv_size10, socket_recv_size11, socket_recv_size12, socket_recv_size13, socket_recv_size14, socket_recv_size15, socket_recv_size16, socket_recv_size17, socket_recv_size18, socket_recv_size19, socket_recv_size20, // histogram of disk read-job latency, measured on the network // thread from when the job is queued to when its completion // latency buckets in ms: 30 * n // 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360, 390, // 420, 450, 480, 510, 540, 570, 600 // // Only populated when built with disk-latency-stats=on builds (see // the disk-latency-stats / TORRENT_DISK_LATENCY_STATS feature); // always zero otherwise. disk_read_latency1, disk_read_latency2, disk_read_latency3, disk_read_latency4, disk_read_latency5, disk_read_latency6, disk_read_latency7, disk_read_latency8, disk_read_latency9, disk_read_latency10, disk_read_latency11, disk_read_latency12, disk_read_latency13, disk_read_latency14, disk_read_latency15, disk_read_latency16, disk_read_latency17, disk_read_latency18, disk_read_latency19, disk_read_latency20, num_stats_counters }; // == ALL FOLLOWING ARE GAUGES == // it is important that all gauges have a higher index than counters. // This assumption is relied upon in other parts of the code // internal enum stats_gauge_t { num_checking_torrents = num_stats_counters, num_stopped_torrents, num_upload_only_torrents, // upload_only means finished num_downloading_torrents, num_seeding_torrents, num_queued_seeding_torrents, num_queued_download_torrents, num_error_torrents, // the number of torrents that don't have the // IP filter applied to them. non_filter_torrents, // these counter indices deliberately // match the order of socket type IDs // defined in socket_type.hpp. num_tcp_peers, num_socks5_peers, num_http_proxy_peers, num_utp_peers, num_i2p_peers, num_ssl_peers, num_ssl_socks5_peers, num_ssl_http_proxy_peers, num_ssl_utp_peers, // the number of peer connections that are half-open (i.e. in the // process of completing a connection attempt) and fully connected. // These states are mutually exclusive (a connection cannot be in both // states simultaneously). num_peers_half_open, num_peers_connected, // the number of peers interested in us (``up_interested``) and peers // we are interested in (``down_interested``). num_peers_up_interested, num_peers_down_interested, // the total number of unchoked peers (``up_unchoked_all``), the number // of peers unchoked via the optimistic unchoke // (``up_unchoked_optimistic``) and peers unchoked via the // reciprocation (regular) unchoke mechanism (``up_unchoked``). // and the number of peers that have unchoked us (``down_unchoked``). num_peers_up_unchoked_all, num_peers_up_unchoked_optimistic, num_peers_up_unchoked, num_peers_down_unchoked, // the number of peers with at least one piece request pending, // downloading (``down_requests``) or uploading (``up_requests``) num_peers_up_requests, num_peers_down_requests, // the number of peers that have at least one outstanding disk request, // either reading (``up_disk``) or writing (``down_disk``). num_peers_up_disk, num_peers_down_disk, // the number of peers in end-game mode. End game mode is where there // are no blocks that we have not sent any requests to download. In this // mode, blocks are allowed to be requested from more than one peer at // at time. num_peers_end_game, request_latency, disk_blocks_in_use, cached_blocks, num_unhashed, queued_disk_jobs, num_running_disk_jobs, num_read_jobs, num_write_jobs, num_jobs, num_writing_threads, num_running_threads, blocked_disk_jobs, file_pool_size, queued_write_bytes, num_unchoke_slots, num_fenced_read, num_fenced_write, num_fenced_hash, num_fenced_move_storage, num_fenced_release_files, num_fenced_delete_files, num_fenced_check_fastresume, num_fenced_save_resume_data, num_fenced_rename_file, num_fenced_stop_torrent, num_fenced_flush_piece, num_fenced_flush_hashed, num_fenced_flush_storage, num_fenced_file_priority, num_fenced_load_torrent, num_fenced_clear_piece, num_fenced_tick_storage, dht_nodes, dht_node_cache, dht_torrents, dht_peers, dht_immutable_data, dht_mutable_data, dht_allocated_observers, has_incoming_connections, limiter_up_queue, limiter_down_queue, limiter_up_bytes, limiter_down_bytes, // the number of uTP connections in each respective state // these must be defined in the same order as the state_t enum // in utp_stream num_utp_idle, num_utp_syn_sent, num_utp_connected, num_utp_fin_sent, num_utp_close_wait, num_utp_deleted, num_outstanding_accept, num_queued_tracker_announces, num_counters, num_gauges_counters = num_counters - static_cast(num_stats_counters) }; #ifdef ATOMIC_LLONG_LOCK_FREE #define TORRENT_COUNTER_NOEXCEPT noexcept #else #define TORRENT_COUNTER_NOEXCEPT #endif counters() TORRENT_COUNTER_NOEXCEPT; counters(counters const&) TORRENT_COUNTER_NOEXCEPT; counters& operator=(counters const&) & TORRENT_COUNTER_NOEXCEPT; // increments the counter or gauge ``c`` (an index into the counter // array) by ``value`` and returns the new value. std::int64_t inc_stats_counter(int c, std::int64_t value = 1) TORRENT_COUNTER_NOEXCEPT; // returns the current value of counter or gauge ``i`` (an index into // the counter array). std::int64_t operator[](int i) const TORRENT_COUNTER_NOEXCEPT; // overwrites the value of counter or gauge ``c`` (an index into // the counter array). ``blend_stats_counter()`` adjusts the stat value // toward the specified ``value``, ``ratio`` specifies the percent of // the new value should be influenced by ``value``. void set_value(int c, std::int64_t value) TORRENT_COUNTER_NOEXCEPT; void blend_stats_counter(int c, std::int64_t value, int ratio) TORRENT_COUNTER_NOEXCEPT; private: // TODO: some space could be saved here by making gauges 32 bits // TODO: restore these to regular integers. Instead have one copy // of the counters per thread and collect them at convenient // synchronization points #ifdef ATOMIC_LLONG_LOCK_FREE aux::array, num_counters> m_stats_counter; #else // if the atomic type isn't lock-free, use a single lock instead, for // the whole array mutable std::mutex m_mutex; aux::array m_stats_counter; #endif }; } #endif