I need to gather statistics about memory usage in my program.
My code is mostly written using STL.
Is there any way of learning how much memory is being consumed by an STL object?
For example,
string s1 = "hello";
string s2 = "hellohellohellohellohellohellohellohellohellohellohellohellohello";
How much memory is consumed by s1
and s2
?
Obviously, sizeof(string)+s1.length()
is not quite accurate.
So there is no surprise regarding std::vector. It uses 4 bytes to store each 4 byte elements.
These abilities come at a price: vectors consume more memory in exchange to handle storage and grow dynamically in size.
Yes, you are correct. Using the vector or string like that is indeed slow. Basically every time you append you're appending to the end of the container, you're potentially asking the container to reallocate a new buffer, copy the data over to the new buffer, and delete the old buffer.
Since this is completely implementation details, you cannot determine this with 100%
accuracy.
However, as you said, you want to put some code to statistics the memory usage in your program, then you can do that with some accuracy.
I believe, for std::string
, the size of memory taken by string objects, will be almost equal to:
size_t statisticalSizeStr = sizeof(string)+ s.capacity() * sizeof(char);
And similarly, for std::vector
size_t statisticalSizeVec = sizeof(std::vector<T>)+ ....;
You can model your statistical estimation on such informations. For vector, you can also consider the size of T
in the same way which will fill the ....
in the above equation. For example, if T
is std::string
, then:
size_t vecSize = sizeof(std::vector<std::string>);
size_t statisticalSizeVec = vecSize + v.capacity() * statisticalSizeStr;
And if T
is int
, then
size_t statisticalSizeVec=sizeof(std::vector<int>)+v.capacity()*sizeof(int);
I hope, such analysis would help you to compute the size with as much accuracy as possible.
If you're willing to be slightly intrusive, you can make a custom allocator to track all heap usage by container type, or by type allocated. This is quite intrusive, but quite accurate as well, for determining memory usage. This does not track how much memory the heap itself takes though, as that is highly OS-dependent.
template<class TrackType>
size_t* mem_used() {static size_t s = 0; return &s;}
template<class T, class TrackType, class BaseAllocator = std::allocator<T> >
class TrackerAllocator : public BaseAllocator {
public:
typedef typename BaseAllocator::pointer pointer;
typedef typename BaseAllocator::size_type size_type;
TrackerAllocator() throw() : BaseAllocator() {}
TrackerAllocator(const TrackerAllocator& b) throw() : BaseAllocator(b) {}
TrackerAllocator(TrackerAllocator&& b) throw() : BaseAllocator(b) {}
template <class U> TrackerAllocator(const typename TrackerAllocator::template rebind<U>::other& b) throw() : BaseAllocator(b) {}
~TrackerAllocator() {}
template<class U> struct rebind {
typedef TrackerAllocator<U, TrackType, typename BaseAllocator::template rebind<U>::other> other;
};
pointer allocate(size_type n) {
pointer r = BaseAllocator::allocate(n);
*mem_used<TrackType>() += n;
return r;
}
pointer allocate(size_type n, pointer h) {
pointer r = BaseAllocator::allocate(n, h);
*mem_used<TrackType>() += n;
return r;
}
void deallocate(pointer p, size_type n) throw() {
BaseAllocator::deallocate(p, n);
*mem_used<TrackType>() -= n;
}
};
And usage is:
typedef std::basic_string<char,
std::char_traits<char>,
TrackerAllocator<char, std::string> > trackstring;
typedef std::vector<int,
TrackerAllocator<int, std::vector<int> > > trackvector;
// ^ ^
// This identifies which memory to track
// it can be any type, related or no.
// All with the same type will be tracked togeather
int main() {
trackstring mystring1("HELLO WORLD");
std::cout << *mem_used<std::string>() << '\n'; //display memory usage of all strings
trackstring mystring2("MUCH LONGER STRING THAT DEFINITELY GETS HEAP ALLOCATED!");
std::cout << *mem_used<std::string>() << '\n'; //display memory usage of all strings
trackvector myvec(mystring1.begin(), mystring1.end());
std::cout << *mem_used<std::vector<int> >() << '\n'; //display memory usage of all vector<int>
// ^ ^
// This identifies which memory type from above to look up.
return 0;
}
Windows results:
0 //this is zero, because the string did not allocate heap space.
64
11
http://ideone.com/lr4I8 (GCC) results:
24
92
11
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With