[英]How can I know how much memory an STL object takes?
I need to gather statistics about memory usage in my program. 我需要在程序中收集有关内存使用情况的统计信息。
My code is mostly written using STL. 我的代码主要使用STL编写。
Is there any way of learning how much memory is being consumed by an STL object? 有没有办法了解STL对象消耗了多少内存?
For example, 例如,
string s1 = "hello";
string s2 = "hellohellohellohellohellohellohellohellohellohellohellohellohello";
How much memory is consumed by s1
and s2
? s1
和s2
消耗了多少内存? Obviously, sizeof(string)+s1.length()
is not quite accurate. 显然,
sizeof(string)+s1.length()
不太准确。
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: Windows结果:
0 //this is zero, because the string did not allocate heap space.
0 //这是零,因为字符串没有分配堆空间。
6464
1111
http://ideone.com/lr4I8 (GCC) results: http://ideone.com/lr4I8(GCC )成果:
24
24
9292
1111
Since this is completely implementation details, you cannot determine this with 100%
accuracy. 由于这是完全实现的细节,因此无法以
100%
准确度来确定。
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: 我相信,对于
std::string
,字符串对象占用的内存大小几乎等于:
size_t statisticalSizeStr = sizeof(string)+ s.capacity() * sizeof(char);
And similarly, for std::vector
同样,对于
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. 对于矢量,您也可以用相同的方式考虑
T
的大小,它将填充上述等式中的....
For example, if T
is std::string
, then: 例如,如果
T
是std::string
,那么:
size_t vecSize = sizeof(std::vector<std::string>);
size_t statisticalSizeVec = vecSize + v.capacity() * statisticalSizeStr;
And if T
is int
, then 如果
T
是int
,那么
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. 我希望,这样的分析可以帮助您尽可能准确地计算尺寸。
Just for fun, I made my best attempt to find the memory usage of the individual strings you gave. 只是为了好玩,我尽最大努力找到你给出的单个字符串的内存使用情况。 I concur with people who say this is basically impossible;
我同意那些说基本上不可能的人; my implementation is not good in many ways:
我的实现在很多方面都不好:
#define private public
gives away that I'm "doing it wrong" and depending on something which is not only not standardized but even for my STL implementation (gcc 4.6) might change by next release. #define private public
表示我“做错了”并且取决于不仅没有标准化的东西,甚至我的STL实现(gcc 4.6)可能会在下一个版本中改变。 You should never see this in production code. std::string
. std::string
。 You'd have to do specific logic for each type as no general mechanism exists on my platform. O(1)
get_allocated_size()
. O(1)
get_allocated_size()
没有现有的精确计数器。 malloc_usable_size
to see the actual size of the area returned by malloc. malloc_usable_size
来查看malloc返回的区域的实际大小。 First, this is specific to the allocator included with glibc
. glibc
附带的分配器特有的。 Second, it doesn't count malloc's book-keeping memory. In practice, I'd suggest make the sort of approximation Nawaz mentioned and validating it empirically with whole-process measurements as other people have mentioned. 在实践中,我建议将Nawaz提及的近似值与其他人提到的全过程测量结果进行经验验证。
With that said, here we go: 话虽如此,我们走了:
$ cat > sizetest.cc <<EOF
#define private public // eww...
#include <malloc.h>
#include <iostream>
#include <string>
using namespace std;
// NON-PORTABLE! Totally dependent on gcc 4.6 / glibc (with the stock allocator)!
size_t get_size(const string &s) {
string::_Rep *rep = (string::_Rep*) s.data() - 1;
return sizeof(string) + malloc_usable_size(rep);
}
int main(int argc, char **argv) {
string s1 = "hello";
string s2 = "hellohellohellohellohellohellohellohellohellohellohellohellohello";
cout << "s1 size: " << get_size(s1) << endl;
cout << "s2 size: " << get_size(s2) << endl;
return 0;
}
EOF
$ g++ -Wall sizetest.cc -o sizetest
$ ./sizetest
s1 size: 48
s2 size: 112
I don't think it would be possible to measure for an individual container. 我认为不可能测量单个容器。
However, to get an overall summary, you can use the mallinfo() function (on Linux). 但是,要获得总体摘要,可以使用mallinfo()函数(在Linux上)。
If you want to know where are the biggest memory hogs in your program, you can run it under valgrind with its massif memory profiler , which will give you information like "15 MB were allocated from map<my_data>::...
", so you can guess how large your structures are. 如果你想知道你的程序中最大的内存占用量,你可以在valgrind下使用它的massif内存分析器来运行它,它将为你提供“15 MB从
map<my_data>::...
”分配的信息,所以你可以猜出你的结构有多大。
You can use the Psapi for this if you want general memory usage statistics. 如果需要常规内存使用情况统计信息,可以使用Psapi。
#ifdef WIN32
#include <psapi.h>
#elif __GNUC__
#include <sys/time.h>
#include <sys/resource.h>
#endif
void MemoryUsage()
{
#ifdef WIN32
PROCESS_MEMORY_COUNTERS pmc;
if(GetProcessMemoryInfo(GetCurrentProcess(),&pmc,sizeof(pmc)))
{
// do something with the values you care about
pmc.PagefileUsage;
pmc.PeakPagefileUsage;
pmc.PeakWorkingSetSize;
pmc.QuotaNonPagedPoolUsage;
pmc.QuotaPagedPoolUsage;
pmc.QuotaPeakNonPagedPoolUsage;
pmc.WorkingSetSize;
}
#else
// I'm not a penguin
#endif
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.