refactor: Values pt. 4 - use Speed in peer_mgr, peer_msgs (#6241)

This commit is contained in:
Charles Kerr 2023-11-12 14:38:27 -06:00 committed by GitHub
parent 0e85befc0f
commit 8ebb5b0bc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 56 additions and 103 deletions

View File

@ -181,10 +181,12 @@ using tr_peer_callback_generic = void (*)(tr_peer* peer, tr_peer_event const& ev
class tr_peer class tr_peer
{ {
public: public:
using Speed = libtransmission::Values::Speed;
tr_peer(tr_torrent const* tor); tr_peer(tr_torrent const* tor);
virtual ~tr_peer(); virtual ~tr_peer();
virtual bool isTransferringPieces(uint64_t now, tr_direction dir, tr_bytes_per_second_t* setme_bytes_per_second) const = 0; [[nodiscard]] virtual Speed get_piece_speed(uint64_t now, tr_direction direction) const = 0;
[[nodiscard]] bool hasPiece(tr_piece_index_t piece) const noexcept [[nodiscard]] bool hasPiece(tr_piece_index_t piece) const noexcept
{ {
@ -208,13 +210,6 @@ public:
// requests that have been made but haven't been fulfilled yet // requests that have been made but haven't been fulfilled yet
[[nodiscard]] virtual size_t activeReqCount(tr_direction) const noexcept = 0; [[nodiscard]] virtual size_t activeReqCount(tr_direction) const noexcept = 0;
[[nodiscard]] tr_bytes_per_second_t get_piece_speed_bytes_per_second(uint64_t now, tr_direction direction) const
{
auto bytes_per_second = tr_bytes_per_second_t{};
isTransferringPieces(now, direction, &bytes_per_second);
return bytes_per_second;
}
virtual void requestBlocks(tr_block_span_t const* block_spans, size_t n_spans) = 0; virtual void requestBlocks(tr_block_span_t const* block_spans, size_t n_spans) = 0;
struct RequestLimit struct RequestLimit

View File

@ -53,6 +53,7 @@
#include "libtransmission/webseed.h" #include "libtransmission/webseed.h"
using namespace std::literals; using namespace std::literals;
using namespace libtransmission::Values;
static auto constexpr CancelHistorySec = int{ 60 }; static auto constexpr CancelHistorySec = int{ 60 };
@ -356,7 +357,7 @@ public:
return std::count_if( return std::count_if(
std::begin(webseeds), std::begin(webseeds),
std::end(webseeds), std::end(webseeds),
[&now](auto const& webseed) { return webseed->isTransferringPieces(now, TR_DOWN, nullptr); }); [&now](auto const& webseed) { return webseed->get_piece_speed(now, TR_DOWN).base_quantity() != 0U; });
} }
[[nodiscard]] TR_CONSTEXPR20 auto peerCount() const noexcept [[nodiscard]] TR_CONSTEXPR20 auto peerCount() const noexcept
@ -1635,8 +1636,8 @@ namespace peer_stat_helpers
stats.progress = peer->percentDone(); stats.progress = peer->percentDone();
stats.isUTP = peer->is_utp_connection(); stats.isUTP = peer->is_utp_connection();
stats.isEncrypted = peer->is_encrypted(); stats.isEncrypted = peer->is_encrypted();
stats.rateToPeer_KBps = tr_toSpeedKBps(peer->get_piece_speed_bytes_per_second(now_msec, TR_CLIENT_TO_PEER)); stats.rateToPeer_KBps = peer->get_piece_speed(now_msec, TR_CLIENT_TO_PEER).count(Speed::Units::KByps);
stats.rateToClient_KBps = tr_toSpeedKBps(peer->get_piece_speed_bytes_per_second(now_msec, TR_PEER_TO_CLIENT)); stats.rateToClient_KBps = peer->get_piece_speed(now_msec, TR_PEER_TO_CLIENT).count(Speed::Units::KByps);
stats.peerIsChoked = peer->peer_is_choked(); stats.peerIsChoked = peer->peer_is_choked();
stats.peerIsInterested = peer->peer_is_interested(); stats.peerIsInterested = peer->peer_is_interested();
stats.clientIsChoked = peer->client_is_choked(); stats.clientIsChoked = peer->client_is_choked();
@ -1812,37 +1813,37 @@ namespace rechoke_uploads_helpers
{ {
struct ChokeData struct ChokeData
{ {
ChokeData(tr_peerMsgs* msgs_in, int rate_in, uint8_t salt_in, bool is_interested_in, bool was_choked_in, bool is_choked_in) ChokeData(tr_peerMsgs* msgs, Speed rate, uint8_t salt, bool is_interested, bool was_choked, bool is_choked)
: msgs{ msgs_in } : msgs_{ msgs }
, rate{ rate_in } , rate_{ rate }
, salt{ salt_in } , salt_{ salt }
, is_interested{ is_interested_in } , is_interested_{ is_interested }
, was_choked{ was_choked_in } , was_choked_{ was_choked }
, is_choked{ is_choked_in } , is_choked_{ is_choked }
{ {
} }
tr_peerMsgs* msgs; tr_peerMsgs* msgs_;
int rate; Speed rate_;
uint8_t salt; uint8_t salt_;
bool is_interested; bool is_interested_;
bool was_choked; bool was_choked_;
bool is_choked; bool is_choked_;
[[nodiscard]] constexpr auto compare(ChokeData const& that) const noexcept // <=> [[nodiscard]] constexpr auto compare(ChokeData const& that) const noexcept // <=>
{ {
// prefer higher overall speeds // prefer higher overall speeds
if (auto const val = tr_compare_3way(this->rate, that.rate); val != 0) if (auto const val = tr_compare_3way(rate_, that.rate_); val != 0)
{ {
return -val; return -val;
} }
if (this->was_choked != that.was_choked) // prefer unchoked if (was_choked_ != that.was_choked_) // prefer unchoked
{ {
return this->was_choked ? 1 : -1; return was_choked_ ? 1 : -1;
} }
return tr_compare_3way(this->salt, that.salt); return tr_compare_3way(salt_, that.salt_);
} }
[[nodiscard]] constexpr auto operator<(ChokeData const& that) const noexcept [[nodiscard]] constexpr auto operator<(ChokeData const& that) const noexcept
@ -1852,23 +1853,22 @@ struct ChokeData
}; };
/* get a rate for deciding which peers to choke and unchoke. */ /* get a rate for deciding which peers to choke and unchoke. */
[[nodiscard]] auto getRateBps(tr_torrent const* tor, tr_peer const* peer, uint64_t now) [[nodiscard]] auto get_rate(tr_torrent const* tor, tr_peer const* peer, uint64_t now)
{ {
if (tor->is_done()) if (tor->is_done())
{ {
return peer->get_piece_speed_bytes_per_second(now, TR_CLIENT_TO_PEER); return peer->get_piece_speed(now, TR_CLIENT_TO_PEER);
} }
/* downloading a private torrent... take upload speed into account // downloading a private torrent... take upload speed into account
* because there may only be a small window of opportunity to share */ // because there may only be a small window of opportunity to share
if (tor->is_private()) if (tor->is_private())
{ {
return peer->get_piece_speed_bytes_per_second(now, TR_PEER_TO_CLIENT) + return peer->get_piece_speed(now, TR_PEER_TO_CLIENT) + peer->get_piece_speed(now, TR_CLIENT_TO_PEER);
peer->get_piece_speed_bytes_per_second(now, TR_CLIENT_TO_PEER);
} }
/* downloading a public torrent */ // downloading a public torrent
return peer->get_piece_speed_bytes_per_second(now, TR_PEER_TO_CLIENT); return peer->get_piece_speed(now, TR_PEER_TO_CLIENT);
} }
// an optimistically unchoked peer is immune from rechoking // an optimistically unchoked peer is immune from rechoking
@ -1916,7 +1916,7 @@ void rechokeUploads(tr_swarm* s, uint64_t const now)
{ {
choked.emplace_back( choked.emplace_back(
peer, peer,
getRateBps(s->tor, peer, now), get_rate(s->tor, peer, now),
salter(), salter(),
peer->peer_is_interested(), peer->peer_is_interested(),
peer->peer_is_choked(), peer->peer_is_choked(),
@ -1951,11 +1951,11 @@ void rechokeUploads(tr_swarm* s, uint64_t const now)
break; break;
} }
item.is_choked = is_maxed_out ? item.was_choked : false; item.is_choked_ = is_maxed_out ? item.was_choked_ : false;
++checked_choke_count; ++checked_choke_count;
if (item.is_interested) if (item.is_interested_)
{ {
++unchoked_interested; ++unchoked_interested;
} }
@ -1968,7 +1968,7 @@ void rechokeUploads(tr_swarm* s, uint64_t const now)
for (auto i = checked_choke_count, n = std::size(choked); i < n; ++i) for (auto i = checked_choke_count, n = std::size(choked); i < n; ++i)
{ {
if (choked[i].is_interested) if (choked[i].is_interested_)
{ {
rand_pool.push_back(&choked[i]); rand_pool.push_back(&choked[i]);
} }
@ -1977,15 +1977,15 @@ void rechokeUploads(tr_swarm* s, uint64_t const now)
if (auto const n = std::size(rand_pool); n != 0) if (auto const n = std::size(rand_pool); n != 0)
{ {
auto* c = rand_pool[tr_rand_int(n)]; auto* c = rand_pool[tr_rand_int(n)];
c->is_choked = false; c->is_choked_ = false;
s->optimistic = c->msgs; s->optimistic = c->msgs_;
s->optimistic_unchoke_time_scaler = OptimisticUnchokeMultiplier; s->optimistic_unchoke_time_scaler = OptimisticUnchokeMultiplier;
} }
} }
for (auto& item : choked) for (auto& item : choked)
{ {
item.msgs->set_choke(item.is_choked); item.msgs_->set_choke(item.is_choked_);
} }
} }
} // namespace rechoke_uploads_helpers } // namespace rechoke_uploads_helpers

View File

@ -381,16 +381,9 @@ public:
} }
} }
bool isTransferringPieces(uint64_t now, tr_direction dir, tr_bytes_per_second_t* setme_bytes_per_second) const override [[nodiscard]] Speed get_piece_speed(uint64_t now, tr_direction dir) const override
{ {
auto const byps = io->get_piece_speed(now, dir).base_quantity(); return io->get_piece_speed(now, dir);
if (setme_bytes_per_second != nullptr)
{
*setme_bytes_per_second = byps;
}
return byps != 0U;
} }
[[nodiscard]] size_t activeReqCount(tr_direction dir) const noexcept override [[nodiscard]] size_t activeReqCount(tr_direction dir) const noexcept override
@ -559,10 +552,10 @@ private:
// Get the rate limit we should use. // Get the rate limit we should use.
// TODO: this needs to consider all the other peers as well... // TODO: this needs to consider all the other peers as well...
uint64_t const now = tr_time_msec(); uint64_t const now = tr_time_msec();
auto rate_bytes_per_second = uint64_t{ get_piece_speed_bytes_per_second(now, TR_PEER_TO_CLIENT) }; auto rate = get_piece_speed(now, TR_PEER_TO_CLIENT);
if (torrent->uses_speed_limit(TR_PEER_TO_CLIENT)) if (torrent->uses_speed_limit(TR_PEER_TO_CLIENT))
{ {
rate_bytes_per_second = std::min(rate_bytes_per_second, torrent->speed_limit(TR_PEER_TO_CLIENT).base_quantity()); rate = std::min(rate, torrent->speed_limit(TR_PEER_TO_CLIENT));
} }
// honor the session limits, if enabled // honor the session limits, if enabled
@ -570,7 +563,7 @@ private:
{ {
if (auto const limit = torrent->session->active_speed_limit(TR_PEER_TO_CLIENT); limit) if (auto const limit = torrent->session->active_speed_limit(TR_PEER_TO_CLIENT); limit)
{ {
rate_bytes_per_second = std::min(rate_bytes_per_second, limit->base_quantity()); rate = std::min(rate, *limit);
} }
} }
@ -578,7 +571,7 @@ private:
// many requests we should send to this peer // many requests we should send to this peer
size_t constexpr Floor = 32; size_t constexpr Floor = 32;
size_t constexpr Seconds = RequestBufSecs; size_t constexpr Seconds = RequestBufSecs;
size_t const estimated_blocks_in_period = (rate_bytes_per_second * Seconds) / tr_block_info::BlockSize; size_t const estimated_blocks_in_period = (rate.base_quantity() * Seconds) / tr_block_info::BlockSize;
size_t const ceil = reqq ? *reqq : 250; size_t const ceil = reqq ? *reqq : 250;
auto max_reqs = estimated_blocks_in_period; auto max_reqs = estimated_blocks_in_period;

View File

@ -480,8 +480,8 @@ namespace make_torrent_field_helpers
peer_map.try_emplace(TR_KEY_peerIsInterested, peer.peerIsInterested); peer_map.try_emplace(TR_KEY_peerIsInterested, peer.peerIsInterested);
peer_map.try_emplace(TR_KEY_port, peer.port); peer_map.try_emplace(TR_KEY_port, peer.port);
peer_map.try_emplace(TR_KEY_progress, peer.progress); peer_map.try_emplace(TR_KEY_progress, peer.progress);
peer_map.try_emplace(TR_KEY_rateToClient, tr_toSpeedBytes(peer.rateToClient_KBps)); peer_map.try_emplace(TR_KEY_rateToClient, Speed{ peer.rateToClient_KBps, Speed::Units::KByps }.base_quantity());
peer_map.try_emplace(TR_KEY_rateToPeer, tr_toSpeedBytes(peer.rateToPeer_KBps)); peer_map.try_emplace(TR_KEY_rateToPeer, Speed{ peer.rateToPeer_KBps, Speed::Units::KByps }.base_quantity());
peers_vec.emplace_back(std::move(peer_map)); peers_vec.emplace_back(std::move(peer_map));
} }
tr_torrentPeersFree(peers, n_peers); tr_torrentPeersFree(peers, n_peers);
@ -675,8 +675,8 @@ namespace make_torrent_field_helpers
case TR_KEY_primary_mime_type: return tor.primary_mime_type(); case TR_KEY_primary_mime_type: return tor.primary_mime_type();
case TR_KEY_priorities: return make_file_priorities_vec(tor); case TR_KEY_priorities: return make_file_priorities_vec(tor);
case TR_KEY_queuePosition: return st.queuePosition; case TR_KEY_queuePosition: return st.queuePosition;
case TR_KEY_rateDownload: return tr_toSpeedBytes(st.pieceDownloadSpeed_KBps); case TR_KEY_rateDownload: return Speed{ st.pieceDownloadSpeed_KBps, Speed::Units::KByps }.base_quantity();
case TR_KEY_rateUpload: return tr_toSpeedBytes(st.pieceUploadSpeed_KBps); case TR_KEY_rateUpload: return Speed{ st.pieceUploadSpeed_KBps, Speed::Units::KByps }.base_quantity();
case TR_KEY_recheckProgress: return st.recheckProgress; case TR_KEY_recheckProgress: return st.recheckProgress;
case TR_KEY_secondsDownloading: return st.secondsDownloading; case TR_KEY_secondsDownloading: return st.secondsDownloading;
case TR_KEY_secondsSeeding: return st.secondsSeeding; case TR_KEY_secondsSeeding: return st.secondsSeeding;

View File

@ -32,7 +32,6 @@ using tr_byte_index_t = uint64_t;
using tr_tracker_tier_t = uint32_t; using tr_tracker_tier_t = uint32_t;
using tr_tracker_id_t = uint32_t; using tr_tracker_id_t = uint32_t;
using tr_torrent_id_t = int; using tr_torrent_id_t = int;
using tr_bytes_per_second_t = size_t;
using tr_mode_t = uint16_t; using tr_mode_t = uint16_t;
struct tr_block_span_t struct tr_block_span_t
@ -1331,7 +1330,7 @@ struct tr_webseed_view
{ {
char const* url; // the url to download from char const* url; // the url to download from
bool is_downloading; // can be true even if speed is 0, e.g. slow download bool is_downloading; // can be true even if speed is 0, e.g. slow download
tr_bytes_per_second_t download_bytes_per_second; // current download speed uint64_t download_bytes_per_second; // current download speed
}; };
struct tr_webseed_view tr_torrentWebseed(tr_torrent const* torrent, size_t nth); struct tr_webseed_view tr_torrentWebseed(tr_torrent const* torrent, size_t nth);

View File

@ -737,15 +737,6 @@ std::string tr_formatter_speed_KBps(double kbyps)
{ {
return Speed{ kbyps, Speed::Units::KByps }.to_string(); return Speed{ kbyps, Speed::Units::KByps }.to_string();
} }
uint64_t tr_toSpeedBytes(size_t kbyps)
{
return Speed{ kbyps, Speed::Units::KByps }.base_quantity();
}
double tr_toSpeedKBps(size_t byps)
{
return Speed{ byps, Speed::Units::Byps }.count(Speed::Units::KByps);
}
// --- formatters: memory // --- formatters: memory
@ -775,11 +766,6 @@ uint64_t tr_toMemBytes(size_t mbytes)
return Memory{ mbytes, Memory::Units::MBytes }.base_quantity(); return Memory{ mbytes, Memory::Units::MBytes }.base_quantity();
} }
double tr_toMemMB(uint64_t bytes)
{
return Memory{ bytes, Memory::Units::Bytes }.count(Memory::Units::MBytes);
}
// --- ENVIRONMENT // --- ENVIRONMENT
bool tr_env_key_exists(char const* key) bool tr_env_key_exists(char const* key)

View File

@ -308,10 +308,7 @@ void tr_formatter_mem_init(size_t base, char const* kb, char const* mb, char con
extern size_t tr_speed_K; extern size_t tr_speed_K;
extern size_t tr_mem_K; extern size_t tr_mem_K;
[[nodiscard]] double tr_toMemMB(uint64_t bytes);
[[nodiscard]] double tr_toSpeedKBps(size_t byps);
[[nodiscard]] uint64_t tr_toMemBytes(size_t mbytes); [[nodiscard]] uint64_t tr_toMemBytes(size_t mbytes);
[[nodiscard]] uint64_t tr_toSpeedBytes(size_t kbyps);
[[nodiscard]] std::string tr_formatter_mem_B(uint64_t bytes); [[nodiscard]] std::string tr_formatter_mem_B(uint64_t bytes);
[[nodiscard]] std::string tr_formatter_mem_MB(double mbytes); [[nodiscard]] std::string tr_formatter_mem_MB(double mbytes);

View File

@ -199,26 +199,9 @@ public:
return tr_torrentFindFromId(session, torrent_id); return tr_torrentFindFromId(session, torrent_id);
} }
[[nodiscard]] bool isTransferringPieces( // [[nodiscard]] Speed get_piece_speed(uint64_t now, tr_direction dir) const override
uint64_t now,
tr_direction dir,
tr_bytes_per_second_t* setme_bytes_per_second) const override
{ {
auto piece_speed = Speed{}; return dir == TR_DOWN ? bandwidth_.get_piece_speed(now, dir) : Speed{};
auto is_active = bool{ false };
if (dir == TR_DOWN)
{
is_active = !std::empty(tasks);
piece_speed = bandwidth_.get_piece_speed(now, dir);
}
if (setme_bytes_per_second != nullptr)
{
*setme_bytes_per_second = piece_speed.base_quantity();
}
return is_active;
} }
[[nodiscard]] TR_CONSTEXPR20 size_t activeReqCount(tr_direction dir) const noexcept override [[nodiscard]] TR_CONSTEXPR20 size_t activeReqCount(tr_direction dir) const noexcept override
@ -547,13 +530,13 @@ tr_peer* tr_webseedNew(tr_torrent* torrent, std::string_view url, tr_peer_callba
tr_webseed_view tr_webseedView(tr_peer const* peer) tr_webseed_view tr_webseedView(tr_peer const* peer)
{ {
auto const* w = dynamic_cast<tr_webseed const*>(peer); auto const* const webseed = dynamic_cast<tr_webseed const*>(peer);
if (w == nullptr) if (webseed == nullptr)
{ {
return {}; return {};
} }
auto bytes_per_second = tr_bytes_per_second_t{ 0 }; auto const is_downloading = !std::empty(webseed->tasks);
auto const is_downloading = peer->isTransferringPieces(tr_time_msec(), TR_DOWN, &bytes_per_second); auto const speed = peer->get_piece_speed(tr_time_msec(), TR_DOWN);
return { w->base_url.c_str(), is_downloading, bytes_per_second }; return { webseed->base_url.c_str(), is_downloading, speed.base_quantity() };
} }