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:
@@ -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