From 53c05d283d31d1bfc7b859ada2095d265d66466c Mon Sep 17 00:00:00 2001 From: Jeremy Rubin Date: Mon, 17 Aug 2020 23:26:28 -0700 Subject: [PATCH] Convert net std::list buffers to std::forward_list and track last element Co-authored-by: joshiaastha --- src/net.cpp | 12 +++++++++--- src/net.h | 7 +++++-- src/net_processing.cpp | 6 ++++-- src/test/util/net.cpp | 7 +++++-- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index 8ef770ede22d1..b995b5cd8fcb1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -659,7 +659,7 @@ bool CNode::ReceiveMsgBytes(Span msg_bytes, bool& complete) i->second += result->m_raw_message_size; // push the message to the process queue, - vRecvMsg.push_back(std::move(*result)); + m_recv_msg_most_recent = vRecvMsg.insert_after(m_recv_msg_most_recent, std::move(*result)); complete = true; } @@ -1577,14 +1577,18 @@ void CConnman::SocketHandler() if (notify) { size_t nSizeAdded = 0; auto it(pnode->vRecvMsg.begin()); - for (; it != pnode->vRecvMsg.end(); ++it) { + // it2 will hold the before end iterator. + auto it2 = it; + for (; it != pnode->vRecvMsg.end(); it2 = it++) { // vRecvMsg contains only completed CNetMessage // the single possible partially deserialized message are held by TransportDeserializer nSizeAdded += it->m_raw_message_size; } { LOCK(pnode->cs_vProcessMsg); - pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it); + pnode->vProcessMsg.splice_after(pnode->m_process_msg_most_recent, pnode->vRecvMsg, pnode->vRecvMsg.before_begin(), it); + pnode->m_process_msg_most_recent = it2; + pnode->m_recv_msg_most_recent = pnode->vRecvMsg.before_begin(); pnode->nProcessQueueSize += nSizeAdded; pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize; } @@ -2984,6 +2988,8 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const m_conn_type(conn_type_in), nLocalServices(nLocalServicesIn) { + m_recv_msg_most_recent = vRecvMsg.before_begin(); + m_process_msg_most_recent = vProcessMsg.before_begin(); if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND); hSocket = hSocketIn; addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn; diff --git a/src/net.h b/src/net.h index a8836dfcb4363..d16cb23d1791f 100644 --- a/src/net.h +++ b/src/net.h @@ -37,6 +37,7 @@ #include #include #include +#include class CScheduler; class CNode; @@ -414,7 +415,8 @@ class CNode Mutex cs_vRecv; RecursiveMutex cs_vProcessMsg; - std::list vProcessMsg GUARDED_BY(cs_vProcessMsg); + std::forward_list vProcessMsg GUARDED_BY(cs_vProcessMsg); + std::forward_list::iterator m_process_msg_most_recent GUARDED_BY(cs_vProcessMsg); size_t nProcessQueueSize{0}; RecursiveMutex cs_sendProcessing; @@ -693,7 +695,8 @@ class CNode //! service advertisements. const ServiceFlags nLocalServices; - std::list vRecvMsg; // Used only by SocketHandler thread + std::forward_list vRecvMsg; // Used only by SocketHandler thread + std::forward_list::iterator m_recv_msg_most_recent; mutable RecursiveMutex cs_addrName; std::string addrName GUARDED_BY(cs_addrName); diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 2538904ade140..08f666e2b6f46 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -4035,12 +4035,14 @@ bool PeerManagerImpl::ProcessMessages(CNode* pfrom, std::atomic& interrupt // Don't bother if send buffer is too full to respond anyway if (pfrom->fPauseSend) return false; - std::list msgs; + std::forward_list msgs; { LOCK(pfrom->cs_vProcessMsg); if (pfrom->vProcessMsg.empty()) return false; // Just take one message - msgs.splice(msgs.begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.begin()); + msgs.splice_after(msgs.before_begin(), pfrom->vProcessMsg, pfrom->vProcessMsg.before_begin()); + if (pfrom->vProcessMsg.empty()) + pfrom->m_process_msg_most_recent = pfrom->vProcessMsg.before_begin(); pfrom->nProcessQueueSize -= msgs.front().m_raw_message_size; pfrom->fPauseRecv = pfrom->nProcessQueueSize > m_connman.GetReceiveFloodSize(); fMoreWork = !pfrom->vProcessMsg.empty(); diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp index 28d79670786bb..6231a2ace6a19 100644 --- a/src/test/util/net.cpp +++ b/src/test/util/net.cpp @@ -16,14 +16,17 @@ void ConnmanTestMsg::NodeReceiveMsgBytes(CNode& node, Span msg_by if (complete) { size_t nSizeAdded = 0; auto it(node.vRecvMsg.begin()); - for (; it != node.vRecvMsg.end(); ++it) { + auto it2 = it; + for (; it != node.vRecvMsg.end(); it2 = it++) { // vRecvMsg contains only completed CNetMessage // the single possible partially deserialized message are held by TransportDeserializer nSizeAdded += it->m_raw_message_size; } { LOCK(node.cs_vProcessMsg); - node.vProcessMsg.splice(node.vProcessMsg.end(), node.vRecvMsg, node.vRecvMsg.begin(), it); + node.vProcessMsg.splice_after(node.m_process_msg_most_recent, node.vRecvMsg, node.vRecvMsg.before_begin(), it); + node.m_process_msg_most_recent = it2; + node.m_recv_msg_most_recent = node.vRecvMsg.before_begin(); node.nProcessQueueSize += nSizeAdded; node.fPauseRecv = node.nProcessQueueSize > nReceiveFloodSize; }