feat(lib): cap the combined download speed
`Client::set_download_speed_limit(bytes_per_second)` puts one ceiling on every download at once. Zero lifts it and is the default. It can be changed at any time, and a change reaches transfers already running within one 100 ms tick. The limiter works the way Soulseek.NET's does, which slskd uses for its own download limit: one token bucket shared by all downloads, refilled to a tenth of a second's worth every 100 ms, handing out partial grants and taking back what a short read or a timeout did not use. A download is paced by reading less from the socket. The unread bytes stay in the kernel's receive buffer and TCP flow control slows the uploader; no protocol message is involved, as in Nicotine+ too. With no cap set, each read costs one atomic load. A same-hour stress run scored develop 88.98/88.98 and this branch 89.00/88.99/88.97, at about 133 MiB/s both. An upload ceiling is left out, as before.
This commit is contained in:
@@ -42,6 +42,7 @@ impl ClientContext {
|
||||
private_messages: Vec::new(),
|
||||
pending_connect_tokens: HashMap::new(),
|
||||
max_peers: Arc::new(AtomicUsize::new(DEFAULT_MAX_PEERS)),
|
||||
download_speed_limit: Arc::default(),
|
||||
shares: Arc::new(Shares::empty()),
|
||||
shared_directories: Vec::new(),
|
||||
peer_addresses: HashMap::new(),
|
||||
|
||||
@@ -14,6 +14,12 @@ impl Client {
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn set_download_speed_limit(&self, bytes_per_second: u64) {
|
||||
if let Ok(ctx) = self.context.read_safe() {
|
||||
ctx.download_speed_limit.set(bytes_per_second);
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn pause_download(&self, username: &str, filename: &str) -> bool {
|
||||
match self.context.write_safe() {
|
||||
|
||||
@@ -9,6 +9,7 @@ use crate::types::{
|
||||
SimilarUser, UserInfo, UserInterests, UserPresence, UserStats, UserStatus,
|
||||
};
|
||||
use crate::utils::logger;
|
||||
use crate::utils::rate_limit::RateLimit;
|
||||
use crate::{
|
||||
Transfer,
|
||||
actor::{ActorSystem, peer_registry::PeerRegistry},
|
||||
@@ -486,6 +487,7 @@ pub struct ClientContext {
|
||||
/// a token we sent in a ConnectToPeer to the peer we expect back.
|
||||
pending_connect_tokens: HashMap<u32, (String, Instant)>,
|
||||
max_peers: Arc<AtomicUsize>,
|
||||
pub(crate) download_speed_limit: Arc<RateLimit>,
|
||||
/// Files we share with peers (read-only after connect).
|
||||
pub shares: Arc<Shares>,
|
||||
/// The directories the current share index was built from.
|
||||
|
||||
Reference in New Issue
Block a user