Reputation: 1
I have the following program:
#include <unistd.h>
#include <cstdlib>
int main()
{
for (int i=0; i<512*512*512; i++)
int *v = (int *) malloc(sizeof(int));
sleep(1000000000); // time to see memory consumption from htop
return 0;
}
Using top (htop), I can see how much memory is allocated (~4 GiB). Rewriting line 6 into
int *v = (int *) malloc(6*sizeof(int));
I can see that the same amount of memory is being allocated. This changes with malloc(7*sizeof(int))
; by such experimentation, I notice that the program always allocates a 32-byte sized block. This becomes very costly because in total I count 32 bytes for the block and 8 bytes for the pointer (If I store them in a vector) = 40 bytes just for one integer, which would otherwise cost only 4 bytes, therefore 10 times higher memory consumption using this dynamic memory allocation. I would like to know why the memory block size is chosen of this size, and why the compiler does not optimize it by reserving a smaller block (just for one integer instead of the one that can accommodate 6 integers). Since I don't have a computer science background and lack the proper terminology, I'm unable to find the correct literature to understand this in more detail. Any recommendation?
Thank you.
Upvotes: 0
Views: 489
Reputation: 62532
Memory allocation strategies is a complex area, so it will be be hard to give an answer that covers every scenario. However, typically your library will allocation a large chunk of memory from the operating system and then divide that up into blocks which it will use for allocation requests.
The library will need to keep housekeeping information about the blocks, such as if they are allocated. If the memory you allocate is larger than a single block then the blocks will need to be physically next to each other in memory, and the library will need to know how many blocks are part of the requested allocation (more housekeeping).
Additionally alignment rules mean that the library will been to return a pointer to memory that is correctly aligned. On a 64bit operating system this means that the address will be a multiple of 8, so if you're requesting an allocation less than this then you'll pay a cost.
The library designers will have likely done analysis and worked out what is the optimal block size based on the cost of managing the blocks versus what sizes people typically allocate. It's very rare to just allocate sizeof(int)
in the real world, typically it a struct/class
or run of memory, at which point the unused portion of the block/blocks not used by your allocation become insignificant.
Upvotes: 1
Reputation: 238421
Why dynamic allocation of small objects in C++ reserves much more memory than actually needed?
Any recommendation?
std::malloc
in C++.Upvotes: 3