How much memory is consumed by my object

I want to know a programmatic way to get the memory consumed by my user-defined class. Below is the class declaration

struct TrieNode { typedef std::map<char, TrieNode *> ChildType; std::string m_word; bool m_visited; } 

I inserted around 264061 words into this Trie . After that, when I do sizeof(trieobject) , just show me 32 . How to find out exactly how much memory is used by such data structures.

+4
source share
5 answers

I use

 valgrind --tool=massif ./myprogram -opt arg1 arg2 ms_print massif.* | less -SR 

for this. Example output from this page

 19.63^ ### | # | # :: | # : ::: | :::::::::# : : :: | : # : : : :: | : # : : : : ::: | : # : : : : : :: | ::::::::::: # : : : : : : ::: | : : # : : : : : : : :: | ::::: : # : : : : : : : : :: | @@@: : : # : : : : : : : : : @ | ::@ : : : # : : : : : : : : : @ | :::: @ : : : # : : : : : : : : : @ | ::: : @ : : : # : : : : : : : : : @ | ::: : : @ : : : # : : : : : : : : : @ | :::: : : : @ : : : # : : : : : : : : : @ | ::: : : : : @ : : : # : : : : : : : : : @ | :::: : : : : : @ : : : # : : : : : : : : : @ | ::: : : : : : : @ : : : # : : : : : : : : : @ 0 +----------------------------------------------------------------------->KB 0 29.48 Number of snapshots: 25 Detailed snapshots: [9, 14 (peak), 24] 

The rest of the log shows the highest percentages of memory allocation, you can specifically see what type of class accepts that% of heap memory (and where allocations occur in terms of the call stack), for example:

 -------------------------------------------------------------------------------- n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 10 10,080 10,080 10,000 80 0 11 12,088 12,088 12,000 88 0 12 16,096 16,096 16,000 96 0 13 20,104 20,104 20,000 104 0 14 20,104 20,104 20,000 104 0 99.48% (20,000B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc. ->49.74% (10,000B) 0x804841A: main (example.c:20) | ->39.79% (8,000B) 0x80483C2: g (example.c:5) | ->19.90% (4,000B) 0x80483E2: f (example.c:11) | | ->19.90% (4,000B) 0x8048431: main (example.c:23) | | | ->19.90% (4,000B) 0x8048436: main (example.c:25) | ->09.95% (2,000B) 0x80483DA: f (example.c:10) ->09.95% (2,000B) 0x8048431: main (example.c:23) 
+4
source

Well, this is not so easy to do. First of all, is m_word a variable-sized string to the right? Internally, std :: string contains many characters, among other things. The same goes for std :: map. I think you can get a rough estimate based on the * TrieNode card size, but that will be just a rough estimate.

I think some code profiling with an external tool would be more useful. Hell, you can even use the task manager if you don't have tools available :).

+1
source

"Object size" - sizeof (std :: string) + sizeof (bool) + m_word.capacity () + space bytes or sizeof (trieobject) + m_word.capacity ()

0
source

Here is a code snippet for GCC that I came up with that you can use in a test program where you only instantiate one object of your class and do some typical work with it. The code replaces the global operator new() and operator delete() ; therefore, it will only track allocations using the ::new expressions and the standard allocator, provided that the standard distributor itself uses ::operator new() (this is the case for GCC).

Since we need to track pointers and their distributions, we need a separate map for this, which, of course, cannot use a standard distributor; GCC malloc-allocator comes to the rescue.

We use a statically initialized global to force memory tracking after main returns data.

 #include <unordered_map> #include <string> #include <iostream> #include <ext/malloc_allocator.h> struct Memtrack { typedef std::unordered_map<void*, std::size_t, std::hash<void*>, std::equal_to<void*>, __gnu_cxx::malloc_allocator<void*>> AllocMap; static int memtrack; static int memmax; static AllocMap allocs; Memtrack() { std::cout << "starting tracker: cur = " << memtrack << ", max = " << memmax << ".\n"; } ~Memtrack() { std::cout << "ending tracker: cur = " << memtrack << ", max = " << memmax << ".\n"; } static void track_new(std::size_t n, void * p) { memtrack += n; if (memmax < memtrack) memmax = memtrack; allocs[p] = n; std::cout << "... allocating " << n << " bytes...\n"; } static void track_delete(void * p) { const int n = int(allocs[p]); memtrack -= n; std::cout << "... freeing " << n << " bytes...\n"; } } m; int Memtrack::memtrack = 0; int Memtrack::memmax = 0; Memtrack::AllocMap Memtrack::allocs; void * operator new(std::size_t n) throw(std::bad_alloc) { void * const p = std::malloc(n); Memtrack::track_new(n, p); return p; } void operator delete(void * p) throw() { Memtrack::track_delete(p); std::free(p); } int main() { std::cout << "Beginning of main.\n"; std::unordered_map<std::string, int> m; // this piece of code m["hello"] = 4; // is a typical test for working m["world"] = 7; // with dynamic allocations std::cout << "End of main.\n"; } 

Some typical output:

 starting tracker: cur = 0, max = 0. Beginning of main. ... allocating 48 bytes... ... allocating 12 bytes... ... allocating 12 bytes... End of main. ... freeing 12 bytes... ... freeing 12 bytes... ... freeing 48 bytes... ending tracker: cur = 0, max = 72. 
0
source

Trivial If you have some time (what could be if you are only interested in size for debugging / optimization purposes). This approach may not be suitable for production code!

 #include <malloc.h> template <typename T> int objSize(T const* obj) { // instead of uordblks, you may be interested in 'arena', you decide! int oldSize = mallinfo().uordblks; T* dummy = new T(*obj); int newSize = mallinfo().uordblks; delete dummy; return newSize - oldSize; } 
-1
source

Source: https://habr.com/ru/post/1380763/


All Articles