perf: use timer to flush outbuf to avoid taking lock frequently (#8454)

* perf: use timer to flush outbuf to avoid taking lock frequently

* code review: extract to `flush_outbuf_soon()`

* code review: make `flush_outbuf_trigger_` const

(cherry picked from commit 4d695a8a4c)
This commit is contained in:
Yat Ho
2026-02-12 15:02:54 +08:00
committed by GitHub
parent c2b3f25993
commit 6d85eba3d5
2 changed files with 38 additions and 19 deletions

View File

@@ -30,6 +30,7 @@
#include "libtransmission/peer-io.h"
#include "libtransmission/peer-socket.h" // tr_peer_socket, tr_netOpen...
#include "libtransmission/session.h"
#include "libtransmission/timer.h"
#include "libtransmission/tr-assert.h"
#include "libtransmission/utils.h" // for _()
@@ -82,6 +83,7 @@ tr_peerIo::tr_peerIo(
: bandwidth_{ parent_bandwidth }
, info_hash_{ info_hash != nullptr ? *info_hash : tr_sha1_digest_t{} }
, session_{ session }
, flush_outbuf_trigger_{ session->timerMaker().create() }
, client_is_seed_{ client_is_seed }
, is_incoming_{ is_incoming }
{
@@ -99,8 +101,18 @@ std::shared_ptr<tr_peerIo> tr_peerIo::create(
TR_ASSERT(session != nullptr);
auto lock = session->unique_lock();
auto io = std::make_shared<tr_peerIo>(session, std::move(socket), parent, info_hash, is_incoming, is_seed);
auto const io = std::shared_ptr<tr_peerIo>{
new tr_peerIo{ session, std::move(socket), parent, info_hash, is_incoming, is_seed }
};
io->bandwidth().set_peer(io);
io->flush_outbuf_trigger_->set_callback(
[weak = io->weak_from_this()]
{
if (auto const ptr = weak.lock())
{
ptr->try_write(SIZE_MAX);
}
});
tr_logAddTraceIo(io, fmt::format("bandwidth is {}; its parent is {}", fmt::ptr(&io->bandwidth()), fmt::ptr(parent)));
return io;
}
@@ -567,6 +579,11 @@ size_t tr_peerIo::flush_outgoing_protocol_msgs()
return flush(TR_UP, byte_count);
}
void tr_peerIo::flush_outbuf_soon()
{
flush_outbuf_trigger_->start_single_shot(std::chrono::milliseconds::zero());
}
void tr_peerIo::write_bytes(void const* bytes, size_t n_bytes, bool is_piece_data)
{
if (n_bytes == 0U)
@@ -580,14 +597,7 @@ void tr_peerIo::write_bytes(void const* bytes, size_t n_bytes, bool is_piece_dat
filter_.encrypt(reinterpret_cast<std::byte const*>(bytes), n_bytes, resbuf);
outbuf_.commit_space(n_bytes);
session_->queue_session_thread(
[ptr = weak_from_this()]()
{
if (auto io = ptr.lock(); io)
{
io->try_write(SIZE_MAX);
}
});
flush_outbuf_soon();
}
// ---

View File

@@ -34,10 +34,15 @@ struct tr_error;
struct tr_session;
struct tr_socket_address;
namespace libtransmission::test
namespace libtransmission
{
class Timer;
namespace test
{
class HandshakeTest;
} // namespace libtransmission::test
}
} // namespace libtransmission
enum class ReadState : uint8_t
{
@@ -63,14 +68,6 @@ class tr_peerIo final : public std::enable_shared_from_this<tr_peerIo>
using GotError = void (*)(tr_peerIo* io, tr_error const& error, void* user_data);
public:
tr_peerIo(
tr_session* session,
tr_peer_socket&& socket,
tr_bandwidth* parent_bandwidth,
tr_sha1_digest_t const* info_hash,
bool is_incoming,
bool client_is_seed);
~tr_peerIo();
tr_peerIo(tr_peerIo const&) = delete;
@@ -322,6 +319,14 @@ private:
friend class libtransmission::test::HandshakeTest;
tr_peerIo(
tr_session* session,
tr_peer_socket&& socket,
tr_bandwidth* parent_bandwidth,
tr_sha1_digest_t const* info_hash,
bool is_incoming,
bool client_is_seed);
[[nodiscard]] constexpr auto client_is_seed() const noexcept
{
return client_is_seed_;
@@ -342,6 +347,8 @@ private:
void close();
void flush_outbuf_soon();
static void event_read_cb(evutil_socket_t fd, short /*event*/, void* vio);
static void event_write_cb(evutil_socket_t fd, short /*event*/, void* vio);
@@ -385,6 +392,8 @@ private:
GotError got_error_ = nullptr;
void* user_data_ = nullptr;
std::unique_ptr<libtransmission::Timer> const flush_outbuf_trigger_;
libtransmission::evhelpers::event_unique_ptr event_read_;
libtransmission::evhelpers::event_unique_ptr event_write_;