From ae3be201c43f87ba761212c3a23f14b0e3a1c498 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 19 Jul 2009 04:59:27 +0000 Subject: [PATCH] reduced the number of floating point operations to better support systems with no FPU --- ChangeLog | 2 + bindings/python/src/torrent_status.cpp | 3 + docs/manual.rst | 83 ++++++++++++++++--------- examples/client_test.cpp | 14 ++--- include/libtorrent/config.hpp | 8 +++ include/libtorrent/peer_connection.hpp | 2 +- include/libtorrent/peer_info.hpp | 11 ++-- include/libtorrent/piece_picker.hpp | 2 +- include/libtorrent/session_settings.hpp | 4 +- include/libtorrent/session_status.hpp | 20 +++--- include/libtorrent/stat.hpp | 22 +++---- include/libtorrent/time.hpp | 4 +- include/libtorrent/torrent.hpp | 6 +- include/libtorrent/torrent_handle.hpp | 25 ++++++-- src/kademlia/node.cpp | 2 +- src/peer_connection.cpp | 43 +++++++------ src/piece_picker.cpp | 6 +- src/session_impl.cpp | 10 +-- src/stat.cpp | 8 +-- src/torrent.cpp | 65 ++++++++++++++----- src/torrent_handle.cpp | 2 + 21 files changed, 217 insertions(+), 125 deletions(-) diff --git a/ChangeLog b/ChangeLog index d334fcbb1..8aabcebc7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,5 @@ + * reduced the number of floating point operations (to better support + systems without FPU) * added new alert when individual files complete * added support for storing symbolic links in .torrent files * added support for uTorrent interpretation of multi-tracker torrents diff --git a/bindings/python/src/torrent_status.cpp b/bindings/python/src/torrent_status.cpp index 99022161b..ae53fd85f 100644 --- a/bindings/python/src/torrent_status.cpp +++ b/bindings/python/src/torrent_status.cpp @@ -25,6 +25,7 @@ void bind_torrent_status() .def_readonly("state", &torrent_status::state) .def_readonly("paused", &torrent_status::paused) .def_readonly("progress", &torrent_status::progress) + .def_readonly("progress_ppm", &torrent_status::progress_ppm) .add_property( "next_announce" , make_getter( @@ -59,6 +60,8 @@ void bind_torrent_status() .def_readonly("total_done", &torrent_status::total_done) .def_readonly("total_wanted_done", &torrent_status::total_wanted_done) .def_readonly("total_wanted", &torrent_status::total_wanted) + .def_readonly("distributed_full_copies", &torrent_status::distributed_full_copies) + .def_readonly("distributed_fraction", &torrent_status::distributed_fraction) .def_readonly("distributed_copies", &torrent_status::distributed_copies) .def_readonly("block_size", &torrent_status::block_size) .def_readonly("num_uploads", &torrent_status::num_uploads) diff --git a/docs/manual.rst b/docs/manual.rst index 4a5d4f994..014362068 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -652,28 +652,28 @@ struct has the following members:: { bool has_incoming_connections; - float upload_rate; - float download_rate; + int upload_rate; + int download_rate; size_type total_download; size_type total_upload; - float payload_upload_rate; - float payload_download_rate; + int payload_upload_rate; + int payload_download_rate; size_type total_payload_download; size_type total_payload_upload; - float ip_overhead_upload_rate; - float ip_overhead_download_rate; + int ip_overhead_upload_rate; + int ip_overhead_download_rate; size_type total_ip_overhead_download; size_type total_ip_overhead_upload; - float dht_upload_rate; - float dht_download_rate; + int dht_upload_rate; + int dht_download_rate; size_type total_dht_download; size_type total_dht_upload; - float tracker_upload_rate; - float tracker_download_rate; + int tracker_upload_rate; + int tracker_download_rate; size_type total_tracker_download; size_type total_tracker_upload; @@ -2767,6 +2767,7 @@ It contains the following fields:: state_t state; bool paused; float progress; + int progress_ppm; std::string error; boost::posix_time::time_duration next_announce; @@ -2783,11 +2784,11 @@ It contains the following fields:: size_type total_failed_bytes; size_type total_redundant_bytes; - float download_rate; - float upload_rate; + int download_rate; + int upload_rate; - float download_payload_rate; - float upload_payload_rate; + int download_payload_rate; + int upload_payload_rate; int num_peers; @@ -2807,6 +2808,10 @@ It contains the following fields:: size_type total_wanted; int num_seeds; + + int distributed_full_copies; + int distributed_fraction; + float distributed_copies; int block_size; @@ -2841,8 +2846,13 @@ It contains the following fields:: }; ``progress`` is a value in the range [0, 1], that represents the progress of the -torrent's current task. It may be checking files or downloading. The torrent's -current task is in the ``state`` member, it will be one of the following: +torrent's current task. It may be checking files or downloading. + +``progress_ppm`` reflects the same value as ``progress``, but instead in a range +[0, 1000000] (ppm = parts per million). When floating point operations are disabled, +this is the only alternative to the floating point value in ``progress``. + +The torrent's current task is in the ``state`` member, it will be one of the following: +--------------------------+----------------------------------------------------------+ |``checking_resume_data`` |The torrent is currently checking the fastresume data and | @@ -2969,17 +2979,27 @@ excluding pieces that have been filtered. ``num_seeds`` is the number of peers that are seeding that this client is currently connected to. -``distributed_copies`` is the number of distributed copies of the torrent. -Note that one copy may be spread out among many peers. The integer part -tells how many copies there are currently of the rarest piece(s) among the -peers this client is connected to. The fractional part tells the share of -pieces that have more copies than the rarest piece(s). For example: 2.5 would -mean that the rarest pieces have only 2 copies among the peers this torrent is -connected to, and that 50% of all the pieces have more than two copies. +``distributed_full_copies`` is the number of distributed copies of the torrent. +Note that one copy may be spread out among many peers. It tells how many copies +there are currently of the rarest piece(s) among the peers this client is +connected to. + +``distributed_fraction`` tells the share of pieces that have more copies than +the rarest piece(s). Divide this number by 1000 to get the fraction. + +For example, if ``distributed_full_copies`` is 2 and ``distrbuted_fraction`` +is 500, it means that the rarest pieces have only 2 copies among the peers +this torrent is connected to, and that 50% of all the pieces have more than +two copies. If we are a seed, the piece picker is deallocated as an optimization, and piece availability is no longer tracked. In this case the distributed -copies is set to -1. +copies members are set to -1. + +``distributed_copies`` is a floating point representation of the +``distributed_full_copies`` as the integer part and ``distributed_fraction`` +/ 1000 as the fraction part. If floating point operations are disabled +this value is always -1. ``block_size`` is the size of a block, in bytes. A block is a sub piece, it is the number of bytes that each piece request asks for and the number of @@ -3089,10 +3109,10 @@ It contains the following fields:: char write_state; asio::ip::tcp::endpoint ip; - float up_speed; - float down_speed; - float payload_up_speed; - float payload_down_speed; + int up_speed; + int down_speed; + int payload_up_speed; + int payload_down_speed; size_type total_download; size_type total_upload; peer_id pid; @@ -3154,6 +3174,7 @@ It contains the following fields:: int upload_rate_peak; float progress; + int progress_ppm; }; The ``flags`` attribute tells you in which state the peer is. It is set to @@ -3373,7 +3394,11 @@ estimated by timing the the tcp ``connect()``. It may be 0 for incoming connecti rates seen on this connection. They are given in bytes per second. This number is reset to 0 on reconnect. -``progress`` is the progress of the peer. +``progress`` is the progress of the peer in the range [0, 1]. This is always 0 when +floating point operations are diabled, instead use ``progress_ppm``. + +``progress_ppm`` indicates the download progress of the peer in the range [0, 1000000] +(parts per million). session customization ===================== diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 25cc7e9a2..342dea86a 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -304,13 +304,13 @@ std::string const& piece_bar(libtorrent::bitfield const& p, int width) return bar; } -std::string const& progress_bar(float progress, int width, char const* code = "33") +std::string const& progress_bar(int progress, int width, char const* code = "33") { static std::string bar; bar.clear(); bar.reserve(width + 10); - int progress_chars = static_cast(progress * width + .5f); + int progress_chars = (progress * width + 500) / 1000; bar = esc(code); std::fill_n(std::back_inserter(bar), progress_chars, '#'); bar += esc("0"); @@ -443,11 +443,11 @@ void print_peer_info(std::string& out, std::vector const& if (i->downloading_piece_index >= 0) { out += progress_bar( - i->downloading_progress / float(i->downloading_total), 14); + i->downloading_progress * 1000 / i->downloading_total, 14); } else { - out += progress_bar(0.f, 14); + out += progress_bar(0, 14); } } @@ -1298,7 +1298,7 @@ int main(int argc, char* argv[]) , sequential_download?"sequential":"progress" , esc("32"), s.total_done, esc("0") , s.progress*100.f - , progress_bar(s.progress, terminal_width - 42, progress_bar_color).c_str()); + , progress_bar(s.progress_ppm / 1000, terminal_width - 42, progress_bar_color).c_str()); out += str; if (print_piece_bar && s.progress < 1.f) @@ -1521,8 +1521,8 @@ int main(int argc, char* argv[]) { bool pad_file = info.file_at(i).pad_file; if (!show_pad_files && pad_file) continue; - float progress = info.file_at(i).size > 0 - ?float(file_progress[i]) / info.file_at(i).size:1; + int progress = info.file_at(i).size > 0 + ?file_progress[i] * 1000 / info.file_at(i).size:1000; char const* color = (file_progress[i] == info.file_at(i).size) ?"32":"33"; diff --git a/include/libtorrent/config.hpp b/include/libtorrent/config.hpp index c453ab35d..9596dab1d 100644 --- a/include/libtorrent/config.hpp +++ b/include/libtorrent/config.hpp @@ -119,6 +119,10 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_USE_WPATH 0 #endif +// set this to 1 to disable all floating point operations +// (disables some float-dependent APIs) +#define TORRENT_NO_FPU 1 + #ifdef TORRENT_WINDOWS #include // this is the maximum number of characters in a @@ -154,6 +158,10 @@ inline int snprintf(char* buf, int len, char const* fmt, ...) # define TORRENT_WRITE_HANDLER_MAX_SIZE 256 #endif +#if defined _MSC_VER && _MSC_VER <= 1200 +#define for if (false) {} else for +#endif + // determine what timer implementation we can use #if defined(__MACH__) diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index cdcbbf0f1..bfb3b3d1d 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -293,7 +293,7 @@ namespace libtorrent void add_stat(size_type downloaded, size_type uploaded); // is called once every second by the main loop - void second_tick(float tick_interval); + void second_tick(int tick_interval_ms); void timeout_requests(); diff --git a/include/libtorrent/peer_info.hpp b/include/libtorrent/peer_info.hpp index 3ddbf6180..e2b99dc55 100644 --- a/include/libtorrent/peer_info.hpp +++ b/include/libtorrent/peer_info.hpp @@ -94,10 +94,10 @@ namespace libtorrent char write_state; tcp::endpoint ip; - float up_speed; - float down_speed; - float payload_up_speed; - float payload_down_speed; + int up_speed; + int down_speed; + int payload_up_speed; + int payload_down_speed; size_type total_download; size_type total_upload; peer_id pid; @@ -211,7 +211,8 @@ namespace libtorrent int upload_rate_peak; // the peers progress - float progress; + float progress; // [0, 1] + int progress_ppm; // [0, 1000000] }; struct TORRENT_EXPORT peer_list_entry diff --git a/include/libtorrent/piece_picker.hpp b/include/libtorrent/piece_picker.hpp index b216d0c8d..4b02cb3b8 100644 --- a/include/libtorrent/piece_picker.hpp +++ b/include/libtorrent/piece_picker.hpp @@ -336,7 +336,7 @@ namespace libtorrent int blocks_in_last_piece() const { return m_blocks_in_last_piece; } - float distributed_copies() const; + std::pair distributed_copies() const; private: diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 0f32dcb0d..f5839b43d 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -89,7 +89,7 @@ namespace libtorrent , tracker_maximum_response_length(1024*1024) , piece_timeout(20) , request_timeout(50) - , request_queue_time(3.f) + , request_queue_time(3) , max_allowed_in_request_queue(250) , max_out_request_queue(200) , whole_pieces_threshold(20) @@ -214,7 +214,7 @@ namespace libtorrent // of seconds it should take for the other end to send // all the pieces. i.e. the actual number of requests // depends on the download rate and this number. - float request_queue_time; + int request_queue_time; // the number of outstanding block requests a peer is // allowed to queue up in the client. If a peer sends diff --git a/include/libtorrent/session_status.hpp b/include/libtorrent/session_status.hpp index e1b266283..85ccce9b9 100644 --- a/include/libtorrent/session_status.hpp +++ b/include/libtorrent/session_status.hpp @@ -56,28 +56,28 @@ namespace libtorrent { bool has_incoming_connections; - float upload_rate; - float download_rate; + int upload_rate; + int download_rate; size_type total_download; size_type total_upload; - float payload_upload_rate; - float payload_download_rate; + int payload_upload_rate; + int payload_download_rate; size_type total_payload_download; size_type total_payload_upload; - float ip_overhead_upload_rate; - float ip_overhead_download_rate; + int ip_overhead_upload_rate; + int ip_overhead_download_rate; size_type total_ip_overhead_download; size_type total_ip_overhead_upload; - float dht_upload_rate; - float dht_download_rate; + int dht_upload_rate; + int dht_download_rate; size_type total_dht_download; size_type total_dht_upload; - float tracker_upload_rate; - float tracker_download_rate; + int tracker_upload_rate; + int tracker_download_rate; size_type total_tracker_download; size_type total_tracker_upload; diff --git a/include/libtorrent/stat.hpp b/include/libtorrent/stat.hpp index 95ac5fde3..30bcc31ca 100644 --- a/include/libtorrent/stat.hpp +++ b/include/libtorrent/stat.hpp @@ -74,8 +74,8 @@ namespace libtorrent } // should be called once every second - void second_tick(float tick_interval); - float rate() const { return m_rate_sum / float(history); } + void second_tick(int tick_interval_ms); + int rate() const { return m_rate_sum / history; } size_type rate_sum() const { return m_rate_sum; } size_type total() const { return m_total_counter; } @@ -208,28 +208,28 @@ namespace libtorrent int upload_tracker() const { return m_stat[upload_tracker_protocol].counter(); } // should be called once every second - void second_tick(float tick_interval) + void second_tick(int tick_interval_ms) { for (int i = 0; i < num_channels; ++i) - m_stat[i].second_tick(tick_interval); + m_stat[i].second_tick(tick_interval_ms); } - float upload_rate() const + int upload_rate() const { return (m_stat[upload_payload].rate_sum() + m_stat[upload_protocol].rate_sum() + m_stat[upload_ip_protocol].rate_sum() + m_stat[upload_dht_protocol].rate_sum()) - / float(stat_channel::history); + / stat_channel::history; } - float download_rate() const + int download_rate() const { return (m_stat[download_payload].rate_sum() + m_stat[download_protocol].rate_sum() + m_stat[download_ip_protocol].rate_sum() + m_stat[download_dht_protocol].rate_sum()) - / float(stat_channel::history); + / stat_channel::history; } size_type total_upload() const @@ -250,9 +250,9 @@ namespace libtorrent + m_stat[download_tracker_protocol].total(); } - float upload_payload_rate() const + int upload_payload_rate() const { return m_stat[upload_payload].rate(); } - float download_payload_rate() const + int download_payload_rate() const { return m_stat[download_payload].rate(); } size_type total_payload_upload() const @@ -267,7 +267,7 @@ namespace libtorrent size_type total_transfer(int channel) const { return m_stat[channel].total(); } - float transfer_rate(int channel) const + int transfer_rate(int channel) const { return m_stat[channel].rate(); } // this is used to offset the statistics when a diff --git a/include/libtorrent/time.hpp b/include/libtorrent/time.hpp index 75bca0dad..80e980d7c 100644 --- a/include/libtorrent/time.hpp +++ b/include/libtorrent/time.hpp @@ -121,9 +121,9 @@ namespace libtorrent { return lhs.diff > rhs.diff; } inline bool operator>=(time_duration lhs, time_duration rhs) { return lhs.diff >= rhs.diff; } - inline time_duration operator*(time_duration lhs, float rhs) + inline time_duration operator*(time_duration lhs, int rhs) { return time_duration(boost::int64_t(lhs.diff * rhs)); } - inline time_duration operator*(float lhs, time_duration rhs) + inline time_duration operator*(int lhs, time_duration rhs) { return time_duration(boost::int64_t(lhs * rhs.diff)); } // libtorrent time type diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 154333f6f..9aeb38278 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -206,7 +206,7 @@ namespace libtorrent void set_queue_position(int p); int queue_position() const { return m_sequence_number; } - void second_tick(stat& accumulator, float tick_interval); + void second_tick(stat& accumulator, int tick_interval_ms); std::string name() const; @@ -248,7 +248,9 @@ namespace libtorrent bool is_piece_filtered(int index) const; void filtered_pieces(std::vector& bitmask) const; void filter_files(std::vector const& files); +#if !TORRENT_NO_FPU void file_progress(std::vector& fp) const; +#endif // ============ end deprecation ============= void piece_availability(std::vector& avail) const; @@ -937,7 +939,7 @@ namespace libtorrent storage_constructor_type m_storage_constructor; - float m_progress; + int m_progress_ppm; // the upload/download ratio that each peer // tries to maintain. diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 66f696160..02411a2e2 100644 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -79,6 +79,7 @@ namespace libtorrent : state(checking_resume_data) , paused(false) , progress(0.f) + , progress_ppm(0) , total_download(0) , total_upload(0) , total_payload_download(0) @@ -134,6 +135,10 @@ namespace libtorrent state_t state; bool paused; float progress; + // progress parts per million (progress * 1000000) + // when disabling floating point operations, this is + // the only option to query progress + int progress_ppm; std::string error; boost::posix_time::time_duration next_announce; @@ -160,13 +165,13 @@ namespace libtorrent // current transfer rate // payload plus protocol - float download_rate; - float upload_rate; + int download_rate; + int upload_rate; // the rate of payload that is // sent and received - float download_payload_rate; - float upload_payload_rate; + int download_payload_rate; + int upload_payload_rate; // the number of peers this torrent is connected to // that are seeding. @@ -227,6 +232,16 @@ namespace libtorrent // // the fractional part tells the fraction of pieces that // have more copies than the rarest piece(s). + + // the number of full distributed copies (i.e. the number + // of peers that have the rarest piece) + int distributed_full_copies; + + // the fraction of pieces that more peers has than the + // rarest pieces. This indicates how close the swarm is + // to have one more full distributed copy + int distributed_fraction; + float distributed_copies; // the block size that is used in this torrent. i.e. @@ -366,10 +381,12 @@ namespace libtorrent void set_piece_deadline(int index, time_duration deadline, int flags = 0) const; #ifndef TORRENT_NO_DEPRECATE +#if !TORRENT_NO_FPU // fills the specified vector with the download progress [0, 1] // of each file in the torrent. The files are ordered as in // the torrent_info. void file_progress(std::vector& progress) const TORRENT_DEPRECATED; +#endif #endif enum file_progress_flags_t { diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index c3157fc9f..74899fe8b 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -346,7 +346,7 @@ time_duration node_impl::refresh_timeout() time_duration next_refresh = next - now; time_duration min_next_refresh - = minutes(15) / (m_table.num_active_buckets()); + = minutes(15) / m_table.num_active_buckets(); if (min_next_refresh > seconds(40)) min_next_refresh = seconds(40); diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index 99845ec53..d36f5e6f7 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -3064,7 +3064,13 @@ namespace libtorrent p.write_state = m_channel_state[upload_channel]; p.read_state = m_channel_state[download_channel]; +#if TORRENT_NO_FPU + p.progress = 0.f; +#else p.progress = (float)p.pieces.count() / (float)p.pieces.size(); +#endif + + p.progress_ppm = p.pieces.count() * 1000000 / p.pieces.size(); } // allocates a disk buffer of size 'disk_buffer_size' and replaces the @@ -3165,7 +3171,7 @@ namespace libtorrent m_superseed_piece = index; } - void peer_connection::second_tick(float tick_interval) + void peer_connection::second_tick(int tick_interval_ms) { ptime now = time_now(); boost::intrusive_ptr me(self()); @@ -3319,7 +3325,7 @@ namespace libtorrent m_ignore_bandwidth_limits = m_ses.settings().ignore_limits_on_local_network && on_local_network(); - m_statistics.second_tick(tick_interval); + m_statistics.second_tick(tick_interval_ms); if (m_statistics.upload_payload_rate() > m_upload_rate_peak) { @@ -3342,7 +3348,7 @@ namespace libtorrent if (!t->ready_for_connections()) return; // calculate the desired download queue size - const float queue_time = m_ses.settings().request_queue_time; + const int queue_time = m_ses.settings().request_queue_time; // (if the latency is more than this, the download will stall) // so, the queue size is queue_time * down_rate / 16 kiB // (16 kB is the size of each request) @@ -3358,8 +3364,8 @@ namespace libtorrent } else { - m_desired_queue_size = static_cast(queue_time - * statistics().download_rate() / block_size); + m_desired_queue_size = queue_time + * statistics().download_rate() / block_size; if (m_desired_queue_size > m_max_out_request_queue) m_desired_queue_size = m_max_out_request_queue; if (m_desired_queue_size < min_request_queue) @@ -3426,40 +3432,37 @@ namespace libtorrent { size_type bias = 0x10000 + 2 * t->block_size() + m_free_upload; - double break_even_time = 15; // seconds. + const int break_even_time = 15; // seconds. size_type have_uploaded = m_statistics.total_payload_upload(); size_type have_downloaded = m_statistics.total_payload_download(); - double download_speed = m_statistics.download_rate(); + int download_speed = m_statistics.download_rate(); size_type soon_downloaded = - have_downloaded + (size_type)(download_speed * break_even_time*1.5); + have_downloaded + (size_type)(download_speed * (break_even_time + break_even_time / 2)); if (t->ratio() != 1.f) - soon_downloaded = (size_type)(soon_downloaded*(double)t->ratio()); + soon_downloaded = size_type(soon_downloaded * t->ratio()); - double upload_speed_limit = (soon_downloaded - have_uploaded + int upload_speed_limit = (soon_downloaded - have_uploaded + bias) / break_even_time; if (m_upload_limit > 0 && m_upload_limit < upload_speed_limit) upload_speed_limit = m_upload_limit; - upload_speed_limit = (std::min)(upload_speed_limit, - (double)(std::numeric_limits::max)()); + upload_speed_limit = (std::min)(upload_speed_limit, (std::numeric_limits::max)()); m_bandwidth_channel[upload_channel].throttle( - (std::min)((std::max)((int)upload_speed_limit, 10) - , m_upload_limit)); + (std::min)((std::max)(upload_speed_limit, 10), m_upload_limit)); } // update once every minute if (now - m_remote_dl_update >= seconds(60)) { - float factor = 0.6666666666667f; - - if (m_remote_dl_rate == 0) factor = 0.0f; - - m_remote_dl_rate = int((m_remote_dl_rate * factor) + - ((m_remote_bytes_dled * (1.0f-factor)) / 60.f)); + if (m_remote_dl_rate > 0) + m_remote_dl_rate = (m_remote_dl_rate * 2 / 3) + + ((m_remote_bytes_dled / 3) / 60); + else + m_remote_dl_rate = m_remote_dl_rate / 60; m_remote_bytes_dled = 0; m_remote_dl_update = now; diff --git a/src/piece_picker.cpp b/src/piece_picker.cpp index d30598ff6..11c2cf01b 100644 --- a/src/piece_picker.cpp +++ b/src/piece_picker.cpp @@ -469,10 +469,10 @@ namespace libtorrent } #endif - float piece_picker::distributed_copies() const + std::pair piece_picker::distributed_copies() const { TORRENT_ASSERT(m_seeds >= 0); - const float num_pieces = static_cast(m_piece_map.size()); + const int num_pieces = m_piece_map.size(); int min_availability = piece_pos::max_peer_count; // find the lowest availability count @@ -503,7 +503,7 @@ namespace libtorrent } } TORRENT_ASSERT(integer_part + fraction_part == num_pieces); - return float(min_availability + m_seeds) + (fraction_part / num_pieces); + return std::make_pair(min_availability + m_seeds, fraction_part * 1000 / num_pieces); } void piece_picker::priority_range(int prio, int* start, int* end) diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 47ce0ca8a..9d50abc3d 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -1198,7 +1198,7 @@ namespace aux { // only tick the following once per second if (now - m_last_second_tick < seconds(1)) return; - float tick_interval = total_microseconds(now - m_last_second_tick) / 1000000.f; + int tick_interval_ms = total_milliseconds(now - m_last_second_tick); m_last_second_tick = now; int session_time = total_seconds(now - m_created); @@ -1241,8 +1241,8 @@ namespace aux { int seeding_torrents = 0; static size_type downloaded = 0; static size_type uploaded = 0; - size_type download_rate = (m_stat.total_download() - downloaded) / tick_interval; - size_type upload_rate = (m_stat.total_upload() - uploaded) / tick_interval; + size_type download_rate = (m_stat.total_download() - downloaded) * 1000 / tick_interval_ms; + size_type upload_rate = (m_stat.total_upload() - uploaded) * 1000 / tick_interval_ms; downloaded = m_stat.total_download(); uploaded = m_stat.total_upload(); size_type num_peers = 0; @@ -1355,7 +1355,7 @@ namespace aux { num_downloads_peers += t.num_peers(); } - t.second_tick(m_stat, tick_interval); + t.second_tick(m_stat, tick_interval_ms); ++i; } @@ -1413,7 +1413,7 @@ namespace aux { } } - m_stat.second_tick(tick_interval); + m_stat.second_tick(tick_interval_ms); // -------------------------------------------------------------- // scrape paused torrents that are auto managed diff --git a/src/stat.cpp b/src/stat.cpp index 18a3285f8..97c33d765 100644 --- a/src/stat.cpp +++ b/src/stat.cpp @@ -43,14 +43,10 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/stat.hpp" #include "libtorrent/invariant_check.hpp" -#if defined _MSC_VER && _MSC_VER <= 1200 -#define for if (false) {} else for -#endif - namespace libtorrent { -void stat_channel::second_tick(float tick_interval) +void stat_channel::second_tick(int tick_interval_ms) { INVARIANT_CHECK; @@ -59,7 +55,7 @@ void stat_channel::second_tick(float tick_interval) for (int i = history - 2; i >= 0; --i) m_rate_history[i + 1] = m_rate_history[i]; - m_rate_history[0] = m_counter / tick_interval; + m_rate_history[0] = m_counter * 1000 / tick_interval_ms; m_rate_sum += m_rate_history[0]; m_counter = 0; } diff --git a/src/torrent.cpp b/src/torrent.cpp index 2fd7e3bcb..1a8e3c8bb 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -167,7 +167,7 @@ namespace libtorrent , m_state(torrent_status::checking_resume_data) , m_settings(ses.settings()) , m_storage_constructor(p.storage) - , m_progress(0.f) + , m_progress_ppm(0) , m_ratio(0.f) , m_max_uploads((std::numeric_limits::max)()) , m_num_uploads(0) @@ -1014,7 +1014,7 @@ namespace libtorrent return; } - m_progress = j.piece / float(torrent_file().num_pieces()); + m_progress_ppm = j.piece * 1000000 / torrent_file().num_pieces(); TORRENT_ASSERT(m_picker); if (j.offset >= 0 && !m_picker->have_piece(j.offset)) @@ -2344,9 +2344,9 @@ namespace libtorrent { time_duration diff = dl_time - m_average_piece_time; if (m_piece_time_deviation == seconds(0)) m_piece_time_deviation = diff; - else m_piece_time_deviation = m_piece_time_deviation * 0.6f + diff * 0.4; + else m_piece_time_deviation = (m_piece_time_deviation * 6 + diff * 4) / 10; - m_average_piece_time = m_average_piece_time * 0.6f + dl_time * 0.4f; + m_average_piece_time = (m_average_piece_time * 6 + dl_time * 4) / 10; } } m_time_critical_pieces.erase(i); @@ -5016,7 +5016,7 @@ namespace libtorrent announce_with_tracker(tracker_request::stopped); } - void torrent::second_tick(stat& accumulator, float tick_interval) + void torrent::second_tick(stat& accumulator, int tick_interval_ms) { INVARIANT_CHECK; @@ -5069,7 +5069,7 @@ namespace libtorrent if (is_paused()) { // let the stats fade out to 0 - m_stat.second_tick(tick_interval); + m_stat.second_tick(tick_interval_ms); return; } @@ -5095,7 +5095,7 @@ namespace libtorrent } } - time_duration since_last_tick = microsec(tick_interval * 1000000L); + time_duration since_last_tick = milliseconds(tick_interval_ms); if (is_seed()) m_seeding_time += since_last_tick; m_active_time += since_last_tick; @@ -5162,7 +5162,7 @@ namespace libtorrent try { #endif - p->second_tick(tick_interval); + p->second_tick(tick_interval_ms); #ifndef BOOST_NO_EXCEPTIONS } catch (std::exception& e) @@ -5177,7 +5177,7 @@ namespace libtorrent accumulator += m_stat; m_total_uploaded += m_stat.last_payload_uploaded(); m_total_downloaded += m_stat.last_payload_downloaded(); - m_stat.second_tick(tick_interval); + m_stat.second_tick(tick_interval_ms); } void torrent::request_time_critical_pieces() @@ -5369,6 +5369,7 @@ namespace libtorrent return &*i; } +#if !TORRENT_NO_FPU void torrent::file_progress(std::vector& fp) const { fp.clear(); @@ -5384,6 +5385,7 @@ namespace libtorrent else fp[i] = float(progress[i]) / f.size; } } +#endif void torrent::file_progress(std::vector& fp, int flags) const { @@ -5657,7 +5659,10 @@ namespace libtorrent if (!valid_metadata()) { st.state = torrent_status::downloading_metadata; - st.progress = m_progress; + st.progress_ppm = m_progress_ppm; +#if !TORRENT_NO_FPU + st.progress = m_progress_ppm / 1000000.f; +#endif st.block_size = 0; return st; } @@ -5665,10 +5670,25 @@ namespace libtorrent st.block_size = block_size(); if (m_state == torrent_status::checking_files) - st.progress = m_progress; - else if (st.total_wanted == 0) st.progress = 1.f; - else st.progress = st.total_wanted_done - / static_cast(st.total_wanted); + { + st.progress_ppm = m_progress_ppm; +#if !TORRENT_NO_FPU + st.progress = m_progress_ppm / 1000000.f; +#endif + } + else if (st.total_wanted == 0) + { + st.progress_ppm = 1000000; + st.progress = 1.f; + } + else + { + st.progress_ppm = st.total_wanted_done * 1000000 + / st.total_wanted; +#if !TORRENT_NO_FPU + st.progress = st.progress_ppm / 1000000.f; +#endif + } if (has_picker()) { @@ -5681,9 +5701,22 @@ namespace libtorrent st.num_pieces = num_have(); st.num_seeds = num_seeds(); if (m_picker.get()) - st.distributed_copies = m_picker->distributed_copies(); + { + boost::tie(st.distributed_full_copies, st.distributed_fraction) = + m_picker->distributed_copies(); +#if TORRENT_NO_FPU + st.distributed_copies = -1.f; +#else + st.distributed_copies = st.distributed_full_copies + + float(st.distributed_fraction) / 1000; +#endif + } else - st.distributed_copies = -1; + { + st.distributed_full_copies = -1; + st.distributed_fraction = -1; + st.distributed_copies = -1.f; + } return st; } diff --git a/src/torrent_handle.cpp b/src/torrent_handle.cpp index 82f923da3..568e845e3 100644 --- a/src/torrent_handle.cpp +++ b/src/torrent_handle.cpp @@ -371,11 +371,13 @@ namespace libtorrent } #ifndef TORRENT_NO_DEPRECATE +#if !TORRENT_NO_FPU void torrent_handle::file_progress(std::vector& progress) const { INVARIANT_CHECK; TORRENT_FORWARD(file_progress(progress)); } +#endif #endif void torrent_handle::file_progress(std::vector& progress, int flags) const