Skip to content

Commit 59c3d95

Browse files
committed
Optimize iterators and Arena::alloc logic
* Add remaining API * Optimize `Arena::alloc` logic * Implement `Iterator` trait for `MapIterator` and `SetIterator`
1 parent 092a922 commit 59c3d95

File tree

17 files changed

+800
-616
lines changed

17 files changed

+800
-616
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# CHANGELOG
22

3+
## 0.7.0
4+
5+
- Implement `Iterator` for `MapIterator` and `SetIterator`.
6+
- Optimize `Arena::alloc` logic.
7+
38
## 0.6.0
49

510
- Change mmap related API

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "skl"
3-
version = "0.6.0"
3+
version = "0.7.1"
44
edition = "2021"
55
rust-version = "1.56.0"
66
repository = "https://github.com/al8n/skl-rs"

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@
2828

2929
```toml
3030
[dependencies]
31-
skl = "0.6"
31+
skl = "0.7"
3232
```
3333

3434
- Enable memory map backend
3535

3636
```toml
3737
[dependencies]
38-
skl = { version = "0.6", features = ["memmap"] }
38+
skl = { version = "0.7", features = ["memmap"] }
3939
```
4040

4141
## Features

examples/mmap.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub fn new_value(i: usize) -> Vec<u8> {
1111
fn main() {
1212
const N: usize = 1000;
1313

14-
let l = Arc::new(SkipMap::mmap_mut(1 << 20, "test.wal", true).unwrap());
14+
let l = Arc::new(SkipMap::mmap_mut("test.wal", 1 << 20, true).unwrap());
1515
let wg = Arc::new(());
1616
for i in 0..N {
1717
let w = wg.clone();

integration/src/bin/test-mmap.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ fn main() {
77
let p = dir.path().join("test_mmap");
88
{
99
const N: usize = 10;
10-
let l = Arc::new(SkipMap::mmap_mut(1 << 20, &p, true).unwrap());
10+
let l = Arc::new(SkipMap::mmap_mut(&p, 1 << 20, true).unwrap());
1111
for i in 0..N {
1212
let l = l.clone();
1313
std::thread::spawn(move || {
@@ -29,7 +29,7 @@ fn main() {
2929

3030
{
3131
const N2: usize = 10;
32-
let l = Arc::new(SkipMap::mmap(&p, false).unwrap());
32+
let l = Arc::new(SkipMap::<u64>::mmap(&p, false).unwrap());
3333
assert_eq!(N2, l.len());
3434
for i in 0..N2 {
3535
let l = l.clone();

src/arena.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ impl Arena {
6969
pub const fn capacity(&self) -> usize {
7070
self.cap
7171
}
72+
73+
/// Returns the number of bytes remaining bytes can be allocated by the arena.
74+
#[inline]
75+
pub fn remaining(&self) -> usize {
76+
self.cap.saturating_sub(self.size())
77+
}
7278
}
7379

7480
impl Arena {
@@ -199,25 +205,27 @@ impl Arena {
199205
align: u32,
200206
overflow: u32,
201207
) -> Result<(u32, u32), ArenaError> {
202-
// Verify that the arena isn't already full.
203-
let orig_size = self.n.load(Ordering::Acquire);
204-
if orig_size > self.cap as u64 {
205-
return Err(ArenaError);
206-
}
207-
208208
// Pad the allocation with enough bytes to ensure the requested alignment.
209209
let padded = size as u64 + align as u64 - 1;
210210

211-
let new_size = self.n.fetch_add(padded, Ordering::AcqRel) + padded;
211+
let res = self
212+
.n
213+
.fetch_update(Ordering::Release, Ordering::Acquire, |orig| {
214+
if orig + padded + overflow as u64 > self.cap as u64 {
215+
return None;
216+
}
217+
Some(orig + padded)
218+
});
212219

213-
if new_size + overflow as u64 > self.cap as u64 {
214-
return Err(ArenaError);
220+
match res {
221+
Ok(new_size) => {
222+
// Return the aligned offset.
223+
let new_size = new_size + padded;
224+
let offset = (new_size as u32 - size) & !(align - 1);
225+
Ok((offset, padded as u32))
226+
}
227+
Err(_) => Err(ArenaError),
215228
}
216-
217-
// Return the aligned offset.
218-
let offset = (new_size as u32 - size) & !(align - 1);
219-
220-
Ok((offset, padded as u32))
221229
}
222230

223231
/// ## Safety:

src/lib.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,38 @@ pub mod map;
2626
pub mod set;
2727

2828
pub use arena::{Arena, ArenaError};
29-
pub use map::{MapIterator, MapRange, SkipMap};
30-
pub use set::{SetIterator, SetRange, SkipSet};
29+
pub use map::{MapIterator, SkipMap};
30+
pub use set::{SetIterator, SkipSet};
3131

3232
const MAX_HEIGHT: usize = 20;
3333
const NODE_ALIGNMENT_FACTOR: usize = mem::align_of::<u64>();
3434

35+
#[cfg(feature = "std")]
36+
fn random_height() -> u32 {
37+
use rand::{thread_rng, Rng};
38+
let mut rng = thread_rng();
39+
let rnd: u32 = rng.gen();
40+
let mut h = 1;
41+
42+
while h < MAX_HEIGHT && rnd <= PROBABILITIES[h] {
43+
h += 1;
44+
}
45+
h as u32
46+
}
47+
48+
#[cfg(not(feature = "std"))]
49+
fn random_height() -> u32 {
50+
use rand::{rngs::OsRng, Rng};
51+
52+
let rnd: u32 = OsRng.gen();
53+
let mut h = 1;
54+
55+
while h < MAX_HEIGHT && rnd <= PROBABILITIES[h] {
56+
h += 1;
57+
}
58+
h as u32
59+
}
60+
3561
/// Precompute the skiplist probabilities so that only a single random number
3662
/// needs to be generated and so that the optimal pvalue can be used (inverse
3763
/// of Euler's number).

0 commit comments

Comments
 (0)