views:

2104

answers:

5

For example, I have a std::map with known sizeof(A) and sizefo(B), while map has N entries inside. How would you estimate its memory usage? I'd say it's something like

(sizeof(A) + sizeof(B)) * N * factor

But what is the factor? Different formula maybe?

Update: Maybe it's easier to ask for upper bound?

+1  A: 

The size of the map really depends on the implementation of the map. You might have different sizes on different compilers/platforms, depending on which STL implementation they are providing.

Why do you need this size?

Cătălin Pitiș
Ok, g++. I need this size to know hom much entries i can hold in memory before i start swapping. I need upper bound.
Drakosha
If you need the upper bound, I suggest to take a look to the implementation of the map, to see how a map node object is implemented and to consider the size of the members of the map node as extra to the size of the key and element. Be aware that this approach is platform and compiler specific.
Cătălin Pitiș
+7  A: 

The estimate would be closer to

(sizeof(A) + sizeof(B) + ELEMENT_OVERHEAD) * N + CONTAINER_OVERHEAD

There is an overhead for each element you add, and there is also a fixed overhead for maintaining the data structure used for the data structure storing the map. This is typically a binary tree, such as a Red-Black Tree. For instance, in the GCC C++ STL implementation ELEMENT_OVERHEAD would be sizeof(_Rb_tree_node_base) and CONTAINER_OVERHEAD would be sizeof(_Rb_tree). To the above figure you should also add the overhead of memory management structures used for storing the map's elements.

It's probably easier to arrive at an estimate by measuring your code's memory consumption for various large collections.

Diomidis Spinellis
While i totally agree with you, i'd like to have some upper bound without knowing internal STL struct sizes.
Drakosha
Are there not going to be N tree nodes?
Martin York
I disagree with this estimate, generally leaf nodes have the same size as non leaf nodes, so the '+ TREE_NODE_SIZE * log2(N)' part is not accurate.
Don Neufeld
Thanks, right! I corrected the entry.
Diomidis Spinellis
+6  A: 

If you really want to know the runtime memory footprint, use a custom allocator and pass it in when creating the map. See Josuttis' book and this page of his (for a custom allocator).

Maybe it's easier to ask for upper bound?

The upper bound will depend on the exact implementation (e.g. the particular variant of balanced tree used). Maybe, you can tell us why you need this information so we can help better?

dirkgently
Thats the *only* way to get an accurate number.
David Lehavi
Can STL internal allocator supply information how much memory totally is used by STL?
Drakosha
@Drakosha: No, that allocator is not meant to do this. Which is why you need to create a custom one that will report whatever you want it to.
dirkgently
Stephan T. Lavavej also has a nice article on custom allocators: http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx Read the comments for a bit of trivia about <cheader> vs. <header.h> use. Now I can feel justified in my continued use of the .h variant of C headers in my C++ code!
Michael Burr
@Michael: Why headers all of sudden? Some context will be of help!
dirkgently
A: 

The formula is more like:

(sizeof(A) + sizeof(B) + factor) * N

where factor is the per entry overhead. C++ maps are typically implemented as red-black trees. These are binary trees, so there will be at least two pointers for the left/right nodes. There will also be some implementation stuff - probably a parent pointer and a "colour" indicator, so factor may be something like

(sizeof( RBNode *) * 3 + 1) / 2

However, all this is highly implementation dependent - to find out for sure you really need to examine the code for your own library implementation.

anon
+1  A: 

You could use MemTrack, by Curtis Bartley. It's a memory allocator that replaces the default one and can track memory usage down to the type of allocation.

An example of output:

-----------------------
Memory Usage Statistics
-----------------------

allocated type                        blocks          bytes  
--------------                        ------          -----  
struct FHRDocPath::IndexedRec          11031  13.7% 2756600  45.8%
class FHRDocPath                       10734  13.3%  772848  12.8%
class FHRDocElemPropLst                13132  16.3%  420224   7.0%
struct FHRDocVDict::IndexedRec          3595   4.5%  370336   6.2%
struct FHRDocMDict::IndexedRec         13368  16.6%  208200   3.5%
class FHRDocObject *                      36   0.0%  172836   2.9%
struct FHRDocData::IndexedRec            890   1.1%  159880   2.7%
struct FHRDocLineTable::IndexedRec       408   0.5%  152824   2.5%
struct FHRDocMList::IndexedRec          2656   3.3%  119168   2.0%
class FHRDocMList                       1964   2.4%   62848   1.0%
class FHRDocVMpObj                      2096   2.6%   58688   1.0%
class FHRDocProcessColor                1259   1.6%   50360   0.8%
struct FHRDocTextBlok::IndexedRec        680   0.8%   48756   0.8%
class FHRDocUString                     1800   2.2%   43200   0.7%
class FHRDocGroup                        684   0.8%   41040   0.7%
class FHRDocObject * (__cdecl*)(void)     36   0.0%   39928   0.7%
class FHRDocXform                        516   0.6%   35088   0.6%
class FHRDocTextColumn                   403   0.5%   33852   0.6%
class FHRDocTString                      407   0.5%   29304   0.5%
struct FHRDocUString::IndexedRec        1800   2.2%   27904   0.5%
Xavier Nodet