Merge pull request #21 from greatest-ape/amortized-maps

Replace HashMap and IndexMap for most state with indexmap_amortized
This commit is contained in:
Joakim Frostegård 2021-11-05 11:22:50 +01:00 committed by GitHub
commit 7df90171b1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 55 additions and 41 deletions

38
Cargo.lock generated
View file

@ -74,11 +74,12 @@ dependencies = [
name = "aquatic_common" name = "aquatic_common"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ahash 0.7.6",
"anyhow", "anyhow",
"arc-swap", "arc-swap",
"hashbrown 0.11.2", "hashbrown 0.11.2",
"hex", "hex",
"indexmap", "indexmap-amortized",
"log", "log",
"privdrop", "privdrop",
"rand", "rand",
@ -99,8 +100,6 @@ dependencies = [
"futures-lite", "futures-lite",
"futures-rustls", "futures-rustls",
"glommio", "glommio",
"hashbrown 0.11.2",
"indexmap",
"itoa", "itoa",
"log", "log",
"memchr", "memchr",
@ -171,10 +170,8 @@ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"futures-lite", "futures-lite",
"glommio", "glommio",
"hashbrown 0.11.2",
"hex", "hex",
"histogram", "histogram",
"indexmap",
"log", "log",
"mimalloc", "mimalloc",
"mio", "mio",
@ -250,7 +247,6 @@ dependencies = [
"futures-rustls", "futures-rustls",
"glommio", "glommio",
"hashbrown 0.11.2", "hashbrown 0.11.2",
"indexmap",
"log", "log",
"mimalloc", "mimalloc",
"privdrop", "privdrop",
@ -330,6 +326,12 @@ dependencies = [
"tungstenite", "tungstenite",
] ]
[[package]]
name = "atone"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a8a5a5e2e3b1e128ec3783765c91c1f392172c1fffc90fd1b96a13bb18e0dd6"
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -927,6 +929,15 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "griddle"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e46a17d0c5d05b045e3814403914aeeb952aa9832f47b1d7ab123ab3d1660454"
dependencies = [
"hashbrown 0.9.1",
]
[[package]] [[package]]
name = "half" name = "half"
version = "1.8.0" version = "1.8.0"
@ -953,6 +964,12 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "hashbrown"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.11.2" version = "0.11.2"
@ -1013,13 +1030,14 @@ dependencies = [
] ]
[[package]] [[package]]
name = "indexmap" name = "indexmap-amortized"
version = "1.7.0" version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" checksum = "81b5a05ffb45214e51fdd40c1f773ab57c74d2a7b41cfadc7ea443acf0359df1"
dependencies = [ dependencies = [
"atone",
"autocfg", "autocfg",
"hashbrown 0.11.2", "griddle",
] ]
[[package]] [[package]]

View file

@ -11,11 +11,12 @@ repository = "https://github.com/greatest-ape/aquatic"
name = "aquatic_common" name = "aquatic_common"
[dependencies] [dependencies]
ahash = "0.7"
anyhow = "1" anyhow = "1"
arc-swap = "1" arc-swap = "1"
hashbrown = "0.11.2" hashbrown = "0.11.2"
hex = "0.4" hex = "0.4"
indexmap = "1" indexmap-amortized = "1"
log = "0.4" log = "0.4"
privdrop = "0.5" privdrop = "0.5"
rand = { version = "0.8", features = ["small_rng"] } rand = { version = "0.8", features = ["small_rng"] }

View file

@ -1,13 +1,15 @@
use std::net::IpAddr; use std::net::IpAddr;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use indexmap::IndexMap; use ahash::RandomState;
use rand::Rng; use rand::Rng;
pub mod access_list; pub mod access_list;
pub mod cpu_pinning; pub mod cpu_pinning;
pub mod privileges; pub mod privileges;
pub type AHashIndexMap<K, V> = indexmap_amortized::IndexMap<K, V, RandomState>;
/// Peer or connection valid until this instant /// Peer or connection valid until this instant
/// ///
/// Used instead of "last seen" or similar to hopefully prevent arithmetic /// Used instead of "last seen" or similar to hopefully prevent arithmetic
@ -32,7 +34,7 @@ impl ValidUntil {
#[inline] #[inline]
pub fn extract_response_peers<K, V, R, F>( pub fn extract_response_peers<K, V, R, F>(
rng: &mut impl Rng, rng: &mut impl Rng,
peer_map: &IndexMap<K, V>, peer_map: &AHashIndexMap<K, V>,
max_num_peers_to_take: usize, max_num_peers_to_take: usize,
sender_peer_map_key: K, sender_peer_map_key: K,
peer_conversion_function: F, peer_conversion_function: F,

View file

@ -26,8 +26,6 @@ either = "1"
futures-lite = "1" futures-lite = "1"
futures-rustls = "0.22" futures-rustls = "0.22"
glommio = { git = "https://github.com/DataDog/glommio.git", rev = "4e6b14772da2f4325271fbcf12d24cf91ed466e5" } glommio = { git = "https://github.com/DataDog/glommio.git", rev = "4e6b14772da2f4325271fbcf12d24cf91ed466e5" }
hashbrown = "0.11.2"
indexmap = "1"
itoa = "0.4" itoa = "0.4"
log = "0.4" log = "0.4"
mimalloc = { version = "0.1", default-features = false } mimalloc = { version = "0.1", default-features = false }

View file

@ -3,9 +3,8 @@ use std::sync::Arc;
use std::time::Instant; use std::time::Instant;
use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap, AccessListCache}; use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap, AccessListCache};
use aquatic_common::AHashIndexMap;
use either::Either; use either::Either;
use hashbrown::HashMap;
use indexmap::IndexMap;
use smartstring::{LazyCompact, SmartString}; use smartstring::{LazyCompact, SmartString};
pub use aquatic_common::{convert_ipv4_mapped_ipv6, ValidUntil}; pub use aquatic_common::{convert_ipv4_mapped_ipv6, ValidUntil};
@ -141,7 +140,7 @@ pub struct PeerMapKey<I: Ip> {
pub ip_or_key: Either<I, SmartString<LazyCompact>>, pub ip_or_key: Either<I, SmartString<LazyCompact>>,
} }
pub type PeerMap<I> = IndexMap<PeerMapKey<I>, Peer<I>>; pub type PeerMap<I> = AHashIndexMap<PeerMapKey<I>, Peer<I>>;
pub struct TorrentData<I: Ip> { pub struct TorrentData<I: Ip> {
pub peers: PeerMap<I>, pub peers: PeerMap<I>,
@ -153,14 +152,14 @@ impl<I: Ip> Default for TorrentData<I> {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
Self { Self {
peers: IndexMap::new(), peers: Default::default(),
num_seeders: 0, num_seeders: 0,
num_leechers: 0, num_leechers: 0,
} }
} }
} }
pub type TorrentMap<I> = HashMap<InfoHash, TorrentData<I>>; pub type TorrentMap<I> = AHashIndexMap<InfoHash, TorrentData<I>>;
#[derive(Default)] #[derive(Default)]
pub struct TorrentMaps { pub struct TorrentMaps {

View file

@ -26,9 +26,7 @@ aquatic_common = "0.1.0"
aquatic_udp_protocol = "0.1.0" aquatic_udp_protocol = "0.1.0"
cfg-if = "1" cfg-if = "1"
core_affinity = "0.5" core_affinity = "0.5"
hashbrown = "0.11.2"
hex = "0.4" hex = "0.4"
indexmap = "1"
log = "0.4" log = "0.4"
mimalloc = { version = "0.1", default-features = false } mimalloc = { version = "0.1", default-features = false }
parking_lot = "0.11" parking_lot = "0.11"

View file

@ -199,7 +199,6 @@ mod tests {
use std::collections::HashSet; use std::collections::HashSet;
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use indexmap::IndexMap;
use quickcheck::{quickcheck, TestResult}; use quickcheck::{quickcheck, TestResult};
use rand::thread_rng; use rand::thread_rng;
@ -229,7 +228,7 @@ mod tests {
let gen_num_peers = data.0 as u32; let gen_num_peers = data.0 as u32;
let req_num_peers = data.1 as usize; let req_num_peers = data.1 as usize;
let mut peer_map: PeerMap<Ipv4Addr> = IndexMap::with_capacity(gen_num_peers as usize); let mut peer_map: PeerMap<Ipv4Addr> = Default::default();
let mut opt_sender_key = None; let mut opt_sender_key = None;
let mut opt_sender_peer = None; let mut opt_sender_peer = None;

View file

@ -4,8 +4,7 @@ use std::sync::Arc;
use std::time::Instant; use std::time::Instant;
use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap}; use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap};
use hashbrown::HashMap; use aquatic_common::AHashIndexMap;
use indexmap::IndexMap;
pub use aquatic_common::{access_list::AccessList, ValidUntil}; pub use aquatic_common::{access_list::AccessList, ValidUntil};
pub use aquatic_udp_protocol::*; pub use aquatic_udp_protocol::*;
@ -80,7 +79,7 @@ pub struct PeerMapKey<I: Ip> {
pub peer_id: PeerId, pub peer_id: PeerId,
} }
pub type PeerMap<I> = IndexMap<PeerMapKey<I>, Peer<I>>; pub type PeerMap<I> = AHashIndexMap<PeerMapKey<I>, Peer<I>>;
pub struct TorrentData<I: Ip> { pub struct TorrentData<I: Ip> {
pub peers: PeerMap<I>, pub peers: PeerMap<I>,
@ -91,14 +90,14 @@ pub struct TorrentData<I: Ip> {
impl<I: Ip> Default for TorrentData<I> { impl<I: Ip> Default for TorrentData<I> {
fn default() -> Self { fn default() -> Self {
Self { Self {
peers: IndexMap::new(), peers: Default::default(),
num_seeders: 0, num_seeders: 0,
num_leechers: 0, num_leechers: 0,
} }
} }
} }
pub type TorrentMap<I> = HashMap<InfoHash, TorrentData<I>>; pub type TorrentMap<I> = AHashIndexMap<InfoHash, TorrentData<I>>;
#[derive(Default)] #[derive(Default)]
pub struct TorrentMaps { pub struct TorrentMaps {

View file

@ -1,11 +1,11 @@
use std::{net::SocketAddr, time::Instant}; use std::{net::SocketAddr, time::Instant};
use aquatic_common::AHashIndexMap;
pub use aquatic_common::{access_list::AccessList, ValidUntil}; pub use aquatic_common::{access_list::AccessList, ValidUntil};
pub use aquatic_udp_protocol::*; pub use aquatic_udp_protocol::*;
use hashbrown::HashMap;
#[derive(Default)] #[derive(Default)]
pub struct ConnectionMap(HashMap<(ConnectionId, SocketAddr), ValidUntil>); pub struct ConnectionMap(AHashIndexMap<(ConnectionId, SocketAddr), ValidUntil>);
impl ConnectionMap { impl ConnectionMap {
pub fn insert( pub fn insert(

View file

@ -10,6 +10,7 @@ use std::sync::{
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use aquatic_common::access_list::create_access_list_cache; use aquatic_common::access_list::create_access_list_cache;
use aquatic_common::AHashIndexMap;
use futures_lite::{Stream, StreamExt}; use futures_lite::{Stream, StreamExt};
use glommio::channels::channel_mesh::{MeshBuilder, Partial, Role, Senders}; use glommio::channels::channel_mesh::{MeshBuilder, Partial, Role, Senders};
use glommio::channels::local_channel::{new_unbounded, LocalSender}; use glommio::channels::local_channel::{new_unbounded, LocalSender};
@ -17,7 +18,6 @@ use glommio::enclose;
use glommio::net::UdpSocket; use glommio::net::UdpSocket;
use glommio::prelude::*; use glommio::prelude::*;
use glommio::timer::TimerActionRepeat; use glommio::timer::TimerActionRepeat;
use hashbrown::HashMap;
use rand::prelude::{Rng, SeedableRng, StdRng}; use rand::prelude::{Rng, SeedableRng, StdRng};
use aquatic_udp_protocol::{IpVersion, Request, Response}; use aquatic_udp_protocol::{IpVersion, Request, Response};
@ -38,7 +38,7 @@ struct PendingScrapeResponse {
} }
#[derive(Default)] #[derive(Default)]
struct PendingScrapeResponses(HashMap<TransactionId, PendingScrapeResponse>); struct PendingScrapeResponses(AHashIndexMap<TransactionId, PendingScrapeResponse>);
impl PendingScrapeResponses { impl PendingScrapeResponses {
fn prepare( fn prepare(
@ -266,8 +266,10 @@ async fn read_requests(
info_hashes, info_hashes,
})) => { })) => {
if connections.borrow().contains(connection_id, src) { if connections.borrow().contains(connection_id, src) {
let mut consumer_requests: HashMap<usize, (ScrapeRequest, Vec<usize>)> = let mut consumer_requests: AHashIndexMap<
HashMap::new(); usize,
(ScrapeRequest, Vec<usize>),
> = Default::default();
for (i, info_hash) in info_hashes.into_iter().enumerate() { for (i, info_hash) in info_hashes.into_iter().enumerate() {
let (req, indices) = consumer_requests let (req, indices) = consumer_requests

View file

@ -28,7 +28,6 @@ futures = "0.3"
futures-rustls = "0.22" futures-rustls = "0.22"
glommio = { git = "https://github.com/DataDog/glommio.git", rev = "4e6b14772da2f4325271fbcf12d24cf91ed466e5" } glommio = { git = "https://github.com/DataDog/glommio.git", rev = "4e6b14772da2f4325271fbcf12d24cf91ed466e5" }
hashbrown = { version = "0.11.2", features = ["serde"] } hashbrown = { version = "0.11.2", features = ["serde"] }
indexmap = "1"
log = "0.4" log = "0.4"
mimalloc = { version = "0.1", default-features = false } mimalloc = { version = "0.1", default-features = false }
privdrop = "0.5" privdrop = "0.5"

View file

@ -3,8 +3,7 @@ use std::sync::Arc;
use std::time::Instant; use std::time::Instant;
use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap, AccessListCache}; use aquatic_common::access_list::{create_access_list_cache, AccessListArcSwap, AccessListCache};
use hashbrown::HashMap; use aquatic_common::AHashIndexMap;
use indexmap::IndexMap;
pub use aquatic_common::ValidUntil; pub use aquatic_common::ValidUntil;
@ -66,7 +65,7 @@ pub struct Peer {
pub valid_until: ValidUntil, pub valid_until: ValidUntil,
} }
pub type PeerMap = IndexMap<PeerId, Peer>; pub type PeerMap = AHashIndexMap<PeerId, Peer>;
pub struct TorrentData { pub struct TorrentData {
pub peers: PeerMap, pub peers: PeerMap,
@ -78,14 +77,14 @@ impl Default for TorrentData {
#[inline] #[inline]
fn default() -> Self { fn default() -> Self {
Self { Self {
peers: IndexMap::new(), peers: Default::default(),
num_seeders: 0, num_seeders: 0,
num_leechers: 0, num_leechers: 0,
} }
} }
} }
pub type TorrentMap = HashMap<InfoHash, TorrentData>; pub type TorrentMap = AHashIndexMap<InfoHash, TorrentData>;
#[derive(Default)] #[derive(Default)]
pub struct TorrentMaps { pub struct TorrentMaps {