#byte-stream #async-read-async-write #async-io #async-write #speed #future #multiple

async-speed-limit

Asynchronously speed-limiting multiple byte streams

6 releases (3 breaking)

0.4.1 Aug 7, 2023
0.4.0 Sep 15, 2021
0.3.1 Dec 11, 2020
0.3.0 Feb 23, 2020
0.1.0 Jan 3, 2020

#102 in Asynchronous

Download history 553/week @ 2023-11-20 534/week @ 2023-11-27 627/week @ 2023-12-04 545/week @ 2023-12-11 766/week @ 2023-12-18 593/week @ 2023-12-25 716/week @ 2024-01-01 1182/week @ 2024-01-08 1193/week @ 2024-01-15 1001/week @ 2024-01-22 1043/week @ 2024-01-29 901/week @ 2024-02-05 812/week @ 2024-02-12 1117/week @ 2024-02-19 839/week @ 2024-02-26 757/week @ 2024-03-04

3,673 downloads per month
Used in 3 crates (via yocalhost)

MIT/Apache

67KB
1.5K SLoC

async-speed-limit

Build status Latest Version Documentation

Asynchronously speed-limiting multiple byte streams (AsyncRead and AsyncWrite).

Usage

use async_speed_limit::Limiter;
use futures_util::{
    future::try_join,
    io::{self, AsyncRead, AsyncWrite},
};
use std::{marker::Unpin, pin::Pin};

#[cfg(feature = "standard-clock")]
async fn copy_both_slowly(
    r1: impl AsyncRead,
    w1: &mut (impl AsyncWrite + Unpin),
    r2: impl AsyncRead,
    w2: &mut (impl AsyncWrite + Unpin),
) -> io::Result<()> {
    // create a speed limiter of 1.0 KiB/s.
    let limiter = <Limiter>::new(1024.0);

    // limit both readers by the same queue
    // (so 1.0 KiB/s is the combined maximum speed)
    let r1 = limiter.clone().limit(r1);
    let r2 = limiter.limit(r2);

    // do the copy.
    try_join(io::copy(r1, w1), io::copy(r2, w2)).await?;
    Ok(())
}

Algorithm

async-speed-limit imposes the maximum speed limit using the token bucket algorithm with a single queue. Transmission is throttled by adding a delay proportional to the consumed tokens after it is sent. Because of this, the traffic flow will have high burstiness around when the token bucket is full.

The time needed to refill the bucket from empty to full is called the refill period. Reducing the refill period also reduces burstiness, but there would be more sleeps. The default value (0.1 s) should be good enough for most situations.

Tokio 0.1

async-speed-limit is designed for "Futures 0.3". This package does not directly support Tokio 0.1, but you can use futures-util's compat module to bridge the types.

Cargo features

Name Dependency Effect
standard-clock (default) futures-timer Enables the clock::StandardClock struct.
fused-future (default) futures-core Implements FusedFuture on limiter::Consume.
futures-io (default) futures-io Implements AsyncRead and AsyncWrite on limiter::Resource.
read-initializer - Deprecated and does nothing. This feature has been removed since futures-io 0.3.19.

License

async-speed-limit is dual-licensed under

Dependencies

~0–1.2MB
~20K SLoC