Skip to content

Commit

Permalink
removed allocation tries, instead count cycles
Browse files Browse the repository at this point in the history
Different allocators have different or even no notion of a try. So
instead remove tries completely and introduce an allocator agnostic
metric to measure how long an allocation takes.
  • Loading branch information
pzittlau committed Dec 18, 2024
1 parent e864db1 commit ff6bfb4
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 75 deletions.
22 changes: 1 addition & 21 deletions betree/src/allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ pub struct SegmentAllocator {
data: BitArr!(for SEGMENT_SIZE, in u8, Lsb0),
}

#[cfg(not(feature = "allocation_log"))]
type AllocateReturnType = Option<u32>;
#[cfg(feature = "allocation_log")]
type AllocateReturnType = (Option<u32>, u32);

impl SegmentAllocator {
/// Constructs a new `SegmentAllocator` given the segment allocation bitmap.
/// The `bitmap` must have a length of `SEGMENT_SIZE`.
Expand All @@ -34,28 +29,16 @@ impl SegmentAllocator {

/// Allocates a block of the given `size`.
/// Returns `None` if the allocation request cannot be satisfied.
pub fn allocate(&mut self, size: u32) -> AllocateReturnType {
pub fn allocate(&mut self, size: u32) -> Option<u32> {
if size == 0 {
#[cfg(not(feature = "allocation_log"))]
return Some(0);
#[cfg(feature = "allocation_log")]
return (Some(0), 0);
}
#[cfg(feature = "allocation_log")]
let mut tries = 0;
let offset = {
let mut idx = 0;
loop {
#[cfg(feature = "allocation_log")]
{
tries += 1;
}
loop {
if idx + size > SEGMENT_SIZE as u32 {
#[cfg(not(feature = "allocation_log"))]
return None;
#[cfg(feature = "allocation_log")]
return (None, tries);
}
if !self.data[idx as usize] {
break;
Expand All @@ -73,10 +56,7 @@ impl SegmentAllocator {
}
};
self.mark(offset, size, Action::Allocate);
#[cfg(not(feature = "allocation_log"))]
return Some(offset);
#[cfg(feature = "allocation_log")]
return (Some(offset), tries);
}

/// Allocates a block of the given `size` at `offset`.
Expand Down
50 changes: 33 additions & 17 deletions betree/src/data_management/dmu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crossbeam_channel::Sender;
use futures::{executor::block_on, future::ok, prelude::*};
use parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::{
arch::x86_64::{__rdtscp, _rdtsc},
collections::HashMap,
fs::OpenOptions,
io::{BufWriter, Write},
Expand Down Expand Up @@ -256,7 +257,8 @@ where
let _ = file.write_u8(Action::Deallocate.as_bool() as u8);
let _ = file.write_u64::<LittleEndian>(obj_ptr.offset.as_u64());
let _ = file.write_u32::<LittleEndian>(obj_ptr.size.as_u32());
let _ = file.write_u32::<LittleEndian>(0);
let _ = file.write_u64::<LittleEndian>(0);
let _ = file.write_u64::<LittleEndian>(0);
}
if let (CopyOnWriteEvent::Removed, Some(tx), CopyOnWriteReason::Remove) = (
self.handler.copy_on_write(
Expand Down Expand Up @@ -548,7 +550,9 @@ where
// Or save the largest contiguous memory region as a value and compare against that. For
// that the allocator needs to support that and we have to 'bubble' the largest value up.
#[cfg(feature = "allocation_log")]
let mut total_tries: u32 = 0;
let mut start_cycles_global = get_cycles();
#[cfg(feature = "allocation_log")]
let mut total_cycles_local: u64 = 0;
'class: for &class in strategy.iter().flatten() {
let disks_in_class = self.pool.disk_count(class);
if disks_in_class == 0 {
Expand Down Expand Up @@ -604,31 +608,35 @@ where
// Has to be split because else the temporary value is dropped while borrowing
let bitmap = self.handler.get_allocation_bitmap(*segment_id, self)?;
let mut allocator = bitmap.access();
let allocation = allocator.allocate(size.as_u32());
#[cfg(feature = "allocation_log")]

#[cfg(not(feature = "allocation_log"))]
{
total_tries += allocation.1;
let allocation = allocator.allocate(size.as_u32());
if let Some(segment_offset) = allocation {
let disk_offset = segment_id.disk_offset(segment_offset);
break disk_offset;
}
}

// This has to be done like that, such that offset is in scope below
#[cfg(feature = "allocation_log")]
let offset = allocation.0;
#[cfg(not(feature = "allocation_log"))]
let offset = allocation;
{
let start_cycles_allocation = get_cycles();
let allocation = allocator.allocate(size.as_u32());
let end_cycles_allocation = get_cycles();
total_cycles_local += end_cycles_allocation - start_cycles_allocation;

if let Some(segment_offset) = offset {
let disk_offset = segment_id.disk_offset(segment_offset);
if let Some(segment_offset) = allocation {
let disk_offset = segment_id.disk_offset(segment_offset);
let total_cycles_global = end_cycles_allocation - start_cycles_global;

#[cfg(feature = "allocation_log")]
{
let mut file = self.allocation_log_file.lock();
file.write_u8(Action::Allocate.as_bool() as u8)?;
file.write_u64::<LittleEndian>(disk_offset.as_u64())?;
file.write_u32::<LittleEndian>(size.as_u32())?;
file.write_u32::<LittleEndian>(total_tries)?;
}
file.write_u64::<LittleEndian>(total_cycles_local)?;
file.write_u64::<LittleEndian>(total_cycles_global)?;

break disk_offset;
break disk_offset;
}
}

let next_segment_id = segment_id.next(disk_size);
Expand Down Expand Up @@ -1118,3 +1126,11 @@ where
self.report_tx = Some(tx);
}
}

fn get_cycles() -> u64 {
unsafe {
//let mut aux = 0;
//__rdtscp(aux)
_rdtsc()
}
}
Loading

0 comments on commit ff6bfb4

Please sign in to comment.