Skip to content

Commit

Permalink
Auto merge of #371 - stepancheg:alloc-info, r=Amanieu
Browse files Browse the repository at this point in the history
RawTable::allocation_info

We are implementing memory profiler for Rust.

We can approximate how much memory is occupied by `RawTable` by replicating some logic of `RawTable`, but it would be more correct/reliable if `RawTable` just exposed this information.

`RawTable::allocation_info` returns just that.

It returns both `Layout` and pointer to allocated memory.

Pointer is helpful when using with jemalloc: the pointer can be passed to `malloc_usable_size` function to measure precisely not just how much memory is requested by `RawTable`, but also what is malloc padding for the allocation.
  • Loading branch information
bors committed Nov 9, 2022
2 parents f1c8537 + 299b0f6 commit bf272b6
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions src/raw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,19 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
self.data_end().as_ptr().wrapping_sub(self.buckets())
}

/// Return the information about memory allocated by the table.
///
/// `RawTable` allocates single memory block to store both data and metadata.
/// This function returns allocation size and alignment and the beginning of the area.
/// These are the arguments which will be passed to `dealloc` when the table is dropped.
///
/// This function might be useful for memory profiling.
#[inline]
#[cfg(feature = "raw")]
pub fn allocation_info(&self) -> (NonNull<u8>, Layout) {
self.table.allocation_info(Self::TABLE_LAYOUT)
}

/// Returns the index of a bucket from a `Bucket`.
#[inline]
pub unsafe fn bucket_index(&self, bucket: &Bucket<T>) -> usize {
Expand Down Expand Up @@ -1573,15 +1586,21 @@ impl<A: Allocator + Clone> RawTableInner<A> {

#[inline]
unsafe fn free_buckets(&mut self, table_layout: TableLayout) {
let (ptr, layout) = self.allocation_info(table_layout);
self.alloc.deallocate(ptr, layout);
}

#[inline]
fn allocation_info(&self, table_layout: TableLayout) -> (NonNull<u8>, Layout) {
// Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
let (layout, ctrl_offset) = match table_layout.calculate_layout_for(self.buckets()) {
Some(lco) => lco,
None => hint::unreachable_unchecked(),
None => unsafe { hint::unreachable_unchecked() },
};
self.alloc.deallocate(
NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)),
(
unsafe { NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)) },
layout,
);
)
}

/// Marks all table buckets as empty without dropping their contents.
Expand Down

0 comments on commit bf272b6

Please sign in to comment.