@@ -5,7 +5,7 @@ A fast and simple ring-buffer-based single-producer, single-consumer queue with
55Add this to your `Cargo.toml`:
66```TOML
77[dependencies]
8- fq = "0.0.2 "
8+ fq = "0.0.3 "
99```
1010
1111## Quickstart
@@ -29,6 +29,22 @@ let receiver = thread::spawn(move || {
2929sender.join().expect("The sender thread has panicked");
3030receiver.join().expect("The receiver thread has panicked");
3131```
32+
33+ ## How does it work?
34+ The ring buffer structure allows for a contiguous data structure. The idea is that if we are able to get extreme
35+ cache locality, we can improve performance by reducing cache misses. This is also the reason why if you use
36+ smart pointers like `Box<T>`, performance *may* degrade since cache locality gets degraded. For very large
37+ `T` types, you are more limited by `memcpy()` performance and less from queue implementations. As such,
38+ ring buffers can be considered strongly optimized for data of a few word sizes with some non-linear performance
39+ degradation for larger sizes. Additional optimizations are provided for CPUs that support `sse` and `prfchw`
40+ instructions. As and when Rust `std` provides more relevant instructions, they will be added. This is simply a
41+ high-level explanation of some of the techniques employed by this crate, you can read the code to gain a better
42+ understanding of what's happening under the hood.
43+
44+ ## Profiles
45+ The crate is fully synchronous and runtime-agnostic. We are heavily reliant on `std` for memory management, so
46+ it's unlikely that we will support `#[no_std]` runtimes anytime soon. You should be using the `release` or
47+ `maxperf` profiles for optimal performance.
3248*/
3349use std:: alloc:: { Layout , alloc, dealloc, handle_alloc_error} ;
3450use std:: cell:: UnsafeCell ;
0 commit comments