don't heap-allocate handlers for incoming UDP packets

This commit is contained in:
arvidn 2017-12-18 00:09:27 +01:00 committed by Arvid Norberg
parent 753826cbb8
commit 40292a1d51
5 changed files with 26 additions and 24 deletions

View File

@ -151,12 +151,12 @@ namespace libtorrent { namespace aux {
template <class Handler, size_t Size>
aux::allocating_handler<Handler, Size>
make_handler(Handler const& handler
make_handler(Handler handler
, handler_storage<Size>& storage
, error_handler_interface& err_handler)
{
return aux::allocating_handler<Handler, Size>(
handler, storage, err_handler);
std::forward<Handler>(handler), storage, err_handler);
}
}
}

View File

@ -199,6 +199,10 @@ namespace aux {
std::shared_ptr<tcp::acceptor> sock;
std::shared_ptr<aux::session_udp_socket> udp_sock;
// since udp packets are expected to be dispatched frequently, this saves
// time on handler allocation every time we read again.
aux::handler_storage<TORRENT_READ_HANDLER_MAX_SIZE> udp_handler_storage;
// the key is an id that is used to identify the
// client with the tracker only.
std::uint32_t tracker_key = 0;
@ -1176,14 +1180,6 @@ namespace aux {
deadline_timer m_timer;
aux::handler_storage<TORRENT_READ_HANDLER_MAX_SIZE> m_tick_handler_storage;
template <class Handler>
aux::allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>
make_tick_handler(Handler const& handler)
{
return aux::allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>(
handler, m_tick_handler_storage, *this);
}
// torrents are announced on the local network in a
// round-robin fashion. All torrents are cycled through
// within the LSD announce interval (which defaults to

View File

@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/utp_socket_manager.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/aux_/allocating_handler.hpp"
#include <boost/asio/io_service.hpp>
#include <vector>
@ -54,6 +55,10 @@ namespace libtorrent { namespace aux {
udp_socket sock;
// since udp packets are expected to be dispatched frequently, this saves
// time on handler allocation every time we read again.
aux::handler_storage<TORRENT_READ_HANDLER_MAX_SIZE> udp_handler_storage;
// this is true when the udp socket send() has failed with EAGAIN or
// EWOULDBLOCK. i.e. we're currently waiting for the socket to become
// writeable again. Once it is, we'll set it to false and notify the utp

View File

@ -502,19 +502,19 @@ POSSIBILITY OF SUCH DAMAGE.
#if !defined(TORRENT_READ_HANDLER_MAX_SIZE)
# ifdef _GLIBCXX_DEBUG
# define TORRENT_READ_HANDLER_MAX_SIZE 400
constexpr std::size_t TORRENT_READ_HANDLER_MAX_SIZE = 400;
# else
// if this is not divisible by 8, we're wasting space
# define TORRENT_READ_HANDLER_MAX_SIZE 336
constexpr std::size_t TORRENT_READ_HANDLER_MAX_SIZE = 336;
# endif
#endif
#if !defined(TORRENT_WRITE_HANDLER_MAX_SIZE)
# ifdef _GLIBCXX_DEBUG
# define TORRENT_WRITE_HANDLER_MAX_SIZE 400
constexpr std::size_t TORRENT_WRITE_HANDLER_MAX_SIZE = 400;
# else
// if this is not divisible by 8, we're wasting space
# define TORRENT_WRITE_HANDLER_MAX_SIZE 336
constexpr std::size_t TORRENT_WRITE_HANDLER_MAX_SIZE = 336;
# endif
#endif

View File

@ -1689,10 +1689,10 @@ namespace {
// internally, this method handle the SOCKS5's connection logic
ret->udp_sock->sock.set_proxy_settings(proxy());
// TODO: 2 use a handler allocator here
ADD_OUTSTANDING_ASYNC("session_impl::on_udp_packet");
ret->udp_sock->sock.async_read(std::bind(&session_impl::on_udp_packet
, this, ret->udp_sock, ret, ret->ssl, _1));
ret->udp_sock->sock.async_read(aux::make_handler(std::bind(&session_impl::on_udp_packet
, this, ret->udp_sock, ret, ret->ssl, _1)
, ret->udp_handler_storage, *this));
#ifndef TORRENT_DISABLE_LOGGING
if (should_log())
@ -2094,10 +2094,10 @@ namespace {
// internally, this method handle the SOCKS5's connection logic
udp_sock->sock.set_proxy_settings(proxy());
// TODO: 2 use a handler allocator here
ADD_OUTSTANDING_ASYNC("session_impl::on_udp_packet");
udp_sock->sock.async_read(std::bind(&session_impl::on_udp_packet
, this, udp_sock, std::weak_ptr<listen_socket_t>(), ep.ssl, _1));
udp_sock->sock.async_read(aux::make_handler(std::bind(&session_impl::on_udp_packet
, this, udp_sock, std::weak_ptr<listen_socket_t>(), ep.ssl, _1)
, udp_sock->udp_handler_storage, *this));
if (!ec && udp_sock)
{
@ -2496,8 +2496,9 @@ namespace {
mgr.socket_drained();
ADD_OUTSTANDING_ASYNC("session_impl::on_udp_packet");
s->sock.async_read(std::bind(&session_impl::on_udp_packet
, this, std::move(socket), std::move(ls), ssl, _1));
s->sock.async_read(make_handler(std::bind(&session_impl::on_udp_packet
, this, std::move(socket), std::move(ls), ssl, _1), s->udp_handler_storage
, *this));
}
void session_impl::async_accept(std::shared_ptr<tcp::acceptor> const& listener
@ -3202,8 +3203,8 @@ namespace {
ADD_OUTSTANDING_ASYNC("session_impl::on_tick");
error_code ec;
m_timer.expires_at(now + milliseconds(m_settings.get_int(settings_pack::tick_interval)), ec);
m_timer.async_wait(make_tick_handler([this](error_code const& err) {
this->wrap(&session_impl::on_tick, err); }));
m_timer.async_wait(aux::make_handler([this](error_code const& err)
{ this->wrap(&session_impl::on_tick, err); }, m_tick_handler_storage, *this));
m_download_rate.update_quotas(now - m_last_tick);
m_upload_rate.update_quotas(now - m_last_tick);