Open rmolinari opened 1 year ago
Thanks for the suggestion!
The difficulty of trying to implement this within the library is that there is no standard, cross-platform way to determine the size of the header that malloc
and friends place before the allocated block or the padding they place at the end. This problem especially affects list
and the planned red-black trees, which store each node in a separate allocation (just counting the memory the library requests would result in a significant underestimate of actual memory consumption). So the issue requires some thought.
In the meantime, I can tell you that the memory usage of each container is as follows:
vec | MALLOC_HDR_SIZE + sizeof( cc_vec_hdr_ty ) + cap( &our_vec ) * CC_EL_SIZE( our_vec ) + MALLOC_PADDING |
list | MALLOC_HDR_SIZE + sizeof( cc_list_hdr_ty ) + MALLOC_PADDING + size( &our_list ) * ( MALLOC_HDR_SIZE + sizeof( cc_listnode_hdr_ty ) + CC_EL_SIZE( our_list ) + MALLOC_PADDING ) |
map | MALLOC_HDR_SIZE + sizeof( cc_map_hdr_ty ) + cap( &our_map ) * CC_MAP_BUCKET_SIZE( our_map ) + MALLOC_PADDING |
set | MALLOC_HDR_SIZE + sizeof( cc_map_hdr_ty ) + cap( &our_set ) * CC_SET_BUCKET_SIZE( our_set ) + MALLOC_PADDING |
MALLOC_HDR_SIZE
is probably 8 or 16 bytes. I'm not sure what MALLOC_PADDING
should be. A few minutes of experimentation with malloc_usable_size
suggests that malloc
on Linux rounds up the memory after the header to 24 + multiples of 16 bytes.
The memory usage of an initialized but not yet used container is effectively zero because init
points the container pointer at a global, static placeholder shared among all containers of the same type. The first dynamic allocation only occurs when the first element is added.
Wow! Thanks for the quick and detailed reply.
For the purposes of Ruby's runtime, a best effort seems to be enough here. So I'll use your formulas and ignore the header and padding for now. I'm sure this will be fine.
Thanks again.
Q: should, say, cc_vec_hdr
be cc_vec_hdr_ty
?
Oops! Sorry. You're right — all those container header structs should be suffixed with _ty
. The non-_ty
identifiers are the names of internal library functions for accessing the headers. I've updated my earlier response.
Thanks so much for this fascinating code!
I am suggesting a function that looks like this:
It would return the amount of (heap) memory associated with cntr.
Use case: when I am writing extension code for Ruby in C, the Ruby runtime likes to know how much memory is associated with a given object (although it doesn't insist on this knowledge). This helps with profiling and (I suspect) the Ruby garbage collector.