Reputation: 13257
I want to know programmatic way to get the memory consumed by my user defined class. Following is the declaration of the class
struct TrieNode {
typedef std::map<char, TrieNode *> ChildType;
std::string m_word;
bool m_visited;
}
I have inserted around 264061
words into this Trie
. After this when i do sizeof(trieobject)
it just show me 32
. How do i know how much exact memory is used by such data structures.
Upvotes: 4
Views: 1076
Reputation: 476950
Here's a piece of code 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()
; so it will only track allocations through ::new
expressions and the standard allocator, provided that the standard allocator itself uses ::operator new()
(this is the case for GCC).
Since we need to track the pointers and their allocations, we need a separate map for that, which of course cannot use the standard allocator itself; GCC's malloc-allocator comes to the rescue.
We use a statically initialized global to make the memory tracker print its data after main
returns.
#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.
Upvotes: 0
Reputation: 1569
Your "object size" is sizeof(std::string) + sizeof(bool) + m_word.capacity() + padding bytes or sizeof(trieobject) + m_word.capacity()
Upvotes: 0
Reputation: 34618
Trivial. If you have some time (which might be the case, if you are only interested in the size for debugging/optimising purposes). This approach might be unsuited 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;
}
Upvotes: -1
Reputation: 392883
I use
valgrind --tool=massif ./myprogram -opt arg1 arg2
ms_print massif.* | less -SR
for that. Sample output from this page
19.63^ ###
| #
| # ::
| # : :::
| :::::::::# : : ::
| : # : : : ::
| : # : : : : :::
| : # : : : : : ::
| ::::::::::: # : : : : : : :::
| : : # : : : : : : : ::
| ::::: : # : : : : : : : : ::
| @@@: : : # : : : : : : : : : @
| ::@ : : : # : : : : : : : : : @
| :::: @ : : : # : : : : : : : : : @
| ::: : @ : : : # : : : : : : : : : @
| ::: : : @ : : : # : : : : : : : : : @
| :::: : : : @ : : : # : : : : : : : : : @
| ::: : : : : @ : : : # : : : : : : : : : @
| :::: : : : : : @ : : : # : : : : : : : : : @
| ::: : : : : : : @ : : : # : : : : : : : : : @
0 +----------------------------------------------------------------------->KB 0 29.48
Number of snapshots: 25
Detailed snapshots: [9, 14 (peak), 24]
The remainder of the log details the highest percentiles of memory allocations, you can specifically see what type of class takes what % of heap memory (and where the allocations originate in terms of call stack), e.g.:
--------------------------------------------------------------------------------
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)
Upvotes: 4
Reputation: 26930
Well, this is not so easy to do. First of all m_word is a string with variable size right? Internally the std::string holds an array of chars among other things. The same stands for std::map. I guess you could get a rough estimation based on the size of the map * TrieNode but this will be just a rough estimate.
I think some code profiling with an external tool would be of more help. Hell you can even use the task manager if you are out of any tools left :).
Upvotes: 1