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.
#include <algorithm>
#include <utility> // std::swap()
#include <random> // for std::mt19937
#include <utility> // for std::swap()
#include <vector>
#include <fmt/core.h>
@ -12,7 +13,6 @@
#include "transmission.h"
#include "bandwidth.h"
#include "crypto-utils.h" // tr_rand_int()
#include "log.h"
#include "peer-io.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)
{
/* First phase of IO. Tries to distribute bandwidth fairly to keep faster
* peers from starving the others. Loop through the peers, giving each a
* small chunk of bandwidth. Keep looping until we run out of bandwidth
* and/or peers that can use it */
// First phase of IO. Tries to distribute bandwidth fairly to keep faster
// peers from starving the others.
tr_logAddTrace(fmt::format("{} peers to go round-robin for {}", peer_array.size(), dir == TR_UP ? "upload" : "download"));
auto n = peer_array.size();
while (n > 0)
// Shuffle the peers so they all have equal chance to be first in line.
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 */
// 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)
for (size_t i = 0; i < n_unfinished;)
{
// peer is done writing for now; move it to the end of the list
std::swap(peer_array[i], peer_array[n - 1]);
--n;
// 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_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;
}
}
}
}