Skip to content

Commit bb4620a

Browse files
committed
feat: improve README
1 parent 4e77366 commit bb4620a

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
/target
2+
*/target/
3+
.DS_Store

README.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# FastQueue (fq)
2-
A fast and simple ring-buffer-based single-producer, single-consumer queue with no dependencies. You can use this to write Rust programs with low-latency message passing.
2+
A fast and simple ring-buffer-based single-producer, single-consumer queue with no dependencies. You can use
3+
this to write Rust programs with low-latency message passing.
34

45
> [!IMPORTANT]
56
> This crate is highly experimental.
@@ -33,15 +34,42 @@ sender.join().expect("The sender thread has panicked");
3334
receiver.join().expect("The receiver thread has panicked");
3435
```
3536

36-
## License
37+
## Examples
38+
See the [examples](examples) directory for more usage examples.
39+
40+
## How does it work?
41+
The ring buffer structure allows for a contigous data structure. The idea is that if we are able to get extreme
42+
cache locality, we can improve performance by reducing cache misses. This is also the reason why if you use
43+
smart pointers like `Box<T>`, performance *may* degrade since cache locality gets affected. For very large
44+
`T` types, you are more limited by `memcpy()` performance and less from queue implementations. As such,
45+
ring buffers can be considered strongly optimized for data of a few word sizes with some non-linear
46+
degradation for larger sizes. Additional optimizations are provided for CPUs that support `sse` and `prfchw`
47+
flags. As and when Rust `std` provides more relevant instructions, they will be added. This is simply a
48+
high-level explanation of some of the techniques employed by this crate, you can read the code to gain a better
49+
understanding of what's happening under the hood.
50+
51+
## Principles
52+
* This crate will always prioritize message throughput over memory usage.
53+
* This crate will always support generic types only.
54+
* This crate will always provide a wait-free **and** lock-free API.
55+
* This crate will use unsafe Rust where possible for maximal throughput.
56+
57+
## Benchmarks
58+
Benchmarks are strictly difficult due to the nature of the program, it's somewhat simple to do a same-CPU
59+
bench but performance will still be affected based on the core type and cache contention. Benchmarks are
60+
provided in the [benchmark](benchmark) directory and can be run with `cargo bench`. Contributions via PRs for
61+
additional benchmarks are welcome.
3762

63+
## License
3864
Licensed under either of:
3965
* MIT license ([LICENSE-MIT](LICENSE-MIT))
4066
* Lesser General Public license v3.0 or later ([LICENSE-LGPL](LICENSE-LGPL))
4167
at your option.
4268

4369
### Contribution
44-
4570
Unless you explicitly state otherwise, any contribution intentionally submitted
4671
for inclusion in the work by you, as defined in the LGPL-3.0 license, shall be dual licensed as above, without any
4772
additional terms or conditions.
73+
74+
## Acknowledgements
75+
Inspired from previous works like [fastqueue2](https://github.com/andersc/fastqueue2), [rigtorp](https://rigtorp.se/ringbuffer) and [rtrb](https://github.com/mgeier/rtrb).

benches/bench.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,8 @@ fn bench_concurrent_spsc_large_messages(c: &mut Criterion) {
126126
let mut group = c.benchmark_group("concurrent_spsc_large_messages");
127127

128128
struct LargeMessage {
129-
_val1: u128,
130-
_val2: String,
129+
_id: u128,
130+
_id_str: String,
131131
}
132132

133133
for messages in [500, 5000, 50000].iter() {
@@ -143,8 +143,8 @@ fn bench_concurrent_spsc_large_messages(c: &mut Criterion) {
143143
let producer_handle = thread::spawn(move || {
144144
for i in 0..messages {
145145
while black_box(producer.push(black_box(LargeMessage {
146-
_val1: i as u128,
147-
_val2: format!("Message {i}"),
146+
_id: i as u128,
147+
_id_str: format!("Message {i}"),
148148
})))
149149
.is_err()
150150
{

0 commit comments

Comments
 (0)