I have a large C++ program which uses much of the standard libraries. It also uses C-style allocation malloc much. I want to analyze how much memory is consumed in one module.
In short, Mgrx
are all very complicated classes. They consist of various fields, in which the standard libraries and custom-defined classes are widely used. Now I want to check how much memory Module1 consumes. I want to it less manually.
struct Mgr1;
struct Mgr2;
struct Mgr3;
struct Module1 {
vector<Mgr1> v1;
vector<Mgr1> v3;
...
};
struct Module2 {
vector<Mgr1> v2;
vector<Mgr1> v3;
};
Generally, there are several utils for problem:
- Jemalloc
Which means I can usethread.allocatedp
to track thread-wise allocation. If my program is moduled by thread pools(which means every module uses its own dedicated thread pool to consume requests, and communicate with each other by sending messages), then it is a good idea. - mmap/sbrk
I have totally got rid of directly calling mmap or sbrk for memory allocations. So all memory allocations are “delegated” by jemalloc - The arena of Jemalloc
- We can bind some threads to their dedicated arena, so the size of each arena represents memory “owned” by this thread.
- If the program is not moduled by thread pools, then we can use the
mallocx
in specific modules. For example, given a module A which calls module B. If we want to compute how much memory module B consumes, then we can replace allmalloc
withmallocx
, providing a MALLOCX_ARENA which specifies a dedicated arena for module B. Thus, the size of this arena is the memory “owned” by module B.
Aboving is general ideas of how to track memory thread-wise or module-wise. However, it is difficult to implement when using C++. Because:
- C++’s standard libraries uses Allocator to specify how to allocate memories. We can’t just replace
malloc
withmallocx
by some macro magic. We have to defined our own Allocator. It is kind of difficult, even the simpleststd::string
should be replaced withstd::basic_string<char, std::char_traits<char>, Myallocator<char>> s
. - Allocators have types,
vector<T, ThisAllocator<T>>
differs fromvector<T, ThatAllocator<B>>
. Moreover, if we have somevector<vector<T>>
or ever complicated types, we have to usescoped_allocator_adaptor
.
As a result, it is very hard to track memory allocation of all instances of a certain class or module.
I wonder if it is some easier ways that won’t reduce the performance too much? IMO, if every fields and sub-fields of Mgr1
uses some kind of Allocator
, then I can record memory usage in this allocator’s allocate
method. However, how can I enforce a custom Allocator
for and only for Mgr1
and all its direct or indirect sub-fields?