quota
A high-performance in-memory rate limiter for Rust, completely lock-free.
It uses a mix of Leaky Token Bucket & GCRA.
Scales with a compact 16 bytes to 29 bytes of memory per quota
- Quota size: 8 bytes (*)
- Last Access Time: 8 bytes (*)
- Last Refill Time: 8 bytes (Enabled by default for an efficient per-quota clock)
- Generation & Occupied: 5 bytes (Enabled by default for preventing dangling references from PoolQuota::quota())
The library uses SoA architecture, so the numbers above are accurate, no byte-alignment involved, which can make it efficient for SIMD processing in the future.
We provide 3 essential clean primitives: Quota, QuotaPolicy, and finally QuotaPool that combines both of them.
Example use of the simple Quota (A simple 8-byte number in memory):
use quota::Quota;
fn main() {
let quota = Quota::with_initial_tokens(10);
let mut results = vec![];
for _ in 0..100 {
results.push(quota.consume(1));
}
assert_eq!(results.iter().filter(|r| r.is_ok()).count(), 10);
assert_eq!(results.iter().filter(|r| r.is_err()).count(), 90);
}
Example use of applying QuotaPolicy with a maximum capacity and RefillRate:
use quota::{Quota, QuotaPolicy, RefillRate};
fn main() {
let policy = QuotaPolicy::new()
.set_capacity(10.0) .set_refill_rate(RefillRate::per_micro(100.0));
let mut quota = Quota::with_initial_tokens(10);
let mut results = vec![];
for _ in 0..100 {
policy.tick(1, &mut quota);
results.push(quota.consume(1));
}
assert_eq!(results.iter().filter(|r| r.is_ok()).count(), 19);
assert_eq!(results.iter().filter(|r| r.is_err()).count(), 81);
}
And now the main QuotaPool:
use quota::{RefillRate, QuotaPolicy, QuotaPool};
fn main() {
let policy = QuotaPolicy::new()
.set_capacity(10.0)
.set_refill_rate(RefillRate::per_sec(3));
let pool = QuotaPool::new(policy, 10);
let mut results = vec![];
for _ in 0..100 {
results.push(pool.consume("testing", 1));
}
}