fix frequent dealloc/alloc for utp socket lists (#1496)

fix frequent dealloc/alloc for utp socket lists
This commit is contained in:
Andrei Kurushin 2017-01-09 03:18:26 +03:00 committed by Arvid Norberg
parent ba995fef84
commit 224db08997
2 changed files with 30 additions and 21 deletions

View File

@ -130,23 +130,29 @@ namespace libtorrent
typedef std::multimap<std::uint16_t, utp_socket_impl*> socket_map_t;
socket_map_t m_utp_sockets;
using socket_vector_t = std::vector<utp_socket_impl*>;
// this is a list of sockets that needs to send an ack.
// once the UDP socket is drained, all of these will
// have a chance to do that. This is to avoid sending
// an ack for every single packet
std::vector<utp_socket_impl*> m_deferred_acks;
socket_vector_t m_deferred_acks;
// storage used for saving cpu time on "push_back"
// by using already pre-allocated vector
socket_vector_t m_temp_sockets;
// sockets that have received or sent packets this
// round, may subscribe to the event of draining the
// UDP socket. At that point they may call the
// user callback function to indicate bytes have been
// sent or received.
std::vector<utp_socket_impl*> m_drained_event;
socket_vector_t m_drained_event;
// list of sockets that received EWOULDBLOCK from the
// underlying socket. They are notified when the socket
// becomes writable again
std::vector<utp_socket_impl*> m_stalled_sockets;
socket_vector_t m_stalled_sockets;
// the last socket we received a packet on
utp_socket_impl* m_last_socket = nullptr;

View File

@ -255,38 +255,41 @@ namespace libtorrent
void utp_socket_manager::writable()
{
std::vector<utp_socket_impl*> stalled_sockets;
m_stalled_sockets.swap(stalled_sockets);
for (std::vector<utp_socket_impl*>::iterator i = stalled_sockets.begin()
, end(stalled_sockets.end()); i != end; ++i)
if (!m_stalled_sockets.empty())
{
m_temp_sockets.clear();
m_stalled_sockets.swap(m_temp_sockets);
for (auto const &s : m_temp_sockets)
{
utp_socket_impl* s = *i;
utp_writable(s);
}
}
}
void utp_socket_manager::socket_drained()
{
// flush all deferred acks
std::vector<utp_socket_impl*> deferred_acks;
m_deferred_acks.swap(deferred_acks);
for (std::vector<utp_socket_impl*>::iterator i = deferred_acks.begin()
, end(deferred_acks.end()); i != end; ++i)
if (!m_deferred_acks.empty())
{
m_temp_sockets.clear();
m_deferred_acks.swap(m_temp_sockets);
for (auto const &s : m_temp_sockets)
{
utp_socket_impl* s = *i;
utp_send_ack(s);
}
}
std::vector<utp_socket_impl*> drained_event;
m_drained_event.swap(drained_event);
for (std::vector<utp_socket_impl*>::iterator i = drained_event.begin()
, end(drained_event.end()); i != end; ++i)
if (!m_drained_event.empty())
{
m_temp_sockets.clear();
m_drained_event.swap(m_temp_sockets);
for (auto const &s : m_temp_sockets)
{
utp_socket_impl* s = *i;
utp_socket_drained(s);
}
}
}
void utp_socket_manager::defer_ack(utp_socket_impl* s)
{