implement general allocator

This commit is contained in:
soruh 2023-07-28 01:49:39 +02:00
parent 2d9791db30
commit 1525b3f466
2 changed files with 38 additions and 3 deletions

View File

@ -18,6 +18,9 @@ impl SlabKind {
} else if size < size_of::<FilePointer>() as u32 {
Self::RelativeFreeList
} else if (size as u64) <= PAGE_SIZE {
// TODO
// slabs of really big object are very inefficient.
// find a better way/ allocate more pages at once e.g. at least 10 elements?
Self::AbsoluteFreeList
} else {
panic!("invalid size")
@ -469,6 +472,10 @@ impl SlabPointer {
unsafe { db.modify(self.0) }
}
pub fn size(&self, db: &Db) -> u32 {
self.read(db).size.get()
}
pub fn alloc(&self, db: &mut Db) -> FileRange {
let Slab { mut head, size } = self.read(db);

View File

@ -1,5 +1,10 @@
use std::{
borrow::BorrowMut, collections::HashMap, fmt::Debug, fs::File, mem::size_of, ops::Range,
borrow::BorrowMut,
collections::{BTreeMap, HashMap},
fmt::Debug,
fs::File,
mem::size_of,
ops::Range,
sync::Arc,
};
@ -153,6 +158,7 @@ pub struct Reader {
pub struct Db {
file: File,
map: MmapMut,
slabs: BTreeMap<u32, SlabPointer>,
state: Arc<AtomicArc<Snapshot>>,
}
@ -241,9 +247,18 @@ impl Db {
unsafe { self.modify_range_unchecked(Self::header_ptr().range(size_of::<Header>() as u64)) }
}
pub fn add_slab(&mut self, size: u32) -> SlabPointer {
fn add_slab(&mut self, size: u32) -> SlabPointer {
let allocator_state = self.header().allocator_state;
allocator_state.slabs.add_slab(self, size)
let slab = allocator_state.slabs.add_slab(self, size);
assert!(self.slabs.insert(size, slab).is_none());
slab
}
pub fn ensure_slab(&mut self, size: u32) -> SlabPointer {
self.slabs
.get(&size)
.copied()
.unwrap_or_else(|| self.add_slab(size))
}
fn transaction(f: impl FnOnce(TransactionHandle)) {
@ -392,8 +407,20 @@ impl Db {
}))),
file,
map,
slabs: BTreeMap::new(),
};
let allocator_state = db.header().allocator_state;
let mut slabs = BTreeMap::new();
for slab in allocator_state.slabs.iter(&db) {
let size = slab.size(&db);
slabs.insert(size, slab);
}
db.slabs = slabs;
unsafe {
if len == 0 {
*db.header_mut() = Header::default();
@ -616,6 +643,7 @@ mod tests {
// alloc_and_free_many::<1>(&mut db, 3 * PAGE_SIZE);
alloc_and_free_many::<4>(&mut db, PAGE_SIZE / 4 * 3);
alloc_and_free_many::<4>(&mut db, PAGE_SIZE / 4 * 3);
alloc_and_free_many::<16>(&mut db, PAGE_SIZE / 16 * 3);
let mut child = std::process::Command::new("hexdump")