From 7d22044c323dcb9b40ba0dbd5e69200f3ff18556 Mon Sep 17 00:00:00 2001 From: vladimir-ea Date: Wed, 27 May 2026 07:53:42 +0100 Subject: [PATCH 1/2] packet recv allocations --- Cargo.lock | 20 ++++++++++++++++++++ Cargo.toml | 1 + crates/bin/Cargo.toml | 1 + crates/bin/src/main.rs | 5 +++++ crates/e2e/Cargo.toml | 2 ++ crates/e2e/examples/gossip_oneway.rs | 8 ++++++++ crates/e2e/examples/gossip_oneway_lh.rs | 3 +++ crates/network/src/socket/linux.rs | 1 + crates/network/src/socket/portable.rs | 1 + crates/network/src/tile.rs | 17 +++++++++-------- 10 files changed, 51 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9e3a0e0..0b36659 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2404,6 +2404,15 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" +[[package]] +name = "libmimalloc-sys" +version = "0.1.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" +dependencies = [ + "cc", +] + [[package]] name = "libp2p" version = "0.56.0" @@ -2841,6 +2850,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mimalloc" +version = "0.1.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" +dependencies = [ + "libmimalloc-sys", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -4130,6 +4148,7 @@ version = "0.0.1" dependencies = [ "flux", "hex", + "mimalloc", "quinn-proto", "rand 0.8.6", "silver_beacon_state", @@ -4247,6 +4266,7 @@ dependencies = [ "futures", "hdrhistogram", "libp2p", + "mimalloc", "quinn-proto", "rand 0.8.6", "silver_beacon_state", diff --git a/Cargo.toml b/Cargo.toml index 664aa8d..c457033 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,6 +92,7 @@ hdrhistogram = "7.5.4" hex = { version = "0.4", features = ["serde"] } hkdf = "0.12" libc = "0.2" +mimalloc = "0.1.52" mio = { version = "1.0.4", features = ["net", "os-poll"] } pprof = { version = "0.13", features = ["criterion", "flamegraph"] } proc-macro2 = "1" diff --git a/crates/bin/Cargo.toml b/crates/bin/Cargo.toml index 3a1485d..2070a69 100644 --- a/crates/bin/Cargo.toml +++ b/crates/bin/Cargo.toml @@ -16,6 +16,7 @@ silver_peer.workspace = true flux.workspace = true hex.workspace = true +mimalloc.workspace = true quinn-proto.workspace = true rand.workspace = true tracing.workspace = true diff --git a/crates/bin/src/main.rs b/crates/bin/src/main.rs index a9461f2..d84956a 100644 --- a/crates/bin/src/main.rs +++ b/crates/bin/src/main.rs @@ -4,6 +4,7 @@ use flux::{ tile::{TileConfig, attach_tile}, utils::ThreadPriority, }; +use mimalloc::MiMalloc; use quinn_proto::{Endpoint, EndpointConfig}; use rand::RngCore; use silver_beacon_state::{BeaconStateTile, SlotTicker}; @@ -15,6 +16,10 @@ use silver_network::{Context, NetworkTile, P2p}; use silver_peer::PeerManager; use tracing_subscriber::{EnvFilter, fmt::format::FmtSpan}; +#[cfg(not(feature = "alloc-profile"))] +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + fn main() -> Result<(), Box> { #[cfg(feature = "alloc-profile")] let _alloc_profile_guard = silver_common::allocator::init_allocator_trace(); diff --git a/crates/e2e/Cargo.toml b/crates/e2e/Cargo.toml index 548aa02..ed6fff7 100644 --- a/crates/e2e/Cargo.toml +++ b/crates/e2e/Cargo.toml @@ -9,6 +9,7 @@ version.workspace = true buffa.workspace = true flux.workspace = true hdrhistogram.workspace = true +mimalloc.workspace = true quinn-proto.workspace = true rand.workspace = true silver_beacon_state.workspace = true @@ -41,6 +42,7 @@ tokio = { version = "1", features = ["rt", "time", "macros"], optional = true } [features] default = [] lh-client = ["dep:futures", "dep:libp2p", "dep:tokio", "dep:async-trait"] +alloc-profile = ["silver_common/alloc-profile"] [dev-dependencies] tracing.workspace = true diff --git a/crates/e2e/examples/gossip_oneway.rs b/crates/e2e/examples/gossip_oneway.rs index 21e9de5..0d5eeee 100644 --- a/crates/e2e/examples/gossip_oneway.rs +++ b/crates/e2e/examples/gossip_oneway.rs @@ -39,6 +39,7 @@ use std::{ use flux::{tile::Tile, timing::Nanos}; use rand::{Rng, RngCore}; +use mimalloc::MiMalloc; use silver_common::{GossipMsgOut, GossipTopic, NewGossipMsg, P2pSend, PeerEvent, TRandomAccess}; use silver_e2e::{ EchoCompressionHalf, EchoNetworkHalf, EchoStack, PublisherStack, Stats, @@ -55,7 +56,14 @@ const FORK_DIGEST_HEX: &str = "abcd1234"; const TOPIC: GossipTopic = GossipTopic::BeaconBlock; const DRAIN_TIMEOUT: Duration = Duration::from_secs(2); +#[cfg(not(feature = "alloc-profile"))] +#[global_allocator] +static GLOBAL: MiMalloc = MiMalloc; + fn main() { + #[cfg(feature = "alloc-profile")] + let _alloc_profile_guard = silver_common::allocator::init_allocator_trace(); + tracing_subscriber::fmt().with_max_level(tracing::Level::WARN).try_init().ok(); let args = parse_args(); assert!(args.payload_size >= 8, "payload-size must be >= 8 for the timestamp prefix"); diff --git a/crates/e2e/examples/gossip_oneway_lh.rs b/crates/e2e/examples/gossip_oneway_lh.rs index 9b16669..77239bc 100644 --- a/crates/e2e/examples/gossip_oneway_lh.rs +++ b/crates/e2e/examples/gossip_oneway_lh.rs @@ -44,6 +44,9 @@ const TOPIC: GossipTopic = GossipTopic::BeaconBlock; const DRAIN_TIMEOUT: Duration = Duration::from_secs(2); fn main() { + #[cfg(feature = "alloc-profile")] + let _alloc_profile_guard = silver_common::allocator::init_allocator_trace(); + tracing_subscriber::fmt().with_max_level(tracing::Level::WARN).try_init().ok(); let args = parse_args(); assert!(args.payload_size >= 8, "payload-size must be >= 8 for the timestamp prefix"); diff --git a/crates/network/src/socket/linux.rs b/crates/network/src/socket/linux.rs index 26d348e..ab49aea 100644 --- a/crates/network/src/socket/linux.rs +++ b/crates/network/src/socket/linux.rs @@ -71,6 +71,7 @@ impl RxBatch { // `self.count` weren't `take()`d last round — they still have // valid iovec pointers and RX_BUF_SIZE len. for i in 0..self.count { + self.bufs[i].clear(); if !self.bufs[i].try_reclaim(RX_BUF_SIZE) { self.bufs[i] = BytesMut::with_capacity(RX_BUF_SIZE); } diff --git a/crates/network/src/socket/portable.rs b/crates/network/src/socket/portable.rs index 5a5e859..7fd1188 100644 --- a/crates/network/src/socket/portable.rs +++ b/crates/network/src/socket/portable.rs @@ -28,6 +28,7 @@ impl RxBatch { pub(crate) fn recv(&mut self, socket: &UdpSocket) -> usize { // Reclaim only slots that were used last round. for &(buf_idx, _len, _addr) in &self.datagrams { + self.bufs[buf_idx].clear(); if !self.bufs[buf_idx].try_reclaim(RX_BUF_SIZE) { self.bufs[buf_idx] = BytesMut::with_capacity(RX_BUF_SIZE); } diff --git a/crates/network/src/tile.rs b/crates/network/src/tile.rs index de622f4..4581169 100644 --- a/crates/network/src/tile.rs +++ b/crates/network/src/tile.rs @@ -263,14 +263,6 @@ where } let now = Instant::now(); - p2p::p2p_spin( - &self.poll, - &mut self.p2p_endpoint, - &mut self.p2p_socket, - &mut self.context, - now, - &mut |evt| on_event(Event::P2pNet(evt)), - ); for evt in &self.events { if evt.token() == DISC_SOCKET_TOKEN && evt.is_readable() { @@ -287,6 +279,15 @@ where } } + p2p::p2p_spin( + &self.poll, + &mut self.p2p_endpoint, + &mut self.p2p_socket, + &mut self.context, + now, + &mut |evt| on_event(Event::P2pNet(evt)), + ); + self.disc_socket.flush(&self.poll); self.discovery.poll(|disc_event| match disc_event { DiscoveryEvent::SendMessage { to, data } => { From f99a41b1d90e5e6ec99c08e2a2f5ef3da27ecb4d Mon Sep 17 00:00:00 2001 From: vladimir-ea Date: Wed, 27 May 2026 08:19:21 +0100 Subject: [PATCH 2/2] fmt --- crates/bin/src/main.rs | 3 +-- crates/e2e/examples/gossip_oneway.rs | 4 ++-- crates/e2e/examples/gossip_oneway_lh.rs | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/bin/src/main.rs b/crates/bin/src/main.rs index d84956a..f71a93d 100644 --- a/crates/bin/src/main.rs +++ b/crates/bin/src/main.rs @@ -4,7 +4,6 @@ use flux::{ tile::{TileConfig, attach_tile}, utils::ThreadPriority, }; -use mimalloc::MiMalloc; use quinn_proto::{Endpoint, EndpointConfig}; use rand::RngCore; use silver_beacon_state::{BeaconStateTile, SlotTicker}; @@ -18,7 +17,7 @@ use tracing_subscriber::{EnvFilter, fmt::format::FmtSpan}; #[cfg(not(feature = "alloc-profile"))] #[global_allocator] -static GLOBAL: MiMalloc = MiMalloc; +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; fn main() -> Result<(), Box> { #[cfg(feature = "alloc-profile")] diff --git a/crates/e2e/examples/gossip_oneway.rs b/crates/e2e/examples/gossip_oneway.rs index 0d5eeee..02bd015 100644 --- a/crates/e2e/examples/gossip_oneway.rs +++ b/crates/e2e/examples/gossip_oneway.rs @@ -38,8 +38,8 @@ use std::{ }; use flux::{tile::Tile, timing::Nanos}; -use rand::{Rng, RngCore}; use mimalloc::MiMalloc; +use rand::{Rng, RngCore}; use silver_common::{GossipMsgOut, GossipTopic, NewGossipMsg, P2pSend, PeerEvent, TRandomAccess}; use silver_e2e::{ EchoCompressionHalf, EchoNetworkHalf, EchoStack, PublisherStack, Stats, @@ -61,7 +61,7 @@ const DRAIN_TIMEOUT: Duration = Duration::from_secs(2); static GLOBAL: MiMalloc = MiMalloc; fn main() { - #[cfg(feature = "alloc-profile")] + #[cfg(feature = "alloc-profile")] let _alloc_profile_guard = silver_common::allocator::init_allocator_trace(); tracing_subscriber::fmt().with_max_level(tracing::Level::WARN).try_init().ok(); diff --git a/crates/e2e/examples/gossip_oneway_lh.rs b/crates/e2e/examples/gossip_oneway_lh.rs index 77239bc..7f3d56a 100644 --- a/crates/e2e/examples/gossip_oneway_lh.rs +++ b/crates/e2e/examples/gossip_oneway_lh.rs @@ -44,9 +44,9 @@ const TOPIC: GossipTopic = GossipTopic::BeaconBlock; const DRAIN_TIMEOUT: Duration = Duration::from_secs(2); fn main() { - #[cfg(feature = "alloc-profile")] + #[cfg(feature = "alloc-profile")] let _alloc_profile_guard = silver_common::allocator::init_allocator_trace(); - + tracing_subscriber::fmt().with_max_level(tracing::Level::WARN).try_init().ok(); let args = parse_args(); assert!(args.payload_size >= 8, "payload-size must be >= 8 for the timestamp prefix");