Skip to content

Commit 299b0f6

Browse files
committed
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.
1 parent f1c8537 commit 299b0f6

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

src/raw/mod.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,19 @@ impl<T, A: Allocator + Clone> RawTable<T, A> {
521521
self.data_end().as_ptr().wrapping_sub(self.buckets())
522522
}
523523

524+
/// Return the information about memory allocated by the table.
525+
///
526+
/// `RawTable` allocates single memory block to store both data and metadata.
527+
/// This function returns allocation size and alignment and the beginning of the area.
528+
/// These are the arguments which will be passed to `dealloc` when the table is dropped.
529+
///
530+
/// This function might be useful for memory profiling.
531+
#[inline]
532+
#[cfg(feature = "raw")]
533+
pub fn allocation_info(&self) -> (NonNull<u8>, Layout) {
534+
self.table.allocation_info(Self::TABLE_LAYOUT)
535+
}
536+
524537
/// Returns the index of a bucket from a `Bucket`.
525538
#[inline]
526539
pub unsafe fn bucket_index(&self, bucket: &Bucket<T>) -> usize {
@@ -1573,15 +1586,21 @@ impl<A: Allocator + Clone> RawTableInner<A> {
15731586

15741587
#[inline]
15751588
unsafe fn free_buckets(&mut self, table_layout: TableLayout) {
1589+
let (ptr, layout) = self.allocation_info(table_layout);
1590+
self.alloc.deallocate(ptr, layout);
1591+
}
1592+
1593+
#[inline]
1594+
fn allocation_info(&self, table_layout: TableLayout) -> (NonNull<u8>, Layout) {
15761595
// Avoid `Option::unwrap_or_else` because it bloats LLVM IR.
15771596
let (layout, ctrl_offset) = match table_layout.calculate_layout_for(self.buckets()) {
15781597
Some(lco) => lco,
1579-
None => hint::unreachable_unchecked(),
1598+
None => unsafe { hint::unreachable_unchecked() },
15801599
};
1581-
self.alloc.deallocate(
1582-
NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)),
1600+
(
1601+
unsafe { NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)) },
15831602
layout,
1584-
);
1603+
)
15851604
}
15861605

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

0 commit comments

Comments
 (0)