Skip to content

Commit

Permalink
Allow for arbitrary sized allocations (#730)
Browse files Browse the repository at this point in the history
  • Loading branch information
rkuris authored Oct 9, 2024
1 parent a308069 commit bd243b5
Showing 1 changed file with 73 additions and 35 deletions.
108 changes: 73 additions & 35 deletions storage/src/nodestore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,37 +66,68 @@ use super::linear::WritableStorage;

/// [NodeStore] divides the linear store into blocks of different sizes.
/// [AREA_SIZES] is every valid block size.
const AREA_SIZES: [u64; 21] = [
1 << MIN_AREA_SIZE_LOG, // Min block size is 8
1 << 4,
1 << 5,
1 << 6,
1 << 7,
1 << 8,
1 << 9,
1 << 10,
1 << 11,
1 << 12,
1 << 13,
1 << 14,
1 << 15,
1 << 16,
1 << 17,
1 << 18,
1 << 19,
1 << 20,
1 << 21,
1 << 22,
1 << 23, // 16 MiB
const AREA_SIZES: [u64; 23] = [
16, // Min block size
32,
64,
96,
128,
256,
512,
768,
1024,
1024 << 1,
1024 << 2,
1024 << 3,
1024 << 4,
1024 << 5,
1024 << 6,
1024 << 7,
1024 << 8,
1024 << 9,
1024 << 10,
1024 << 11,
1024 << 12,
1024 << 13,
1024 << 14,
];

// TODO: automate this, must stay in sync with above
fn index_name(index: AreaIndex) -> &'static str {
match index {
0 => "16",
1 => "32",
2 => "64",
3 => "96",
4 => "128",
5 => "256",
6 => "512",
7 => "768",
8 => "1024",
9 => "2048",
10 => "4096",
11 => "8192",
12 => "16384",
13 => "32768",
14 => "65536",
15 => "131072",
16 => "262144",
17 => "524288",
18 => "1048576",
19 => "2097152",
20 => "4194304",
21 => "8388608",
22 => "16777216",
_ => "unknown",
}
}

/// The type of an index into the [AREA_SIZES] array
/// This is not usize because we can store this as a single byte
pub type AreaIndex = u8;

// TODO danlaine: have type for index in AREA_SIZES
// Implement try_into() for it.
const MIN_AREA_SIZE_LOG: AreaIndex = 3;
const NUM_AREA_SIZES: usize = AREA_SIZES.len();
const MIN_AREA_SIZE: u64 = AREA_SIZES[0];
const MAX_AREA_SIZE: u64 = AREA_SIZES[NUM_AREA_SIZES - 1];
Expand All @@ -114,13 +145,16 @@ fn area_size_to_index(n: u64) -> Result<AreaIndex, Error> {
return Ok(0);
}

let mut log = n.ilog2();
// If n is not a power of 2, we need to round up to the next power of 2.
if n != 1 << log {
log += 1;
}

Ok(log as AreaIndex - MIN_AREA_SIZE_LOG)
AREA_SIZES
.iter()
.position(|&size| size >= n)
.map(|index| index as AreaIndex)
.ok_or_else(|| {
Error::new(
ErrorKind::InvalidData,
format!("Node size {} is too large", n),
)
})
}

/// Objects cannot be stored at the zero address, so a [LinearAddress] is guaranteed not
Expand Down Expand Up @@ -413,8 +447,10 @@ impl<S: ReadableStorage> NodeStore<Arc<ImmutableProposal>, S> {
*free_stored_area_addr = free_head.next_free_block;
}

counter!("firewood.space.reused").increment(AREA_SIZES[index]);
counter!("firewood.space.wasted").increment(AREA_SIZES[index] - n);
counter!("firewood.space.reused", "index" => index_name(index as u8))
.increment(AREA_SIZES[index]);
counter!("firewood.space.wasted", "index" => index_name(index as u8))
.increment(AREA_SIZES[index] - n);

// Return the address of the newly allocated block.
trace!(
Expand All @@ -425,7 +461,8 @@ impl<S: ReadableStorage> NodeStore<Arc<ImmutableProposal>, S> {
}

trace!("No free blocks of sufficient size {index_wanted} found");
counter!("firewood.space.notfree").increment(AREA_SIZES[index_wanted as usize]);
counter!("firewood.space.from_end", "index" => index_name(index_wanted as u8))
.increment(AREA_SIZES[index_wanted as usize]);
Ok(None)
}

Expand Down Expand Up @@ -474,8 +511,9 @@ impl<S: WritableStorage> NodeStore<Committed, S> {

let (area_size_index, _) = self.area_index_and_size(addr)?;
trace!("Deleting node at {addr:?} of size {}", area_size_index);
counter!("firewood.delete_node").increment(1);
counter!("firewood.space.freed").increment(AREA_SIZES[area_size_index as usize]);
counter!("firewood.delete_node", "index" => index_name(area_size_index)).increment(1);
counter!("firewood.space.freed", "index" => index_name(area_size_index))
.increment(AREA_SIZES[area_size_index as usize]);

// The area that contained the node is now free.
let area: Area<Node, FreeArea> = Area::Free(FreeArea {
Expand Down

0 comments on commit bd243b5

Please sign in to comment.