Skip to content

Commit

Permalink
0.10.0
Browse files Browse the repository at this point in the history
- Remove `SkipSet`
- Add `insert`, `get_or_insert` and `get_or_insert_with` methods
- Add `compare_remove` and `get_or_remove` methods
- Add `Entry` and `VersionedEntry`
- Add discard states tracker and `discarded` method to let users know how many bytes in ARENA are discarded.
- Do not panic when users do not fully fill `VacantValue`
- Add `tracing`
  • Loading branch information
al8n committed May 20, 2024
1 parent a04556d commit 71b1585
Show file tree
Hide file tree
Showing 23 changed files with 2,829 additions and 4,817 deletions.
2 changes: 1 addition & 1 deletion .clippy.toml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
msrv = "1.56.0"
msrv = "1.75.0"
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# CHANGELOG

## 0.10.0

- Remove `SkipSet`
- Add `insert`, `get_or_insert` and `get_or_insert_with` methods
- Add `compare_remove` and `get_or_remove` methods
- Add `Entry` and `VersionedEntry`
- Add discard states tracker and `discarded` method to let users know how many bytes in ARENA are discarded.
- Do not panic when users do not fully fill `VacantValue`
- Add `tracing`

## 0.9.0

- Make file backed mmap `SkipMap` and `SkipSet` still can be reopened even last time the program was aborted.
Expand Down Expand Up @@ -57,4 +67,7 @@

## UNRELEASED

FEATURES
### 0.11.0

- Add `unaligned` feature, which does not apply pad for each allocation from ARENA.
- Add an ordered double end linked list to track holes.
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "skl"
version = "0.9.0"
version = "0.10.0"
edition = "2021"
rust-version = "1.56.0"
rust-version = "1.75.0"
repository = "https://github.com/al8n/skl-rs"
description = "A lock-free thread-safe concurrent ARENA based (heap backend or memory map backend) skiplist implementation which helps develop MVCC memtable for LSM-Tree."
documentation = "https://docs.rs/skl"
Expand Down Expand Up @@ -35,6 +35,7 @@ default = ["std"]
alloc = []
memmap = ["memmap2", "fs4", "std"]
std = ["rand/default", "either/default"]
tracing = ["dep:tracing"]

[target.'cfg(loom)'.dependencies]
loom = "0.7"
Expand All @@ -50,12 +51,15 @@ rand = { version = "0.8", default-features = false, features = ["getrandom"] }
fs4 = { version = "0.8", optional = true }
memmap2 = { version = "0.9", optional = true }

tracing = { version = "0.1", optional = true }

[dev-dependencies]
criterion = "0.5"
tempfile = "3"
parking_lot = "0.12"
paste = "1"
wg = { version = "0.9", default-features = false, features = ["std"] }
# tracing-subscriber = { version = "0.3", features = ["env-filter"] }

[profile.bench]
opt-level = 3
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
<img alt="wakatime" src="https://wakatime.com/badge/user/9203ce16-5227-4320-acdb-c8b6135e4730/project/9e07939d-5f12-4f23-bc46-5e1430137b9f.svg?style=for-the-badge&color=e5928d" height="22">
<img alt="license" src="https://img.shields.io/badge/License-Apache%202.0/MIT-blue.svg?style=for-the-badge&fontColor=white&logoColor=f5c076&logo=data:image/svg+xml;base64,PCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4KDTwhLS0gVXBsb2FkZWQgdG86IFNWRyBSZXBvLCB3d3cuc3ZncmVwby5jb20sIFRyYW5zZm9ybWVkIGJ5OiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4KPHN2ZyBmaWxsPSIjZmZmZmZmIiBoZWlnaHQ9IjgwMHB4IiB3aWR0aD0iODAwcHgiIHZlcnNpb249IjEuMSIgaWQ9IkNhcGFfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmlld0JveD0iMCAwIDI3Ni43MTUgMjc2LjcxNSIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgc3Ryb2tlPSIjZmZmZmZmIj4KDTxnIGlkPSJTVkdSZXBvX2JnQ2FycmllciIgc3Ryb2tlLXdpZHRoPSIwIi8+Cg08ZyBpZD0iU1ZHUmVwb190cmFjZXJDYXJyaWVyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KDTxnIGlkPSJTVkdSZXBvX2ljb25DYXJyaWVyIj4gPGc+IDxwYXRoIGQ9Ik0xMzguMzU3LDBDNjIuMDY2LDAsMCw2Mi4wNjYsMCwxMzguMzU3czYyLjA2NiwxMzguMzU3LDEzOC4zNTcsMTM4LjM1N3MxMzguMzU3LTYyLjA2NiwxMzguMzU3LTEzOC4zNTcgUzIxNC42NDgsMCwxMzguMzU3LDB6IE0xMzguMzU3LDI1OC43MTVDNzEuOTkyLDI1OC43MTUsMTgsMjA0LjcyMywxOCwxMzguMzU3UzcxLjk5MiwxOCwxMzguMzU3LDE4IHMxMjAuMzU3LDUzLjk5MiwxMjAuMzU3LDEyMC4zNTdTMjA0LjcyMywyNTguNzE1LDEzOC4zNTcsMjU4LjcxNXoiLz4gPHBhdGggZD0iTTE5NC43OTgsMTYwLjkwM2MtNC4xODgtMi42NzctOS43NTMtMS40NTQtMTIuNDMyLDIuNzMyYy04LjY5NCwxMy41OTMtMjMuNTAzLDIxLjcwOC0zOS42MTQsMjEuNzA4IGMtMjUuOTA4LDAtNDYuOTg1LTIxLjA3OC00Ni45ODUtNDYuOTg2czIxLjA3Ny00Ni45ODYsNDYuOTg1LTQ2Ljk4NmMxNS42MzMsMCwzMC4yLDcuNzQ3LDM4Ljk2OCwyMC43MjMgYzIuNzgyLDQuMTE3LDguMzc1LDUuMjAxLDEyLjQ5NiwyLjQxOGM0LjExOC0yLjc4Miw1LjIwMS04LjM3NywyLjQxOC0xMi40OTZjLTEyLjExOC0xNy45MzctMzIuMjYyLTI4LjY0NS01My44ODItMjguNjQ1IGMtMzUuODMzLDAtNjQuOTg1LDI5LjE1Mi02NC45ODUsNjQuOTg2czI5LjE1Miw2NC45ODYsNjQuOTg1LDY0Ljk4NmMyMi4yODEsMCw0Mi43NTktMTEuMjE4LDU0Ljc3OC0zMC4wMDkgQzIwMC4yMDgsMTY5LjE0NywxOTguOTg1LDE2My41ODIsMTk0Ljc5OCwxNjAuOTAzeiIvPiA8L2c+IDwvZz4KDTwvc3ZnPg==" height="22">

1. A lock-free thread-safe concurrent `SkipMap` and `SkipSet` implementation based on ARENA skiplist which helps develop MVCC memtable for LSM-Tree.
2. A lock-free thread-safe concurrent memory map based on-disk `SkipMap` and `SkipSet`.
1. A lock-free thread-safe concurrent `SkipMap` implementation based on ARENA skiplist which helps develop MVCC memtable for LSM-Tree.
2. A lock-free thread-safe concurrent memory map based on-disk `SkipMap`.

</div>

Expand All @@ -28,24 +28,24 @@

```toml
[dependencies]
skl = "0.9"
skl = "0.10"
```

- Enable memory map backend

```toml
[dependencies]
skl = { version = "0.9", features = ["memmap"] }
skl = { version = "0.10", features = ["memmap"] }
```

## Features

- **MVCC and 3D access**: Builtin MVCC (multiple versioning concurrency control) and key-value-version access support.
- **Lock-free and Concurrent-Safe:** SkipMap and SkipSet provide lock-free operations, ensuring efficient concurrent access without the need for explicit locking mechanisms.
- **Extensible for Key-Value Database Developers:** Designed as a low-level crate, SkipMap and SkipSet offer a flexible foundation for key-value database developers. You can easily build your own memtable or write-ahead-log (WAL) using these structures.
- **Lock-free and Concurrent-Safe:** SkipMap provide lock-free operations, ensuring efficient concurrent access without the need for explicit locking mechanisms.
- **Extensible for Key-Value Database Developers:** Designed as a low-level crate, SkipMap offer a flexible foundation for key-value database developers. You can easily build your own memtable or write-ahead-log (WAL) using these structures.
- **Memory Efficiency:** These data structures are optimized for minimal memory overhead. They operate around references, avoiding unnecessary allocations and deep copies, which can be crucial for efficient memory usage.
- **Efficient Iteration:** Enjoy fast forward and backward iteration through the elements in your SkipMap or SkipSet. Additionally, bounded iterators are supported, allowing you to traverse only a specified range of elements efficiently.
- **Snapshot Support:** Create snapshots of your SkipMap or SkipSet, offering a read-only view of the contents at a specific moment in time. Snapshots provide a consistent view of the data, enabling implementations of transactional semantics and other use cases where data consistency is crucial.
- **Efficient Iteration:** Enjoy fast forward and backward iteration through the elements in your SkipMap. Additionally, bounded iterators are supported, allowing you to traverse only a specified range of elements efficiently.
- **Snapshot Support:** Create snapshots of your SkipMap, offering a read-only view of the contents at a specific moment in time. Snapshots provide a consistent view of the data, enabling implementations of transactional semantics and other use cases where data consistency is crucial.
- **Memory Management Options:**
- **Heap Allocation:** Memory allocation is handled by Rust's allocator, ensuring all data resides in RAM.
- **Mmap:** Data can be mapped to a disk file by the operating system, making it suitable for write-ahead-logs (WAL) and durable storage.
Expand Down
65 changes: 65 additions & 0 deletions src/align8vp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use crate::sync::{AtomicU64, Ordering};

#[repr(C, align(8))]
pub(crate) struct Pointer(AtomicU64);

impl core::fmt::Debug for Pointer {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let (offset, len) = decode_value(self.0.load(Ordering::Relaxed));
f.debug_struct("Pointer")
.field("offset", &offset)
.field("len", &len)
.finish()
}
}

impl Pointer {
#[inline]
pub(crate) fn new(offset: u32, len: u32) -> Self {
Self(AtomicU64::new(encode_value(offset, len)))
}

#[inline]
pub(crate) fn remove(offset: u32) -> Self {
Self(AtomicU64::new(encode_value(offset, u32::MAX)))
}

#[cfg(not(feature = "unaligned"))]
#[inline]
pub(crate) fn load(&self, ordering: Ordering) -> (u32, u32) {
decode_value(self.0.load(ordering))
}

#[inline]
pub(crate) fn swap(&self, offset: u32, len: u32) -> (u32, u32) {
decode_value(self.0.swap(encode_value(offset, len), Ordering::AcqRel))
}

#[inline]
pub(crate) fn compare_remove(
&self,
success: Ordering,
failure: Ordering,
) -> Result<(u32, u32), (u32, u32)> {
let old = self.0.load(Ordering::Acquire);
let (offset, _) = decode_value(old);
let new = encode_value(offset, u32::MAX);
self
.0
.compare_exchange(old, new, success, failure)
.map(decode_value)
.map_err(decode_value)
}
}

#[inline]
const fn encode_value(offset: u32, val_size: u32) -> u64 {
(val_size as u64) << 32 | offset as u64
}

#[inline]
const fn decode_value(value: u64) -> (u32, u32) {
let offset = value as u32;
let val_size = (value >> 32) as u32;
(offset, val_size)
}
Loading

0 comments on commit 71b1585

Please sign in to comment.