Use `VecDeque`, rather than `LinkedList` in peer message buffering
authorMatt Corallo <git@bluematt.me>
Sat, 4 Nov 2023 20:20:12 +0000 (20:20 +0000)
committerMatt Corallo <git@bluematt.me>
Tue, 7 Nov 2023 18:13:23 +0000 (18:13 +0000)
When buffering outbound messages for peers, `LinkedList` adds
rather substantial allocation overhead, which we avoid here by
swapping for a `VecDeque`.

lightning/src/ln/peer_handler.rs

index a1a4d4b26729c6822227b7d58f576ed0e1725ad1..34110a73a4c66a2e6cde0c66b15d0a224624f5b4 100644 (file)
@@ -40,7 +40,7 @@ use crate::util::string::PrintableString;
 
 use crate::prelude::*;
 use crate::io;
-use alloc::collections::LinkedList;
+use alloc::collections::VecDeque;
 use crate::sync::{Arc, Mutex, MutexGuard, FairRwLock};
 use core::sync::atomic::{AtomicBool, AtomicU32, AtomicI32, Ordering};
 use core::{cmp, hash, fmt, mem};
@@ -489,13 +489,13 @@ struct Peer {
        their_features: Option<InitFeatures>,
        their_socket_address: Option<SocketAddress>,
 
-       pending_outbound_buffer: LinkedList<Vec<u8>>,
+       pending_outbound_buffer: VecDeque<Vec<u8>>,
        pending_outbound_buffer_first_msg_offset: usize,
        /// Queue gossip broadcasts separately from `pending_outbound_buffer` so we can easily
        /// prioritize channel messages over them.
        ///
        /// Note that these messages are *not* encrypted/MAC'd, and are only serialized.
-       gossip_broadcast_buffer: LinkedList<Vec<u8>>,
+       gossip_broadcast_buffer: VecDeque<Vec<u8>>,
        awaiting_write_event: bool,
 
        pending_read_buffer: Vec<u8>,
@@ -997,9 +997,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                        their_features: None,
                                        their_socket_address: remote_network_address,
 
-                                       pending_outbound_buffer: LinkedList::new(),
+                                       pending_outbound_buffer: VecDeque::new(),
                                        pending_outbound_buffer_first_msg_offset: 0,
-                                       gossip_broadcast_buffer: LinkedList::new(),
+                                       gossip_broadcast_buffer: VecDeque::new(),
                                        awaiting_write_event: false,
 
                                        pending_read_buffer,
@@ -1053,9 +1053,9 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                        their_features: None,
                                        their_socket_address: remote_network_address,
 
-                                       pending_outbound_buffer: LinkedList::new(),
+                                       pending_outbound_buffer: VecDeque::new(),
                                        pending_outbound_buffer_first_msg_offset: 0,
-                                       gossip_broadcast_buffer: LinkedList::new(),
+                                       gossip_broadcast_buffer: VecDeque::new(),
                                        awaiting_write_event: false,
 
                                        pending_read_buffer,
@@ -1168,6 +1168,13 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        if peer.pending_outbound_buffer_first_msg_offset == next_buff.len() {
                                peer.pending_outbound_buffer_first_msg_offset = 0;
                                peer.pending_outbound_buffer.pop_front();
+                               const VEC_SIZE: usize = ::core::mem::size_of::<Vec<u8>>();
+                               let large_capacity = peer.pending_outbound_buffer.capacity() > 4096 / VEC_SIZE;
+                               let lots_of_slack = peer.pending_outbound_buffer.len()
+                                       < peer.pending_outbound_buffer.capacity() / 2;
+                               if large_capacity && lots_of_slack {
+                                       peer.pending_outbound_buffer.shrink_to_fit();
+                               }
                        } else {
                                peer.awaiting_write_event = true;
                        }
@@ -1246,6 +1253,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
        /// Append a message to a peer's pending outbound/write gossip broadcast buffer
        fn enqueue_encoded_gossip_broadcast(&self, peer: &mut Peer, encoded_message: Vec<u8>) {
                peer.msgs_sent_since_pong += 1;
+               debug_assert!(peer.gossip_broadcast_buffer.len() <= OUTBOUND_BUFFER_LIMIT_DROP_GOSSIP);
                peer.gossip_broadcast_buffer.push_back(encoded_message);
        }