UBQ
UBQ is a lock-free, unbounded, multi-producer/multi-consumer (MPMC) queue built from a linked ring of fixed-size blocks, intended for concurrent producers and consumers.
Features
- Lock-free —
pushandpopnever park the calling thread. - Unbounded — capacity grows automatically as new blocks are allocated.
- MPMC — any number of producers and consumers may operate concurrently.
- Arc-friendly sharing —
UBQ<T>is meant to be wrapped inArcfor shared, concurrent ownership across threads. - FIFO ordering — elements are returned in the order they were pushed, within each block.
Usage
Add UBQ to your Cargo.toml:
[]
= "5"
Basic example
use UBQ;
Multi-threaded (MPMC)
use UBQ;
use Arc;
use thread;
let q: = new;
// Spawn 4 producers and 4 consumers.
let m = 100_000;
let handles: =
.flat_map
.collect;
for h in handles
See the full API reference on docs.rs.
no_std + alloc
UBQ supports no_std targets that provide heap allocation and native 8-bit
and pointer-width atomics:
[]
= { = "5", = false }
The final application must install a global allocator. UBQ remains unbounded,
so a push may allocate a new aligned block; applications with a fixed memory
budget must enforce their own queue-depth limit. In no_std builds the built-in
backoff policies spin instead of yielding to an operating-system scheduler.
How it works
TODO
Benchmarks
This repo includes a benchmark harness that compares UBQ against established
MPMC queue implementations (segqueue, concurrent-queue, and optional
RBBQ/BBQ, lfqueue/LSCQ, and wCQ variants) in
1p1c, 4p1c, 1p4c, 4p4c, 8p1c, 8p4c, 8p8c, 1p8c, 4p8c,
16p1c, 1p16c, 8p16c, 16p8c, 16p16c, 32p1c, 1p32c, 16p32c,
32p16c, 32p32c, 64p1c, 1p64c, 32p64c, 64p32c, and 64p64c
scenarios.
The Rust benchmark harness and binaries are isolated behind the bench_tools
feature. Benchmark-specific features such as bench_registry, bench_rbbq,
bench_lfqueue, and bench_wcq enable it automatically.
The v2 harness has two layers:
bench_matrix: direct matrix execution. It dispatches through the precompiled benchmark registry and writes v2 JSON files underbench_results/runs.bench_frontier: higher-level frontier search. It inspects existing v2 runs, expands the UBQ search graph scenario-by-scenario, and submits missing work tobench_matrix. RBBQ/BBQ uses a fixed block-size grid rather than adaptive frontier expansion. A run isfrontier-completewhen no pending frontier bundles remain; the frontier expands around the best fully-covered UBQ label per scenario/metric, including the matchingpool=0no-pool variant, while propagating baseline-beating fully-covered winners across scenarios.
UBQ labels are 4-part identifiers:
preset,pool,block,backoff- Example:
balanced,8,127,crossbeam
Publication-backed baseline labels are emitted with their sizing knob:
- RBBQ/BBQ:
fastfifo_<block_size>, for examplefastfifo_256(default grid64,256,1024,4096). - LSCQ via
lfqueue:lfqueue_<segment_size>, for examplelfqueue_256(default grid32,256,1024). - wCQ:
wcq_<capacity>, for examplewcq_65536(default grid4096,65536,1048576). wCQ is bounded, so fill/drain samples are only scheduled when the selected capacity can hold the full pre-drain item set plus consumer sentinels.
The plotting scripts also emit queue_metadata.csv files that map queue labels
back to their implementation family and publication lineage, so paper-backed
baselines remain identifiable in aggregate plots.
For a presentation-oriented preview run and the full BSC-CNS paper run, see
docs/bsc_cns_presentation_runbook.md.
Run an explicit direct matrix:
For BBQ ATC 2022-style microbenchmarks, the scenario parser also accepts
spsc, mpsc:N-M, spmc:N-M, mpmc:N-M, bbq-atc22-x86-88t, and
bbq-atc22-oversub-x86-12t. The paper-style metric modes are
throughput, complex_throughput, data_latency, and fairness. See
docs/bbq_atc22_reproduction.md and
bench_fleet_bbq_atc22.toml for the ready-to-run suite.
The harness also includes synthetic application-level queue experiments. These are still controlled benchmarks, not full production workload models, but they exercise common application communication patterns. See docs/application_benchmarks.md for notes on how to interpret them:
app_log_fan_in: producers emit boxed log/event records into one shared queue while consumers hash and free them.app_pipeline: ingress threads feed a first queue, worker threads transform records into a second queue, and one collector drains completions.app_task_roundtrip: client threads submit one in-flight request at a time to worker threads and receive completions through a shared response queue.
Run the application-level suite:
Run the frontier search on one machine:
Run the configured fleet search:
full_bench_fleet now runs bench_frontier per machine, syncs
bench_results/runs, and refreshes plots under bench_results/plots.
--repeats overrides the defaults.repeats value from bench_fleet.toml.
Python is only needed for the plotting helpers.
Set up a minimal plotting environment:
Generate plots manually (PNG + CSV when matplotlib is installed, CSV-only otherwise):
# Optional: choose error bars from repeated samples (default: sem).
# Render plots from all JSON files under bench_results/runs recursively.
# Render PNGs from existing generated CSV machine folders and emit merged paper figures.
# Optional: cap how many configs appear in the per-machine scaling line chart.
Outputs are grouped by meta.machine_label and mode, e.g.:
bench_results/plots/local/throughput/1p1c_throughput.pngbench_results/plots/local/throughput/scenarios_line_throughput.pngbench_results/plots/local/throughput_push_elapsed/1p1c_push_elapsed.pngbench_results/plots/local/fill_drain_drain_elapsed/1p1c_drain_elapsed.pngbench_results/plots/lab/throughput/1p1c_throughput.pngbench_results/plots/hebrides/csv/throughput/1p1c_throughput.csvbench_results/plots/hebrides/csv/throughput/scenarios_line_throughput.csvbench_results/plots/hebrides/csv/throughput/queue_metadata.csvbench_results/plots/grace/throughput/mpsc_line_throughput.pngbench_results/plots/paper/mpsc_producer_throughput.pngbench_results/plots/paper/mpsc_push_elapsed_log.png
When records contain the newer timing fields, the plotter also emits derived
metric folders such as throughput_push_elapsed,
throughput_pop_elapsed, fill_drain_fill_elapsed, and
fill_drain_drain_elapsed. Timing, latency, and fairness-ratio charts sort
lower values first; throughput charts still sort higher values first.
Per-scenario UBQ outputs also emit a companion CSV named
<scenario>_immediate_variants_throughput.csv that marks each required
winner-adjacent variant, including the matching pool=0 no-pool comparison, as
present or missing.
The standalone benchmark target can be inspected with:
License
MIT