Skip to content

Commit c07fb56

Browse files
Advise mmap to cleanup closed segments (#108)
* [Experiment] advise mmap to cleanup closed segments * Disable wal clear on non-linux machines * Don't panic if mmap clearing didn't work * Lock quickcheck dependency to 1.0.3 * Fix test --------- Co-authored-by: timvisee <tim@visee.me>
1 parent 2209eb2 commit c07fb56

File tree

3 files changed

+32
-7
lines changed

3 files changed

+32
-7
lines changed

src/lib.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ fn close_segment(mut segment: OpenSegment, start_index: u64) -> Result<ClosedSeg
572572
.path()
573573
.with_file_name(format!("closed-{start_index}"));
574574
segment.segment.rename(new_path)?;
575+
segment.segment.close();
575576
Ok(ClosedSegment {
576577
start_index,
577578
segment: segment.segment,
@@ -621,7 +622,10 @@ mod test {
621622
use crate::test_utils::EntryGenerator;
622623
use log::trace;
623624
use quickcheck::TestResult;
624-
use std::{io::Write, num::NonZeroUsize};
625+
use std::{
626+
io::Write,
627+
num::{NonZeroU8, NonZeroUsize},
628+
};
625629
use tempfile::Builder;
626630

627631
use super::{Wal, WalOptions};
@@ -960,8 +964,10 @@ mod test {
960964
#[test]
961965
fn check_prefix_truncate() {
962966
init_logger();
963-
fn prefix_truncate(entry_count: u8, until: u8, retain_closed: NonZeroUsize) -> TestResult {
964-
trace!("prefix truncate; entry_count: {entry_count}, until: {until}");
967+
fn prefix_truncate(entry_count: u8, until: u8, retain_closed: NonZeroU8) -> TestResult {
968+
trace!(
969+
"prefix truncate; entry_count: {entry_count}, until: {until}, retain_closed: {retain_closed}",
970+
);
965971
if until > entry_count {
966972
return TestResult::discard();
967973
}
@@ -971,7 +977,7 @@ mod test {
971977
&WalOptions {
972978
segment_capacity: 80,
973979
segment_queue_len: 3,
974-
retain_closed,
980+
retain_closed: NonZeroUsize::from(retain_closed),
975981
},
976982
)
977983
.unwrap();
@@ -980,7 +986,7 @@ mod test {
980986
.collect::<Vec<_>>();
981987

982988
let mut has_ever_reached_max = false;
983-
let retain_closed = retain_closed.get();
989+
let retain_closed = retain_closed.get() as usize;
984990

985991
for entry in &entries {
986992
wal.append(entry).unwrap();
@@ -993,7 +999,12 @@ mod test {
993999

9941000
let retained = if has_ever_reached_max {
9951001
// If it ever reaches max, it should stay there
996-
wal.closed_segments.len() == retain_closed
1002+
if until < entry_count {
1003+
// If `until` is (much) lower we might retain more to satisfy prefix_truncate
1004+
wal.closed_segments.len() >= retain_closed
1005+
} else {
1006+
wal.closed_segments.len() == retain_closed
1007+
}
9971008
} else {
9981009
wal.closed_segments.len() < retain_closed
9991010
};
@@ -1003,7 +1014,7 @@ mod test {
10031014
num_entries <= entry_count && num_entries >= entry_count - until && retained,
10041015
)
10051016
}
1006-
quickcheck::quickcheck(prefix_truncate as fn(u8, u8, NonZeroUsize) -> TestResult);
1017+
quickcheck::quickcheck(prefix_truncate as fn(u8, u8, NonZeroU8) -> TestResult);
10071018
}
10081019

10091020
#[test]

src/mmap_view_sync.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ pub struct MmapViewSync {
1919
}
2020

2121
impl MmapViewSync {
22+
pub fn close(&self) {
23+
#[cfg(target_os = "linux")]
24+
unsafe {
25+
let mmap = &mut *self.inner.get();
26+
if let Err(err) = mmap.unchecked_advise(memmap2::UncheckedAdvice::DontNeed) {
27+
log::warn!("Erorr clearing closed wal segment: {err:?}");
28+
}
29+
}
30+
}
31+
2232
pub fn from_file(file: &File, offset: usize, capacity: usize) -> Result<MmapViewSync> {
2333
let mmap = unsafe {
2434
MmapOptions::new()

src/segment.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ pub struct Segment {
111111
}
112112

113113
impl Segment {
114+
pub fn close(&self) {
115+
self.mmap.close()
116+
}
117+
114118
/// Creates a new segment.
115119
///
116120
/// The initial capacity must be at least 8 bytes.

0 commit comments

Comments
 (0)