From 479a29348b70bdfbf07015e88b13f3b98bd1e3b4 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 21 Jul 2020 15:28:25 -0400 Subject: [PATCH] Try reducing memory footprint a bit further --- src/bgp_client.rs | 26 +++++++++++++++++++++++++- src/printer.rs | 8 ++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/bgp_client.rs b/src/bgp_client.rs index 8dfb3eb..3e54190 100644 --- a/src/bgp_client.rs +++ b/src/bgp_client.rs @@ -79,6 +79,8 @@ struct RoutingTable { // and Vecs are way more memory-effecient in that case. v4_table: HashMap>, v6_table: HashMap>, + max_paths: usize, + routes_with_max: usize, } impl RoutingTable { @@ -86,6 +88,8 @@ impl RoutingTable { Self { v4_table: HashMap::with_capacity(900_000), v6_table: HashMap::with_capacity(100_000), + max_paths: 0, + routes_with_max: 0, } } @@ -117,6 +121,12 @@ impl RoutingTable { ($rt: expr, $v: expr, $id: expr) => { { match $rt.entry($v.into()) { hash_map::Entry::Occupied(mut entry) => { + if entry.get().len() == self.max_paths { + self.routes_with_max -= 1; + if self.routes_with_max == 0 { + self.max_paths = 0; + } + } entry.get_mut().retain(|e| e.0 != $id); if entry.get_mut().is_empty() { entry.remove(); @@ -151,9 +161,22 @@ impl RoutingTable { fn announce(&mut self, prefix: NLRIEncoding, route: Route) { macro_rules! insert { ($rt: expr, $v: expr, $id: expr) => { { - let entry = $rt.entry($v.into()).or_insert(Vec::new()); + let old_max_paths = self.max_paths; + let entry = $rt.entry($v.into()).or_insert_with(|| Vec::with_capacity(old_max_paths)); + let entry_had_max = entry.len() == self.max_paths; entry.retain(|e| e.0 != $id); + if entry_had_max { + entry.reserve_exact(1); + } else { + entry.reserve_exact(cmp::max(self.max_paths, entry.len() + 1) - entry.len()); + } entry.push(($id, route)); + if entry.len() > self.max_paths { + self.max_paths = entry.len(); + self.routes_with_max = 1; + } else if entry.len() == self.max_paths { + if !entry_had_max { self.routes_with_max += 1; } + } } } } match prefix { @@ -416,6 +439,7 @@ impl BGPClient { } printer.set_stat(Stat::V4RoutingTableSize(route_table.v4_table.len())); printer.set_stat(Stat::V6RoutingTableSize(route_table.v6_table.len())); + printer.set_stat(Stat::RoutingTablePaths(route_table.max_paths)); }, _ => {} } diff --git a/src/printer.rs b/src/printer.rs index 4b65222..e16bfbb 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -13,6 +13,7 @@ pub enum Stat { ConnectionClosed, V4RoutingTableSize(usize), V6RoutingTableSize(usize), + RoutingTablePaths(usize), } struct Stats { @@ -21,6 +22,7 @@ struct Stats { connection_count: u64, v4_table_size: usize, v6_table_size: usize, + paths: usize, } pub struct Printer { @@ -35,6 +37,7 @@ impl Printer { connection_count: 0, v4_table_size: 0, v6_table_size: 0, + paths: 0, })); let thread_arc = Arc::clone(&stats); std::thread::spawn(move || { @@ -88,8 +91,8 @@ impl Printer { } out.write_all(format!( - "\nBGP Routing Table: {} v4 paths, {} v6 paths\n", - stats.v4_table_size, stats.v6_table_size).as_bytes()).expect("stdout broken?"); + "\nBGP Routing Table: {} v4 nets, {} v6 nets, {} max paths\n", + stats.v4_table_size, stats.v6_table_size, stats.paths).as_bytes()).expect("stdout broken?"); out.write_all(b"\nCommands:\n").expect("stdout broken?"); out.write_all(b"q: quit\n").expect("stdout broken?"); @@ -135,6 +138,7 @@ impl Printer { Stat::ConnectionClosed => self.stats.lock().unwrap().connection_count -= 1, Stat::V4RoutingTableSize(c) => self.stats.lock().unwrap().v4_table_size = c, Stat::V6RoutingTableSize(c) => self.stats.lock().unwrap().v6_table_size = c, + Stat::RoutingTablePaths(c) => self.stats.lock().unwrap().paths = c, } } } -- 2.39.5