Skip to content

Commit 6271ce8

Browse files
committed
Merge #800: Torrent repository with parking_lot crate locks
0058e72 feat: new torrent repo implementation using parking_lot Mutex (Jose Celano) 0fa396c chore(deps): add parking_lot to cargo machete (Jose Celano) 9258ac0 feat: new torrent repo implementation using parking_lot RwLock (Jose Celano) 5750e2c chore(deps): add dependency parking_lot (Jose Celano) Pull request description: Relates to: #774 A new torrent repository implementation with a different lock implementation for the torrent entry. The crate is: [parking_lot](https://github.com/Amanieu/parking_lot) It's supposed to be faster than the standard implementation of `Mutex` and `RwLock`. This PR adds two implementations with `Mutex` and `RwLock`. ### Subtasks - [x] With `parking_lot::RwLock` - [x] With `parking_lot::Mutex` ### Performance With `parking_lot::RwLock`: ```output Requests out: 420183.87/second Responses in: 356799.49/second - Connect responses: 176636.38 - Announce responses: 176603.09 - Scrape responses: 3560.02 - Error responses: 0.00 Peers per announce response: 0.00 Announce responses per info hash: - p10: 1 - p25: 1 - p50: 1 - p75: 1 - p90: 2 - p95: 3 - p99: 104 - p99.9: 287 - p100: 359 ``` With `parking_lot::RwLock::Mutex` ```output Requests out: 405157.91/second Responses in: 363773.19/second - Connect responses: 180009.24 - Announce responses: 180202.03 - Scrape responses: 3561.92 - Error responses: 0.00 Peers per announce response: 0.00 Announce responses per info hash: - p10: 1 - p25: 1 - p50: 1 - p75: 1 - p90: 2 - p95: 3 - p99: 105 - p99.9: 293 - p100: 367 ``` With current implementation (SkipMap and Std Mutex): ```output Requests out: 415067.21/second Responses in: 369397.08/second - Connect responses: 183049.81 - Announce responses: 182717.15 - Scrape responses: 3630.12 - Error responses: 0.00 Peers per announce response: 0.00 Announce responses per info hash: - p10: 1 - p25: 1 - p50: 1 - p75: 1 - p90: 2 - p95: 3 - p99: 104 - p99.9: 297 - p100: 375 ``` ![image](https://github.com/torrust/torrust-tracker/assets/58816/f3615cce-4a86-4d12-8ca8-eaf7d609f49e) ![image](https://github.com/torrust/torrust-tracker/assets/58816/1c7d8b5e-3b3c-4d3c-a8d9-b0d0bbb14976) ### Conclusion Performance looks similar (the current version is slightly better), so I would keep the current version with the standard Mutex. ACKs for top commit: josecelano: ACK 0058e72 Tree-SHA512: 17a906efe39cf3365a0ea2db20f408595acb3ac8e467d8774d4c67afeec107e19889e9e2255cd6296d1f0df2b10a918644b4bc36a38fd9fa5cac9a10beab99c1
2 parents 7664ec6 + 0058e72 commit 6271ce8

File tree

13 files changed

+456
-30
lines changed

13 files changed

+456
-30
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ hyper = "1"
5151
lazy_static = "1"
5252
log = { version = "0", features = ["release_max_level_info"] }
5353
multimap = "0"
54+
parking_lot = "0.12.1"
5455
percent-encoding = "2"
5556
r2d2 = "0"
5657
r2d2_mysql = "24"
@@ -78,7 +79,7 @@ url = "2"
7879
uuid = { version = "1", features = ["v4"] }
7980

8081
[package.metadata.cargo-machete]
81-
ignored = ["serde_bytes", "crossbeam-skiplist", "dashmap"]
82+
ignored = ["serde_bytes", "crossbeam-skiplist", "dashmap", "parking_lot"]
8283

8384
[dev-dependencies]
8485
local-ip-address = "0"

packages/torrent-repository/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ version.workspace = true
1919
crossbeam-skiplist = "0.1"
2020
dashmap = "5.5.3"
2121
futures = "0.3.29"
22+
parking_lot = "0.12.1"
2223
tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "signal", "sync"] }
2324
torrust-tracker-clock = { version = "3.0.0-alpha.12-develop", path = "../clock" }
2425
torrust-tracker-configuration = { version = "3.0.0-alpha.12-develop", path = "../configuration" }

packages/torrent-repository/benches/repository_benchmark.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ mod helpers;
55
use criterion::{criterion_group, criterion_main, Criterion};
66
use torrust_tracker_torrent_repository::{
77
TorrentsDashMapMutexStd, TorrentsRwLockStd, TorrentsRwLockStdMutexStd, TorrentsRwLockStdMutexTokio, TorrentsRwLockTokio,
8-
TorrentsRwLockTokioMutexStd, TorrentsRwLockTokioMutexTokio, TorrentsSkipMapMutexStd,
8+
TorrentsRwLockTokioMutexStd, TorrentsRwLockTokioMutexTokio, TorrentsSkipMapMutexParkingLot, TorrentsSkipMapMutexStd,
9+
TorrentsSkipMapRwLockParkingLot,
910
};
1011

1112
use crate::helpers::{asyn, sync};
@@ -49,6 +50,14 @@ fn add_one_torrent(c: &mut Criterion) {
4950
b.iter_custom(sync::add_one_torrent::<TorrentsSkipMapMutexStd, _>);
5051
});
5152

53+
group.bench_function("SkipMapMutexParkingLot", |b| {
54+
b.iter_custom(sync::add_one_torrent::<TorrentsSkipMapMutexParkingLot, _>);
55+
});
56+
57+
group.bench_function("SkipMapRwLockParkingLot", |b| {
58+
b.iter_custom(sync::add_one_torrent::<TorrentsSkipMapRwLockParkingLot, _>);
59+
});
60+
5261
group.bench_function("DashMapMutexStd", |b| {
5362
b.iter_custom(sync::add_one_torrent::<TorrentsDashMapMutexStd, _>);
5463
});
@@ -102,6 +111,16 @@ fn add_multiple_torrents_in_parallel(c: &mut Criterion) {
102111
.iter_custom(|iters| sync::add_multiple_torrents_in_parallel::<TorrentsSkipMapMutexStd, _>(&rt, iters, None));
103112
});
104113

114+
group.bench_function("SkipMapMutexParkingLot", |b| {
115+
b.to_async(&rt)
116+
.iter_custom(|iters| sync::add_multiple_torrents_in_parallel::<TorrentsSkipMapMutexParkingLot, _>(&rt, iters, None));
117+
});
118+
119+
group.bench_function("SkipMapRwLockParkingLot", |b| {
120+
b.to_async(&rt)
121+
.iter_custom(|iters| sync::add_multiple_torrents_in_parallel::<TorrentsSkipMapRwLockParkingLot, _>(&rt, iters, None));
122+
});
123+
105124
group.bench_function("DashMapMutexStd", |b| {
106125
b.to_async(&rt)
107126
.iter_custom(|iters| sync::add_multiple_torrents_in_parallel::<TorrentsDashMapMutexStd, _>(&rt, iters, None));
@@ -156,6 +175,16 @@ fn update_one_torrent_in_parallel(c: &mut Criterion) {
156175
.iter_custom(|iters| sync::update_one_torrent_in_parallel::<TorrentsSkipMapMutexStd, _>(&rt, iters, None));
157176
});
158177

178+
group.bench_function("SkipMapMutexParkingLot", |b| {
179+
b.to_async(&rt)
180+
.iter_custom(|iters| sync::update_one_torrent_in_parallel::<TorrentsSkipMapMutexParkingLot, _>(&rt, iters, None));
181+
});
182+
183+
group.bench_function("SkipMapRwLockParkingLot", |b| {
184+
b.to_async(&rt)
185+
.iter_custom(|iters| sync::update_one_torrent_in_parallel::<TorrentsSkipMapRwLockParkingLot, _>(&rt, iters, None));
186+
});
187+
159188
group.bench_function("DashMapMutexStd", |b| {
160189
b.to_async(&rt)
161190
.iter_custom(|iters| sync::update_one_torrent_in_parallel::<TorrentsDashMapMutexStd, _>(&rt, iters, None));
@@ -211,6 +240,18 @@ fn update_multiple_torrents_in_parallel(c: &mut Criterion) {
211240
.iter_custom(|iters| sync::update_multiple_torrents_in_parallel::<TorrentsSkipMapMutexStd, _>(&rt, iters, None));
212241
});
213242

243+
group.bench_function("SkipMapMutexParkingLot", |b| {
244+
b.to_async(&rt).iter_custom(|iters| {
245+
sync::update_multiple_torrents_in_parallel::<TorrentsSkipMapMutexParkingLot, _>(&rt, iters, None)
246+
});
247+
});
248+
249+
group.bench_function("SkipMapRwLockParkingLot", |b| {
250+
b.to_async(&rt).iter_custom(|iters| {
251+
sync::update_multiple_torrents_in_parallel::<TorrentsSkipMapRwLockParkingLot, _>(&rt, iters, None)
252+
});
253+
});
254+
214255
group.bench_function("DashMapMutexStd", |b| {
215256
b.to_async(&rt)
216257
.iter_custom(|iters| sync::update_multiple_torrents_in_parallel::<TorrentsDashMapMutexStd, _>(&rt, iters, None));

packages/torrent-repository/src/entry/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch};
88

99
use self::peer_list::PeerList;
1010

11+
pub mod mutex_parking_lot;
1112
pub mod mutex_std;
1213
pub mod mutex_tokio;
1314
pub mod peer_list;
15+
pub mod rw_lock_parking_lot;
1416
pub mod single;
1517

1618
pub trait Entry {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use std::net::SocketAddr;
2+
use std::sync::Arc;
3+
4+
use torrust_tracker_configuration::TrackerPolicy;
5+
use torrust_tracker_primitives::swarm_metadata::SwarmMetadata;
6+
use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch};
7+
8+
use super::{Entry, EntrySync};
9+
use crate::{EntryMutexParkingLot, EntrySingle};
10+
11+
impl EntrySync for EntryMutexParkingLot {
12+
fn get_swarm_metadata(&self) -> SwarmMetadata {
13+
self.lock().get_swarm_metadata()
14+
}
15+
16+
fn is_good(&self, policy: &TrackerPolicy) -> bool {
17+
self.lock().is_good(policy)
18+
}
19+
20+
fn peers_is_empty(&self) -> bool {
21+
self.lock().peers_is_empty()
22+
}
23+
24+
fn get_peers_len(&self) -> usize {
25+
self.lock().get_peers_len()
26+
}
27+
28+
fn get_peers(&self, limit: Option<usize>) -> Vec<Arc<peer::Peer>> {
29+
self.lock().get_peers(limit)
30+
}
31+
32+
fn get_peers_for_client(&self, client: &SocketAddr, limit: Option<usize>) -> Vec<Arc<peer::Peer>> {
33+
self.lock().get_peers_for_client(client, limit)
34+
}
35+
36+
fn upsert_peer(&self, peer: &peer::Peer) -> bool {
37+
self.lock().upsert_peer(peer)
38+
}
39+
40+
fn remove_inactive_peers(&self, current_cutoff: DurationSinceUnixEpoch) {
41+
self.lock().remove_inactive_peers(current_cutoff);
42+
}
43+
}
44+
45+
impl From<EntrySingle> for EntryMutexParkingLot {
46+
fn from(entry: EntrySingle) -> Self {
47+
Arc::new(parking_lot::Mutex::new(entry))
48+
}
49+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use std::net::SocketAddr;
2+
use std::sync::Arc;
3+
4+
use torrust_tracker_configuration::TrackerPolicy;
5+
use torrust_tracker_primitives::swarm_metadata::SwarmMetadata;
6+
use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch};
7+
8+
use super::{Entry, EntrySync};
9+
use crate::{EntryRwLockParkingLot, EntrySingle};
10+
11+
impl EntrySync for EntryRwLockParkingLot {
12+
fn get_swarm_metadata(&self) -> SwarmMetadata {
13+
self.read().get_swarm_metadata()
14+
}
15+
16+
fn is_good(&self, policy: &TrackerPolicy) -> bool {
17+
self.read().is_good(policy)
18+
}
19+
20+
fn peers_is_empty(&self) -> bool {
21+
self.read().peers_is_empty()
22+
}
23+
24+
fn get_peers_len(&self) -> usize {
25+
self.read().get_peers_len()
26+
}
27+
28+
fn get_peers(&self, limit: Option<usize>) -> Vec<Arc<peer::Peer>> {
29+
self.read().get_peers(limit)
30+
}
31+
32+
fn get_peers_for_client(&self, client: &SocketAddr, limit: Option<usize>) -> Vec<Arc<peer::Peer>> {
33+
self.read().get_peers_for_client(client, limit)
34+
}
35+
36+
fn upsert_peer(&self, peer: &peer::Peer) -> bool {
37+
self.write().upsert_peer(peer)
38+
}
39+
40+
fn remove_inactive_peers(&self, current_cutoff: DurationSinceUnixEpoch) {
41+
self.write().remove_inactive_peers(current_cutoff);
42+
}
43+
}
44+
45+
impl From<EntrySingle> for EntryRwLockParkingLot {
46+
fn from(entry: EntrySingle) -> Self {
47+
Arc::new(parking_lot::RwLock::new(entry))
48+
}
49+
}

packages/torrent-repository/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ use torrust_tracker_clock::clock;
99
pub mod entry;
1010
pub mod repository;
1111

12+
// Repo Entries
13+
1214
pub type EntrySingle = entry::Torrent;
1315
pub type EntryMutexStd = Arc<std::sync::Mutex<entry::Torrent>>;
1416
pub type EntryMutexTokio = Arc<tokio::sync::Mutex<entry::Torrent>>;
17+
pub type EntryMutexParkingLot = Arc<parking_lot::Mutex<entry::Torrent>>;
18+
pub type EntryRwLockParkingLot = Arc<parking_lot::RwLock<entry::Torrent>>;
19+
20+
// Repos
1521

1622
pub type TorrentsRwLockStd = RwLockStd<EntrySingle>;
1723
pub type TorrentsRwLockStdMutexStd = RwLockStd<EntryMutexStd>;
@@ -21,6 +27,9 @@ pub type TorrentsRwLockTokioMutexStd = RwLockTokio<EntryMutexStd>;
2127
pub type TorrentsRwLockTokioMutexTokio = RwLockTokio<EntryMutexTokio>;
2228

2329
pub type TorrentsSkipMapMutexStd = CrossbeamSkipList<EntryMutexStd>;
30+
pub type TorrentsSkipMapMutexParkingLot = CrossbeamSkipList<EntryMutexParkingLot>;
31+
pub type TorrentsSkipMapRwLockParkingLot = CrossbeamSkipList<EntryRwLockParkingLot>;
32+
2433
pub type TorrentsDashMapMutexStd = XacrimonDashMap<EntryMutexStd>;
2534

2635
/// This code needs to be copied into each crate.

0 commit comments

Comments
 (0)