开发者

How can I find out how much memory an instance of a C++ class consumes?

开发者 https://www.devze.com 2022-12-24 01:02 出处:网络
I am developing a Graph-class, based on boost-graph-library. A Graph-object contains a boost-graph, so to say an adjacency_list, and a map.

I am developing a Graph-class, based on boost-graph-library.

A Graph-object contains a boost-graph, so to say an adjacency_list, and a map. When monitoring the total memory usage of my program, it consumes quite a lot (checked with pmap).

Now, I would like to know, how much of the memory 开发者_JAVA技巧is exactly consumed by a filled object of this Graph-class? With filled I mean when the adjacency_list is full of vertices and edges.

I found out, that using sizeof() doesn't bring me far. Using valgrind is also not an alternative as there is quite some memory allocation done previously and this makes the usage of valgrind impractical for this purpose. I'm also not interested in what other parts of the program cost in memory, I want to focus on one single object.

Thank you.


If you are able to control the creation and filling of the object such that no other allocations are performed during that time, then one way to do this is to override new and delete operators with your own versions that simply count the total allocation size and store it in a global variable. Grab the total size at the beginning and the end, and the difference should be a reasonable approximation of the size used (not counting heap overhead).


I have never used adjacency_list so this is just an idea which although works with STL containers.

So using adjacency_list says BGL uses containers from the STL such as std::vector, std::list, and std::set to represent the set of vertices and the adjacency structure. OK, then you just have to give your adjacent list std::vector, std::list, and std::set which have their own allocator type. Adding your own allocator to STL containers is an easy task. Having done all this you just have to get from your allocators the size of memory that has been allocated while filling the adjacency_list.

So the idea is to build the adjacent list out of STL containers (which seems possible after a quick look at the BGL documentaiton) which have own allocator types.

Update 1 Actually you haven't told why you need to know how much bytes your graph consumes. If you just need to get this number only once you probably have to write you program with and without filling the graph. Then run for example UNIX95= ps -u $USER -o vsz,args and find out the difference. Roughly you will get the size of you graph.

If you need to get this values regularly in your application and if you are not able to implement the whole solution using allocators you need to start with a few small steps.

  1. Read about allocators: C++ Standard Allocator, An Introduction and Implementation Allocators(STL)
  2. Try to implement std::vector with your own allocator as an exercise
  3. Try to add counting bytes to your allocator
  4. Try to build the Boost graph with allocator Customizing the Adjacency List Storage
  5. Do something to count bytes in std::string members of your containers. By default they will not use the allocator of their container. So either instead use fixed-size strings or manage somehow insert a container's allocator in this string members. Again, take a look at Adding your own allocator to STL containers

By the way if you don't want to reinvent the C++ allocator you can just use something like that:

template <typename T> class your_allocator {    
public:
// here you need to put everything that is required by C++ standard
// and calls finally send to std_allocator_    
private:
    std::allocator<T> std_allocator_;    
};


I managed now to shrink everything down so far, that I can think of profiling with valgrind.
I then used "--tool=massif" to check heap-memory-consumption. I used the following code to create an instance of my Graph-class

    typedef Graph<VertexProperties, EdgeProperties> MyGraph;
    MyGraph* G;
    G = new MyGraph(*vertex_props);

The constructor is built in such a way, that it recieves a list of VertexProperties-pairs which equal to the edges and then stores everything via the adjacency_list.
The massif-profile then returned me the following results. For simplicity, I posted them in a pastebin: http://dpaste.com/hold/174033/
You can see there the diagram for the overall execution and the peak is reached at snapshot 83 with 235.4MiB.
My question is now, is this the overall maximum amount of memory on the heap consumed by my program? What about the approx. 1GB of memory usage that pmap returns me for my program? How do those values come together?
And most importantly, when looking at the details for snapshot 83, is says:

  1. 32.76% (80,842,846B) for std::string::_Rep::_S_create(....)
  2. 15.94% (39,341,760B) for std::_Rb_tree >
  3. 11.91% (29,389,824B) for main (new_allocator.h:92)

Am I getting it right, that 1. tells me that approx. 80MB are consumed for std::string and 2. tells me, that my Graph takes up approx. 40MB?
What does 3. then tell me?

Thank you.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号