-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from warlock-labs/0xalcibiades/spin
feat: flexible spin lock
- Loading branch information
Showing
6 changed files
with
531 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[package] | ||
name = "electrologica" | ||
version = "0.2.0" | ||
version = "0.3.0" | ||
edition = "2021" | ||
authors = ["0xAlcibiades <[email protected]"] | ||
homepage = "https://github.com/warlock-labs/electrologica" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,113 +1,204 @@ | ||
# Electrologica | ||
|
||
[![Crates.io](https://img.shields.io/crates/v/electrologica.svg)](https://crates.io/crates/electrologica) | ||
[![Documentation](https://docs.rs/electrologica/badge.svg)](https://docs.rs/electrologica) | ||
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) | ||
[![License](https://img.shields.io/crates/l/electrologica)](https://choosealicense.com/licenses/apache-2.0/) | ||
[![Crates.io](https://img.shields.io/crates/v/electrologica)](https://crates.io/crates/electrologica) | ||
[![Docs](https://img.shields.io/crates/v/electrologica?color=blue&label=docs)](https://docs.rs/electrologica/) | ||
[![Rust](https://github.com/warlock-labs/electrologica/workflows/Rust/badge.svg)](https://github.com/warlock-labs/electrologica/actions) | ||
[![codecov](https://codecov.io/gh/warlock-labs/electrologica/branch/main/graph/badge.svg?token=XXXXXXXXXX)](https://codecov.io/gh/warlock-labs/electrologica) | ||
|
||
Electrologica is a high-performance concurrent data structures crate for Rust, designed for scenarios where | ||
nanosecond-level latencies matter and contention in highly parallel systems is a concern. This library is | ||
EXPERIMENTAL and uses unsafe Rust, not recommended for production use. | ||
Electrologica is a high-performance, concurrent data structures library for Rust, optimized for nanosecond-level | ||
latencies and high-contention scenarios. It provides lock-free data structures and synchronization primitives designed | ||
to excel in environments where every nanosecond counts. Please note this crate is EXPERIMENTAL and not yet suitable for | ||
production use. | ||
|
||
## Features | ||
|
||
- **AtomicSemaphore**: An extremely low-latency semaphore optimized for high-contention scenarios, particularly useful | ||
in nested parallelism contexts. | ||
- **AtomicRingBuffer**: A lock-free, single-producer single-consumer (SPSC) ring buffer implementation that supports | ||
contiguous writes and reads for any type `T`, including non-Copy types. | ||
- Designed to manage congestion in parallel data structure updates. | ||
- Optimized for scenarios involving frequent updates to shared data structures. | ||
|
||
## Use Cases | ||
|
||
Electrologica is particularly well-suited for: | ||
|
||
- Nested parallelism scenarios where fine-grained concurrency control is needed | ||
- Systems requiring congestion control in highly parallel data structure updates | ||
- High-performance computing scenarios requiring efficient inter-thread communication | ||
- Network packet handling for efficient buffering of network data | ||
- **Lock-free data structures**: Efficiently manage concurrent access without traditional locks | ||
- **Atomic operations**: Carefully designed with precise memory ordering for optimal performance | ||
- **Nanosecond-level optimizations**: Tailored for ultra-low latency requirements | ||
- **Flexible spin-wait primitives**: Customizable synchronization tools for specific use cases | ||
- **Nested parallelism support**: Ideal for complex, multi-layered concurrent systems | ||
- **Congestion management**: Built-in mechanisms to handle high-contention scenarios effectively | ||
|
||
## Installation | ||
|
||
Add this to your `Cargo.toml`: | ||
Add Electrologica to your `Cargo.toml`: | ||
|
||
```toml | ||
[dependencies] | ||
electrologica = "0.1.0" | ||
electrologica = "0.3.0" | ||
``` | ||
|
||
## Usage | ||
|
||
### AtomicSemaphore | ||
|
||
The `AtomicSemaphore` provides a high-performance mechanism for controlling access to a limited number of resources: | ||
|
||
```rust | ||
use electrologica::AtomicSemaphore; | ||
|
||
let sem = AtomicSemaphore::new(5); | ||
|
||
// Acquire a permit | ||
if sem.acquire() { | ||
// Do some work | ||
// ... | ||
// Release the permit | ||
sem.release(); | ||
} | ||
|
||
// Use RAII guard | ||
if let Some(guard) = sem.acquire_guard() { | ||
// Do some work | ||
// Permit is automatically released when guard goes out of scope | ||
fn main() { | ||
let sem = AtomicSemaphore::new(5); | ||
assert!(sem.try_acquire()); | ||
assert_eq!(sem.available_permits(), 4); | ||
sem.release(); | ||
assert_eq!(sem.available_permits(), 5); | ||
} | ||
``` | ||
|
||
### AtomicRingBuffer | ||
|
||
The `AtomicRingBuffer` offers a lock-free, single-producer single-consumer queue for efficient inter-thread communication: | ||
|
||
```rust | ||
use electrologica::AtomicRingBuffer; | ||
|
||
let buffer: AtomicRingBuffer<String, 1024 > = AtomicRingBuffer::new(); | ||
fn main() { | ||
let buffer: AtomicRingBuffer<String, 4> = AtomicRingBuffer::new(); | ||
|
||
// Producer thread | ||
buffer.push(String::from("Hello")).unwrap(); | ||
buffer.push(String::from("World")).unwrap(); | ||
// Producer operations | ||
buffer.try_push(String::from("Hello")).unwrap(); | ||
buffer.try_push(String::from("World")).unwrap(); | ||
|
||
// Consumer thread | ||
assert_eq!(buffer.pop(), Some(String::from("Hello"))); | ||
assert_eq!(buffer.pop(), Some(String::from("World"))); | ||
assert_eq!(buffer.pop(), None); | ||
// Consumer operations | ||
assert_eq!(buffer.try_pop(), Some(String::from("Hello"))); | ||
assert_eq!(buffer.try_pop(), Some(String::from("World"))); | ||
assert_eq!(buffer.try_pop(), None); | ||
} | ||
``` | ||
|
||
### Spin Module | ||
|
||
The `spin` module provides configurable spin-wait primitives for custom synchronization needs: | ||
|
||
```rust | ||
use electrologica::spin::{spin_try, SpinConfig, SpinError}; | ||
use std::sync::Arc; | ||
use std::sync::atomic::{AtomicBool, Ordering}; | ||
use std::thread; | ||
use std::time::Duration; | ||
|
||
fn main() { | ||
let flag = Arc::new(AtomicBool::new(false)); | ||
let flag_clone = Arc::clone(&flag); | ||
|
||
thread::spawn(move || { | ||
thread::sleep(Duration::from_millis(10)); | ||
flag_clone.store(true, Ordering::SeqCst); | ||
}); | ||
|
||
let result = spin_try( | ||
|| { | ||
if flag.load(Ordering::SeqCst) { | ||
Some(true) | ||
} else { | ||
None | ||
} | ||
}, | ||
SpinConfig { | ||
spin_timeout: Duration::from_millis(100), | ||
..SpinConfig::default() | ||
} | ||
); | ||
|
||
assert!(result.is_ok()); | ||
assert_eq!(result.unwrap(), true); | ||
} | ||
``` | ||
|
||
## Architecture | ||
|
||
Electrologica is built around three core components: | ||
|
||
1. **AtomicSemaphore**: A high-performance semaphore implementation that uses atomic operations to manage concurrent | ||
access to shared resources efficiently. | ||
|
||
2. **AtomicRingBuffer**: A lock-free, single-producer single-consumer ring buffer that provides a fast and efficient way | ||
to pass data between threads without the need for mutexes or locks. | ||
|
||
3. **Spin Module**: A collection of configurable spin-wait primitives that allow for fine-tuned control over busy-wait | ||
loops, essential for scenarios where traditional blocking mechanisms are too slow. | ||
|
||
Each of these components is meticulously designed with careful attention to memory ordering and optimized for extremely | ||
low-latency scenarios. The library leverages Rust's powerful type system and ownership model to provide safe | ||
abstractions over low-level, high-performance concurrent programming primitives. | ||
|
||
## Performance | ||
|
||
The `AtomicSemaphore` is designed to provide extremely low latency in high-contention scenarios. It uses a combination | ||
of atomic operations and optimized spinning strategies to minimize overhead and maximize throughput. | ||
Electrologica is designed from the ground up for high performance in concurrent scenarios. Some key performance | ||
characteristics include: | ||
|
||
- Lock-free algorithms to minimize contention and avoid kernel-mode transitions | ||
- Careful use of atomic operations and memory ordering to ensure correctness with minimal overhead | ||
- Optimized data structures that minimize cache line bouncing and false sharing | ||
- Spin-wait primitives that can be fine-tuned for specific hardware and workload characteristics | ||
|
||
We are committed to continual performance improvements and welcome benchmarks and performance reports from the | ||
community. | ||
|
||
## Security | ||
|
||
While Electrologica strives for high performance, we take security seriously. However, please note: | ||
|
||
- This library uses unsafe Rust to achieve its performance goals. | ||
- It is not recommended for production use without thorough review and testing. | ||
- The library has not undergone a formal security audit. | ||
|
||
The `AtomicRingBuffer` is optimized for high-throughput, low-latency scenarios. It uses lock-free operations and a | ||
watermark mechanism for efficient wraparound handling, making it suitable for performance-critical applications. | ||
We encourage users to carefully evaluate the security implications of using Electrologica in their projects. If you | ||
discover any security-related issues, please report them responsibly by emailing [email protected] instead of using | ||
the public issue tracker. | ||
|
||
Benchmark results and comparisons with other synchronization primitives are available in the `benches/` directory. | ||
## API Documentation | ||
|
||
For detailed API documentation, please refer to the [API docs on docs.rs](https://docs.rs/electrologica/). | ||
|
||
## Minimum Supported Rust Version (MSRV) | ||
|
||
Electrologica's MSRV is `1.80`. We strive to maintain compatibility with stable Rust releases and will clearly | ||
communicate any changes to the MSRV in our release notes. | ||
|
||
## Contributing | ||
|
||
We welcome contributions to Electrologica! Please feel free to submit issues, fork the repository and send pull | ||
requests. | ||
We welcome contributions to Electrologica! Whether it's bug reports, feature requests, documentation improvements, or | ||
code contributions, your input is valued. | ||
|
||
To contribute: | ||
Before contributing, please: | ||
|
||
1. Fork the repository (https://github.com/warlock-labs/electrologica/fork) | ||
2. Create your feature branch (`git checkout -b my-new-feature`) | ||
3. Commit your changes (`git commit -am 'Add some feature'`) | ||
4. Push to the branch (`git push origin my-new-feature`) | ||
5. Create a new Pull Request | ||
1. Check the [issue tracker](https://github.com/warlock-labs/electrologica/issues) to see if your topic has already been | ||
discussed. | ||
2. Read our [Contributing Guide](CONTRIBUTING.md) for details on our development process, coding standards, and more. | ||
3. Review our [Code of Conduct](CODE_OF_CONDUCT.md) to understand our community standards. | ||
|
||
## License | ||
|
||
This project is licensed under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for details. | ||
Electrologica is licensed under the Apache License, Version 2.0. | ||
|
||
## Inspiration | ||
|
||
Electrologica draws its name and inspiration from the pioneering work of the Dutch company Electrologica, which produced | ||
the X1 computer in the 1950s. The X1, first delivered in 1958, was one of the first commercially successful | ||
transistorized computers in Europe. | ||
|
||
Key features of the X1 that inspire our work: | ||
|
||
- **Modularity**: The X1 was designed with a modular architecture, allowing for flexible configurations. | ||
- **Speed**: For its time, the X1 was remarkably fast, with a basic cycle time of 64 microseconds. | ||
- **Innovative Design**: It incorporated novel features like interrupt handling and a hardware floating point unit. | ||
|
||
Just as the original Electrologica pushed the boundaries of what was possible in computing during the 1950s, our | ||
Electrologica library aims to push the boundaries of concurrent programming in Rust. We strive to honor this legacy of | ||
innovation by: | ||
|
||
## Acknowledgments | ||
1. Prioritizing modularity and flexibility in our API design | ||
2. Continuously optimizing for speed and efficiency | ||
3. Incorporating cutting-edge techniques in concurrent programming | ||
|
||
Electrologica is inspired by the pioneering work in computer engineering by the Electrologica company, which produced | ||
the X1 computer in the 1950s. We aim to honor their legacy by pushing the boundaries of what's possible in modern, | ||
high-performance computing. | ||
While modern computing challenges are vastly different from those of the 1950s, we believe that the spirit of innovation | ||
and the pursuit of performance that drove the original Electrologica company are just as relevant today. Our library is | ||
a tribute to those early pioneers and a commitment to continuing their legacy of advancing the field of computing. | ||
|
||
The development of this library has been influenced by research in network congestion control algorithms, optimized | ||
graph traversal techniques, and lock-free data structures. | ||
As we develop and evolve Electrologica, we keep in mind the remarkable progress made in just a few decades - from | ||
computers that measured speed in microseconds to our current nanosecond-scale optimizations. It's a reminder of the | ||
rapid pace of technological advancement and the exciting possibilities that lie ahead in the field of high-performance | ||
computing. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
#![doc = include_str!("../README.md")] | ||
|
||
pub use ring::AtomicRingBuffer; | ||
pub use semaphore::{AtomicSemaphore, SemaphoreGuard}; | ||
|
||
mod ring; | ||
mod semaphore; | ||
mod spin; | ||
pub mod spin; |
Oops, something went wrong.