peak_alloc icon indicating copy to clipboard operation
peak_alloc copied to clipboard

implement rest of `GlobalAlloc`

Open droundy opened this issue 3 years ago • 2 comments

By only implementing alloc and dealloc (and not realloc or alloc_zeroed) you introduce an additional and needless cost to using peak_alloc. Would you accept a pull request adding support for the other two methods?

droundy avatar May 12 '22 19:05 droundy

Of course, I'd love to !

xgillard avatar May 12 '22 21:05 xgillard

Not sure what the additional and needless cost is here.

Using the rust-analyzer LSP to insert the default implementation of realloc and alloc_zeroed yields the following code, which calls into alloc and dealloc ensuring that peak_alloc maintains a proper account of memory used.

Is the goal to optimize and consolidate the identical branch checks with !ptr.is_null() (one in each function: alloc, dealloc, realloc, alloc_zeroed)?

    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
        let size = layout.size();
        // SAFETY: the safety contract for `alloc` must be upheld by the caller.
        let ptr = unsafe { self.alloc(layout) };     // !!! Null check 1 when alloc() called.
        if !ptr.is_null() {    // !!! Null check 2
            // SAFETY: as allocation succeeded, the region from `ptr`
            // of size `size` is guaranteed to be valid for writes.
            unsafe { std::ptr::write_bytes(ptr, 0, size) };
        }
        ptr
    }

    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
        // SAFETY: the caller must ensure that the `new_size` does not overflow.
        // `layout.align()` comes from a `Layout` and is thus guaranteed to be valid.
        let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
        // SAFETY: the caller must ensure that `new_layout` is greater than zero.
        let new_ptr = unsafe { self.alloc(new_layout) };    // !!! Null check 1 when alloc() called.
        if !new_ptr.is_null() {    // !!! Null check 2
            // SAFETY: the previously allocated block cannot overlap the newly allocated block.
            // The safety contract for `dealloc` must be upheld by the caller.
            unsafe {
                std::ptr::copy_nonoverlapping(ptr, new_ptr, std::cmp::min(layout.size(), new_size));
                self.dealloc(ptr, layout);    // !!! Null check 3
            }
        }
        new_ptr
    }

boxofrox avatar May 17 '25 19:05 boxofrox