From 8fc07e6e89a9a1594f6d4d1582fefe05b42624c6 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 8 Jul 2014 22:37:13 +0000 Subject: [PATCH] more work towards making client_test event-driven and use session stats counters instead of session_status + some refactoring --- examples/Jamfile | 2 +- examples/client_test.cpp | 135 +++------------- examples/print.cpp | 15 +- examples/print.hpp | 2 +- examples/session_view.cpp | 168 ++++++++++++++++++++ examples/torrent_view.cpp | 31 ++-- include/libtorrent/performance_counters.hpp | 1 + src/session_stats.cpp | 2 +- 8 files changed, 223 insertions(+), 133 deletions(-) create mode 100644 examples/session_view.cpp diff --git a/examples/Jamfile b/examples/Jamfile index c8c659388..cb26676c1 100644 --- a/examples/Jamfile +++ b/examples/Jamfile @@ -16,7 +16,7 @@ project client_test static ; -exe client_test : client_test.cpp print.cpp torrent_view.cpp ; +exe client_test : client_test.cpp print.cpp torrent_view.cpp session_view.cpp ; exe simple_client : simple_client.cpp ; exe stats_counters : stats_counters.cpp ; diff --git a/examples/client_test.cpp b/examples/client_test.cpp index da2b0a332..81a5b2b1c 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -65,6 +65,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/create_torrent.hpp" #include "torrent_view.hpp" +#include "session_view.hpp" #include "print.hpp" using boost::bind; @@ -177,8 +178,10 @@ bool print_disk_stats = false; int num_outstanding_resume_data = 0; torrent_view view; +session_view ses_view; -int load_file(std::string const& filename, std::vector& v, libtorrent::error_code& ec, int limit = 8000000) +int load_file(std::string const& filename, std::vector& v + , libtorrent::error_code& ec, int limit = 8000000) { ec.clear(); FILE* f = fopen(filename.c_str(), "rb"); @@ -735,14 +738,13 @@ int save_file(std::string const& filename, std::vector& v) // returns true if the alert was handled (and should not be printed to the log) // returns false if the alert was not handled bool handle_alert(libtorrent::session& ses, libtorrent::alert* a - , handles_t& files, std::set& non_files - , std::vector& stats_counters) + , handles_t& files, std::set& non_files) { using namespace libtorrent; if (session_stats_alert* s = alert_cast(a)) { - stats_counters.swap(s->values); + ses_view.update_counters(s->values, s->timestamp); return true; } @@ -1079,12 +1081,6 @@ int main(int argc, char* argv[]) settings_pack settings; settings.set_int(settings_pack::active_loaded_limit, 20); - std::vector stats_counters; - std::vector metrics = session_stats_metrics(); - stats_counters.resize(metrics.size(), 0); - - const int queued_bytes_idx = find_metric_idx(metrics, "queued_write_bytes"); - proxy_settings ps; int refresh_delay = 500; @@ -1436,18 +1432,24 @@ int main(int argc, char* argv[]) signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); #endif + while (!quit) { ++tick; ses.post_torrent_updates(); ses.post_session_stats(); - int c = 0; + int terminal_width = 80; + int terminal_height = 50; + terminal_size(&terminal_width, &terminal_height); + view.set_size(terminal_width, terminal_height / 2); + ses_view.set_pos(terminal_height / 2); + int c = 0; if (sleep_and_input(&c, refresh_delay)) { -#ifdef WIN32 +#ifdef _WIN32 #define ESCAPE_SEQ 224 #define LEFT_ARROW 75 #define RIGHT_ARROW 77 @@ -1587,11 +1589,6 @@ int main(int argc, char* argv[]) h.force_recheck(); } - if (c == 'x') - { - print_disk_stats = !print_disk_stats; - } - if (c == 'r' && h.is_valid()) { h.force_reannounce(); @@ -1672,6 +1669,7 @@ int main(int argc, char* argv[]) if (c == 'a') print_piece_bar = !print_piece_bar; if (c == 'g') show_dht_status = !show_dht_status; if (c == 'u') print_utp_stats = !print_utp_stats; + if (c == 'x') print_disk_stats = !print_disk_stats; // toggle columns if (c == '1') print_ip = !print_ip; if (c == '2') print_as = !print_as; @@ -1716,17 +1714,11 @@ int main(int argc, char* argv[]) int tmp; while (sleep_and_input(&tmp, 500) == false); } + } while (sleep_and_input(&c, 0)); if (c == 'q') break; } - int terminal_width = 80; - int terminal_height = 50; - - terminal_size(&terminal_width, &terminal_height); - - view.set_max_size(terminal_height - 15); - // loop through the alert queue to see if anything has happened. std::deque alerts; ses.pop_alerts(&alerts); @@ -1736,8 +1728,7 @@ int main(int argc, char* argv[]) { TORRENT_TRY { - if (!::handle_alert(ses, *i, files, non_files - , stats_counters)) + if (!::handle_alert(ses, *i, files, non_files)) { // if we didn't handle the alert, print it to the log std::string event_string; @@ -1756,8 +1747,9 @@ int main(int argc, char* argv[]) char str[500]; - clear_below(view.height()); - set_cursor_pos(0, view.height()); + int pos = view.height() + ses_view.height(); + clear_rows(pos, terminal_height); + set_cursor_pos(0, pos); int cache_flags = print_downloads ? 0 : lt::session::disk_cache_no_pieces; torrent_handle h = view.get_active_handle(); @@ -1768,44 +1760,6 @@ int main(int argc, char* argv[]) if (cs.blocks_read < 1) cs.blocks_read = 1; if (cs.blocks_written < 1) cs.blocks_written = 1; - snprintf(str, sizeof(str), "==== conns: %d (%d) down: %s%s%s (%s%s%s) up: %s%s%s (%s%s%s) " - "tcp/ip: %s%s%s %s%s%s DHT: %s%s%s %s%s%s tracker: %s%s%s %s%s%s ====\n" - , sess_stat.num_peers, sess_stat.num_dead_peers - , esc("32"), add_suffix(sess_stat.download_rate, "/s").c_str(), esc("0") - , esc("32"), add_suffix(sess_stat.total_download).c_str(), esc("0") - , esc("31"), add_suffix(sess_stat.upload_rate, "/s").c_str(), esc("0") - , esc("31"), add_suffix(sess_stat.total_upload).c_str(), esc("0") - , esc("32"), add_suffix(sess_stat.ip_overhead_download_rate, "/s").c_str(), esc("0") - , esc("31"), add_suffix(sess_stat.ip_overhead_upload_rate, "/s").c_str(), esc("0") - , esc("32"), add_suffix(sess_stat.dht_download_rate, "/s").c_str(), esc("0") - , esc("31"), add_suffix(sess_stat.dht_upload_rate, "/s").c_str(), esc("0") - , esc("32"), add_suffix(sess_stat.tracker_download_rate, "/s").c_str(), esc("0") - , esc("31"), add_suffix(sess_stat.tracker_upload_rate, "/s").c_str(), esc("0")); - out += str; - - snprintf(str, sizeof(str), "==== waste: %s fail: %s unchoked: %d / %d " - "bw queues: %8d (%d) | %8d (%d) disk queues: %d | %d cache: w: %d%% r: %d%% " - "size: w: %s r: %s total: %s ===\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 - , sess_stat.up_bandwidth_bytes_queue - , 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 - , int((cs.blocks_written - cs.writes) * 100 / cs.blocks_written) - , int(cs.blocks_read_hit * 100 / cs.blocks_read) - , add_suffix(boost::int64_t(cs.write_cache_size) * 16 * 1024).c_str() - , add_suffix(boost::int64_t(cs.read_cache_size) * 16 * 1024).c_str() - , add_suffix(boost::int64_t(cs.total_used_buffers) * 16 * 1024).c_str()); - out += str; - - snprintf(str, sizeof(str), "==== optimistic unchoke: %d unchoke counter: %d peerlist: %d ====\n" - , sess_stat.optimistic_unchoke_counter, sess_stat.unchoke_counter, sess_stat.peerlist_size); - out += str; - #ifndef TORRENT_DISABLE_DHT if (show_dht_status) { @@ -1848,51 +1802,6 @@ int main(int argc, char* argv[]) } } #endif - if (print_disk_stats) - { - snprintf(str, sizeof(str), "Disk stats:\n timing - " - " read: %6d ms | write: %6d ms | hash: %6d\n" - , cs.average_read_time / 1000, cs.average_write_time / 1000 - , cs.average_hash_time / 1000); - out += str; - - snprintf(str, sizeof(str), " jobs - queued: %4d (%4d) pending: %4d blocked: %4d " - "queued-bytes: %5" PRId64 " kB\n" - , cs.queued_jobs, cs.peak_queued, cs.pending_jobs, cs.blocked_jobs - , stats_counters[queued_bytes_idx] / 1000); - out += str; - - snprintf(str, sizeof(str), " cache - total: %4d read: %4d write: %4d pinned: %4d write-queue: %4d\n" - , cs.read_cache_size + cs.write_cache_size, cs.read_cache_size, cs.write_cache_size, cs.pinned_blocks - , int(stats_counters[queued_bytes_idx] / 0x4000)); - out += str; - - int mru_size = cs.arc_mru_size + cs.arc_mru_ghost_size; - int mfu_size = cs.arc_mfu_size + cs.arc_mfu_ghost_size; - int arc_size = mru_size + mfu_size; - - snprintf(str, sizeof(str), "LRU: (%d) %d LFU: %d (%d)\n" - , cs.arc_mru_ghost_size, cs.arc_mru_size - , cs.arc_mfu_size, cs.arc_mfu_ghost_size); - out += str; - if (arc_size > 0) - { - out += ' '; - if (mru_size > 0) - { - out += progress_bar(cs.arc_mru_ghost_size * 1000 / mru_size - , mru_size * (terminal_width-3) / arc_size, col_yellow, '-', '#'); - } - out += '|'; - if (mfu_size) - { - out += progress_bar(cs.arc_mfu_size * 1000 / mfu_size - , mfu_size * (terminal_width-3) / arc_size, col_green, '=', '-'); - } - } - out += "\n"; - } - if (print_utp_stats) { snprintf(str, sizeof(str), "uTP idle: %d syn: %d est: %d fin: %d wait: %d\n" @@ -1910,10 +1819,6 @@ int main(int argc, char* argv[]) || print_peers) h.get_peer_info(peers); - out += "====== "; - out += s.name; - out += " ======\n"; - if (print_peers && !peers.empty()) print_peer_info(out, peers); diff --git a/examples/print.cpp b/examples/print.cpp index 9109924c5..81b04a24a 100644 --- a/examples/print.cpp +++ b/examples/print.cpp @@ -142,22 +142,25 @@ void clear_screen() #endif } -void clear_below(int y) +void clear_rows(int y1, int y2) { + if (y1 > y2) return; + #ifdef _WIN32 HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); - COORD c = {0, y}; + COORD c = {0, y1}; SetConsoleCursorPosition(out, c); CONSOLE_SCREEN_BUFFER_INFO si; GetConsoleScreenBufferInfo(out, &si); DWORD n; - FillConsoleOutputCharacter(out, ' ', si.dwSize.X * (si.dwSize.Y - y), c, &n); - FillConsoleOutputAttribute(out, 0x7, si.dwSize.X * (si.dwSize.Y - y), c, &n); + int num_chars = si.dwSize.X * (std::min)(si.dwSize.Y - y1, y2 - y1); + FillConsoleOutputCharacter(out, ' ', num_chars, c, &n); + FillConsoleOutputAttribute(out, 0x7, num_chars, c, &n); #else - printf("\033[%d;1H\033[J", y + 1); + for (int i = y1; i < y2; ++i) + printf("\033[%d;1H\033[2K", i + 1); #endif - } void terminal_size(int* terminal_width, int* terminal_height) diff --git a/examples/print.hpp b/examples/print.hpp index 46b6abf9b..54e310c48 100644 --- a/examples/print.hpp +++ b/examples/print.hpp @@ -31,7 +31,7 @@ void set_cursor_pos(int x, int y); void clear_screen(); -void clear_below(int y); +void clear_rows(int y1, int y2); void terminal_size(int* terminal_width, int* terminal_height); diff --git a/examples/session_view.cpp b/examples/session_view.cpp new file mode 100644 index 000000000..d412fd5d0 --- /dev/null +++ b/examples/session_view.cpp @@ -0,0 +1,168 @@ +#include "session_view.hpp" +#include "print.hpp" + +session_view::session_view() +{ + std::vector metrics = lt::session_stats_metrics(); + m_cnt[0].resize(metrics.size(), 0); + m_cnt[1].resize(metrics.size(), 0); + + m_queued_bytes_idx = find_metric_idx(metrics, "disk.queued_write_bytes"); + m_wasted_bytes_idx = find_metric_idx(metrics, "net.recv_redundant_bytes"); + m_failed_bytes_idx = find_metric_idx(metrics, "net.recv_failed_bytes"); + m_num_peers_idx = find_metric_idx(metrics, "peer.num_peers_connected"); + m_recv_payload_idx = find_metric_idx(metrics, "net.recv_payload_bytes"); + m_sent_payload_idx = find_metric_idx(metrics, "net.sent_payload_bytes"); + m_unchoked_idx = find_metric_idx(metrics, "peer.num_peers_up_unchoked"); + m_unchoke_slots_idx = find_metric_idx(metrics, "ses.num_unchoke_slots"); + m_limiter_up_queue_idx = find_metric_idx(metrics, "net.limiter_up_queue"); + m_limiter_down_queue_idx = find_metric_idx(metrics, "net.limiter_down_queue"); + m_limiter_up_bytes_idx = find_metric_idx(metrics, "net.limiter_up_bytes"); + m_limiter_down_bytes_idx = find_metric_idx(metrics, "net.limiter_down_bytes"); + m_queued_writes_idx = find_metric_idx(metrics, "disk.num_write_jobs"); + m_queued_reads_idx = find_metric_idx(metrics, "disk.num_write_jobs"); + + m_writes_cache_idx = find_metric_idx(metrics, "disk.write_cache_blocks"); + m_reads_cache_idx = find_metric_idx(metrics, "disk.read_cache_blocks"); + m_pinned_idx = find_metric_idx(metrics, "disk.pinned_blocks"); + m_num_blocks_read_idx = find_metric_idx(metrics, "disk.num_blocks_read"); + m_cache_hit_idx = find_metric_idx(metrics, "disk.num_blocks_cache_hits"); + m_blocks_in_use_idx = find_metric_idx(metrics, "disk.disk_blocks_in_use"); + m_blocks_written_idx = find_metric_idx(metrics, "disk.num_blocks_written"); + m_write_ops_idx = find_metric_idx(metrics, "disk.num_write_ops"); +} + +void session_view::set_pos(int pos) +{ + m_position = pos; +} + +int session_view::pos() const { return m_position; } + +int session_view::height() const +{ + return 2; +} + +void session_view::render() +{ + char str[1024]; + int pos = 0; + + int y = m_position; + + float seconds = (m_timestamp[0] - m_timestamp[1]) / 1000000.f; + + int download_rate = (m_cnt[0][m_recv_payload_idx] - m_cnt[1][m_recv_payload_idx]) + / seconds; + int upload_rate = (m_cnt[0][m_sent_payload_idx] - m_cnt[1][m_sent_payload_idx]) + / seconds; + + pos += snprintf(str, sizeof(str), "| conns: %d down: %s (%s) up: %s (%s)\x1b[K" + , int(m_cnt[0][m_num_peers_idx]) + , color(add_suffix(download_rate, "/s"), col_green).c_str() + , color(add_suffix(m_cnt[0][m_recv_payload_idx]), col_green).c_str() + , color(add_suffix(upload_rate, "/s"), col_red).c_str() + , color(add_suffix(m_cnt[0][m_sent_payload_idx]), col_red).c_str()); + + set_cursor_pos(0, y++); + print(str); + + snprintf(str, sizeof(str), "| waste: %s fail: %s unchoked: %d / %d " + "bw queues: %8d (%d) | %8d (%d) disk queues: %d | %d cache: w: %d%% r: %d%% " + "size: w: %s r: %s total: %s\x1b[K" + , add_suffix(m_cnt[0][m_wasted_bytes_idx]).c_str() + , add_suffix(m_cnt[0][m_failed_bytes_idx]).c_str() + , int(m_cnt[0][m_unchoked_idx]) + , int(m_cnt[0][m_unchoke_slots_idx]) + , int(m_cnt[0][m_limiter_up_bytes_idx]) + , int(m_cnt[0][m_limiter_up_queue_idx]) + , int(m_cnt[0][m_limiter_down_bytes_idx]) + , int(m_cnt[0][m_limiter_down_queue_idx]) + , int(m_cnt[0][m_queued_writes_idx]) + , int(m_cnt[0][m_queued_reads_idx]) + , int((m_cnt[0][m_blocks_written_idx] - m_cnt[0][m_write_ops_idx]) * 100 + / (std::max)(boost::uint64_t(1), m_cnt[0][m_blocks_written_idx])) + , int(m_cnt[0][m_cache_hit_idx] * 100 + / (std::max)(boost::uint64_t(1), m_cnt[0][m_num_blocks_read_idx])) + , add_suffix(m_cnt[0][m_writes_cache_idx] * 16 * 1024).c_str() + , add_suffix(m_cnt[0][m_reads_cache_idx] * 16 * 1024).c_str() + , add_suffix(m_cnt[0][m_blocks_in_use_idx] * 16 * 1024).c_str() + ); + set_cursor_pos(0, y++); + print(str); + +/* + snprintf(str, sizeof(str), "| timing - " + " read: %6d ms | write: %6d ms | hash: %6d" + , cs.average_read_time / 1000, cs.average_write_time / 1000 + , cs.average_hash_time / 1000); + + set_cursor_pos(0, y++); + print(str); + + snprintf(str, sizeof(str), "| jobs - queued: %4d (%4d) pending: %4d blocked: %4d " + "queued-bytes: %5" PRId64 " kB" + , cs.queued_jobs, cs.peak_queued, cs.pending_jobs, cs.blocked_jobs + , m_cnt[0][m_queued_bytes_idx] / 1000); + + set_cursor_pos(0, y++); + print(str); + + snprintf(str, sizeof(str), "| cache - total: %4d read: %4d write: %4d pinned: %4d write-queue: %4d" + , cs.read_cache_size + cs.write_cache_size, cs.read_cache_size + , cs.write_cache_size, cs.pinned_blocks + , int(m_cnt[0][m_queued_bytes_idx] / 0x4000)); + set_cursor_pos(0, y++); + print(str); + + int mru_size = cs.arc_mru_size + cs.arc_mru_ghost_size; + int mfu_size = cs.arc_mfu_size + cs.arc_mfu_ghost_size; + int arc_size = mru_size + mfu_size; + + snprintf(str, sizeof(str), "LRU: (%d) %d LFU: %d (%d)\n" + , cs.arc_mru_ghost_size, cs.arc_mru_size + , cs.arc_mfu_size, cs.arc_mfu_ghost_size); + + set_cursor_pos(0, y++); + print(str); + + str[0] = '\0'; + if (arc_size > 0) + { + pos = snprintf(str, sizeof(str), " "); + if (mru_size > 0) + { + pos = snprintf(str + pos, sizeof(str) - pos, "%s" + , progress_bar(cs.arc_mru_ghost_size * 1000 / mru_size + , mru_size * (terminal_width-3) / arc_size, col_yellow, '-', '#').c_str()); + } + pos = snprintf(str, sizeof(str), "|"); + if (mfu_size) + { + pos = snprintf(str + pos, sizeof(str) - pos, "%s" + , progress_bar(cs.arc_mfu_size * 1000 / mfu_size + , mfu_size * (terminal_width-3) / arc_size, col_green, '=', '-').c_str()); + } + } + set_cursor_pos(0, y++); + print(str); +*/ +} + +void session_view::update_counters(std::vector& stats_counters + , boost::uint64_t t) +{ + // only update the previous counters if there's been enough + // time since it was last updated + if (t - m_timestamp[1] > 2000000) + { + m_cnt[1].swap(m_cnt[0]); + m_timestamp[1] = m_timestamp[0]; + } + + m_cnt[0].swap(stats_counters); + m_timestamp[0] = t; + render(); +} + diff --git a/examples/torrent_view.cpp b/examples/torrent_view.cpp index 24182094c..bc074cb22 100644 --- a/examples/torrent_view.cpp +++ b/examples/torrent_view.cpp @@ -45,12 +45,17 @@ torrent_view::torrent_view() : m_active_torrent(0) , m_scroll_position(0) , m_torrent_filter(0) - , m_max_lines(30) + , m_width(80) + , m_height(30) {} -void torrent_view::set_max_size(int height) +void torrent_view::set_size(int width, int height) { - m_max_lines = height; + if (m_width == width && m_height == height) return; + + m_width = width; + m_height = height; + render(); } int torrent_view::filter() const @@ -136,7 +141,7 @@ void torrent_view::update_torrents(std::vector const& st) ++i; continue; } - if (lines_printed >= m_max_lines) + if (lines_printed >= m_height) break; lt::torrent_status const& s = **i; @@ -155,7 +160,7 @@ void torrent_view::update_torrents(std::vector const& st) int torrent_view::height() const { - return int(m_filtered_handles.size() + header_size); + return m_height; } void torrent_view::arrow_up() @@ -197,8 +202,8 @@ void torrent_view::render() // handle scrolling down when moving the cursor // below the fold TORRENT_ASSERT(m_scroll_position >= 0); - if (m_active_torrent >= m_max_lines - m_scroll_position) - m_scroll_position = m_active_torrent - m_max_lines + 1; + if (m_active_torrent >= m_height - m_scroll_position) + m_scroll_position = m_active_torrent - m_height+ 1; TORRENT_ASSERT(m_scroll_position >= 0); if (m_active_torrent < m_scroll_position) m_scroll_position = m_active_torrent; @@ -214,7 +219,7 @@ void torrent_view::render() ++i; continue; } - if (lines_printed >= m_max_lines) + if (lines_printed >= m_height) { print("...\n"); ++lines_printed; @@ -234,7 +239,7 @@ void torrent_view::render() ++lines_printed; } - clear_below(torrent_index + header_size); + clear_rows(torrent_index + header_size, m_height); } void torrent_view::print_tabs() @@ -253,6 +258,8 @@ void torrent_view::print_tabs() } pos += snprintf(str + pos, sizeof(str) - pos, "\x1b[K"); + if (m_width + 1 < sizeof(str)) + str[m_width + 1] = '\0'; print(str); } @@ -269,6 +276,9 @@ void torrent_view::print_headers() , "#", "Name", "Progress", "Download", "Upload", "Peers (D:S)" , "Down", "Up", "Flags"); + if (m_width + 1 < sizeof(str)) + str[m_width + 1] = '\0'; + print(str); } @@ -340,6 +350,9 @@ void torrent_view::print_torrent(lt::torrent_status const& s, bool selected) } */ + if (m_width + 1 < sizeof(str)) + str[m_width + 1] = '\0'; + print(str); } diff --git a/include/libtorrent/performance_counters.hpp b/include/libtorrent/performance_counters.hpp index a03ba9c5e..928217561 100644 --- a/include/libtorrent/performance_counters.hpp +++ b/include/libtorrent/performance_counters.hpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { + // TODO: 3 does this need to be exported? struct TORRENT_EXTRA_EXPORT counters { enum stats_counter_t diff --git a/src/session_stats.cpp b/src/session_stats.cpp index f6c000f52..6e7f74bd4 100644 --- a/src/session_stats.cpp +++ b/src/session_stats.cpp @@ -220,7 +220,7 @@ namespace libtorrent METRIC(ses, torrent_evicted_counter, type_counter) // the number of allowed unchoked peers - METRIC(peer, num_unchoke_slots, type_gauge) + METRIC(ses, num_unchoke_slots, type_gauge) // bittorrent message counters. These counters are incremented // every time a message of the corresponding type is received from