perf: reduce excess rand() calls in tr_bandwidth::phaseOne() (#4404)

This commit is contained in:
Charles Kerr 2022-12-18 13:24:46 -06:00 committed by GitHub
parent 128cf34123
commit 9e6ffa351c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 30 additions and 23 deletions

View File

@ -4,7 +4,8 @@
// License text can be found in the licenses/ folder. // License text can be found in the licenses/ folder.
#include <algorithm> #include <algorithm>
#include <utility> // std::swap() #include <random> // for std::mt19937
#include <utility> // for std::swap()
#include <vector> #include <vector>
#include <fmt/core.h> #include <fmt/core.h>
@ -12,7 +13,6 @@
#include "transmission.h" #include "transmission.h"
#include "bandwidth.h" #include "bandwidth.h"
#include "crypto-utils.h" // tr_rand_int()
#include "log.h" #include "log.h"
#include "peer-io.h" #include "peer-io.h"
#include "tr-assert.h" #include "tr-assert.h"
@ -166,31 +166,38 @@ void tr_bandwidth::allocateBandwidth(
void tr_bandwidth::phaseOne(std::vector<tr_peerIo*>& peer_array, tr_direction dir) void tr_bandwidth::phaseOne(std::vector<tr_peerIo*>& peer_array, tr_direction dir)
{ {
/* First phase of IO. Tries to distribute bandwidth fairly to keep faster // First phase of IO. Tries to distribute bandwidth fairly to keep faster
* peers from starving the others. Loop through the peers, giving each a // peers from starving the others.
* small chunk of bandwidth. Keep looping until we run out of bandwidth
* and/or peers that can use it */
tr_logAddTrace(fmt::format("{} peers to go round-robin for {}", peer_array.size(), dir == TR_UP ? "upload" : "download")); tr_logAddTrace(fmt::format("{} peers to go round-robin for {}", peer_array.size(), dir == TR_UP ? "upload" : "download"));
auto n = peer_array.size(); // Shuffle the peers so they all have equal chance to be first in line.
while (n > 0) thread_local auto random_engine = std::mt19937{ std::random_device{}() };
std::shuffle(std::begin(peer_array), std::end(peer_array), random_engine);
// Give each peer `Increment` bandwidth bytes to use. Repeat this
// process until we run out of bandwidth and/or peers that can use it.
for (size_t n_unfinished = std::size(peer_array); n_unfinished > 0U;)
{ {
auto const i = tr_rand_int(n); /* pick a peer at random */ for (size_t i = 0; i < n_unfinished;)
// value of 3000 bytes chosen so that when using µTP we'll send a full-size
// frame right away and leave enough buffered data for the next frame to go
// out in a timely manner.
static auto constexpr Increment = size_t{ 3000 };
auto const bytes_used = peer_array[i]->flush(dir, Increment);
tr_logAddTrace(fmt::format("peer #{} of {} used {} bytes in this pass", i, n, bytes_used));
if (bytes_used != Increment)
{ {
// peer is done writing for now; move it to the end of the list // Value of 3000 bytes chosen so that when using µTP we'll send a full-size
std::swap(peer_array[i], peer_array[n - 1]); // frame right away and leave enough buffered data for the next frame to go
--n; // out in a timely manner.
static auto constexpr Increment = size_t{ 3000 };
auto const bytes_used = peer_array[i]->flush(dir, Increment);
tr_logAddTrace(fmt::format("peer #{} of {} used {} bytes in this pass", i, n_unfinished, bytes_used));
if (bytes_used != Increment)
{
// peer is done writing for now; move it to the end of the list
std::swap(peer_array[i], peer_array[n_unfinished - 1]);
--n_unfinished;
}
else
{
++i;
}
} }
} }
} }