Idea: Reduce the size of `Ref` and `RefMut` to one pointer size

Currently, Ref and RefMut both have size of two pointers because they store both the address of the value and the address of the borrow flag. But it seems that we only need to store one of those two addresses, the other one can be calculated with the offset of borrow field and value field in RefCell:

pub struct RefCell<T: ?Sized> {
    borrow: Cell<BorrowFlag>,
    #[cfg(feature = "debug_refcell")]
    borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
    value: UnsafeCell<T>,
}

Rc::from_raw already have used field offset to obtain the address of its owner struct, is it a good idea to use the same technique in Ref and RefMut?

Heck, you don’t even need something that clever: they can just store &RefCell and build everything on top of that.

My guess is that Ref and RefMut are usually found on the stack, and so it’s not really worth optimizing for their size. Saving both addresses directly means not having to calculate either when accessing the value and when the borrow ends. It probably also makes implementation simpler. But, it could still be worth benchmarking, if you have the time to whip up a pull request. (Not that I’m in charge of what is and isn’t worth benchmarking.)

There’s also always a possibility that I’m missing a circumstance where you have many outstanding Refs and thus their in-memory size starts to matter. Do you have such a use case?

3 Likes

Once you call map, the value pointer might have come from an indirection, so it's not even be part of the same allocation anymore.

4 Likes

I see. A possible solution is to add a new RefMap type that contains two pointers for map function, but it’s too late to change the implementation now.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.