slottle
This is a simple Rust library provide thread-based throttle pool. It can dynamic create multiple throttles by user given resource id.
For example, a web scraping tool may treat domain name as resource id to control access speed of each hosts in generic way. User can create multiple pools at the same time, each one have different configurations for different situations.
Example
use rayon::prelude::*;
use slottle::ThrottlePool;
use std::time::{Duration, Instant};
fn main() {
rayon::ThreadPoolBuilder::new()
.num_threads(8)
.build_global()
.unwrap();
let throttles: ThrottlePool<bool> = ThrottlePool::builder()
.interval(Duration::from_millis(10)) .concurrent(2) .build()
.unwrap();
let started_time = Instant::now();
let mut time_passed_ms_vec: Vec<f64> = vec![1, 2, 3, 4, 5, 6]
.into_par_iter()
.map(|x| {
throttles.run(
x >= 5, || {
let time_passed_ms = started_time.elapsed().as_secs_f64() * 1000.0;
println!(
"[throttle: {:>5}] allowed job {} started at: {:.2}ms",
x >= 5, x, time_passed_ms,
);
time_passed_ms
},
)
})
.collect();
time_passed_ms_vec.sort_by(|a, b| a.partial_cmp(b).unwrap());
let expected_time_passed_ms = [0.0, 0.0, 5.0, 5.0, 10.0, 15.0];
time_passed_ms_vec
.into_iter()
.zip(expected_time_passed_ms.iter())
.for_each(|(value, expected)| assert_eq_approx("time_passed (ms)", value, *expected, 1.0));
}
fn assert_eq_approx(name: &str, value: f64, expected: f64, espilon: f64) {
let expected_range = (expected - espilon)..(expected + espilon);
assert!(
expected_range.contains(&value),
"{}: {} out of accpetable range: {:?}",
name, value, expected_range,
);
}
Output:
[throttle: false] allowed job 1 to start at: 0.05ms
[throttle: true] allowed job 5 to start at: 0.06ms
[throttle: false] allowed job 2 to start at: 5.10ms
[throttle: true] allowed job 6 to start at: 5.12ms
[throttle: false] allowed job 3 to start at: 10.11ms
[throttle: false] allowed job 4 to start at: 15.11ms
Please check online documents for more detail.
License
MIT