我想计算应用程序的峰值内存消耗。为此,我想监视分配和释放。以下是对该概念的简短描述。希望您可以对此进行验证/纠正。
钩住所有分配器宏(GC_MALLOC
,GC_REALLOC
等),以便将给定指针保存为其原始大小(请求的大小而不是GC_size)。
一个例子:
// Track all the pointers with the size.
// The size is needed to know when free happens.
std::map<void*, size_t> addressTable;
size_t allocated = 0;
size_t peak_allocated = 0;
#undef GC_MALLOC
#define GC_MALLOC(size) GC_malloc_hook(size)
void* GC_malloc_hook(size_t size)
{
#if defined(GC_DEBUG)
void* ptr = GC_debug_malloc(size, GC_EXTRAS);
#else
void* ptr = GC_malloc(size);
#endif
addressTable[ptr] = size; // Save the pointer and its size.
allocated += size;
if (allocated > peak_allocated)
peak_allocated = allocated;
return ptr;
}
这部分有两种不同的解决方案。我不知道它们是否等同于可能的解除分配检查器解决方案。
使用GC_REGISTER_FINALIZER_NO_ORDER
宏为每个指针(由GC_MALLOC
及其朋友提供)注册终结器回调。在这种情况下,GC可以在取消分配内存区域之前进行通知。
请注意,GC_FREE
也应进行检查,因为(如我所检查的那样),当显式释放发生时,终结器回调不会执行。
一个示例(使用finalizer回调扩展以上代码):
void* GC_malloc_hook(size_t size)
{
#if defined(GC_DEBUG)
void* ptr = GC_debug_malloc(size, GC_EXTRAS);
#else
void* ptr = GC_malloc(size);
#endif
addressTable[ptr] = size; // Save the pointer and its size.
allocated += size;
if (allocated > peak_allocated)
peak_allocated = allocated;
GC_REGISTER_FINALIZER_NO_ORDER(ptr, [](void* obj, void* cd)
{
allocated -= addressTable[obj];
addressTable.erase(obj);
}, nullptr, nullptr, nullptr);
return ptr;
}
#undef GC_FREE
#define GC_FREE(address) GC_free_hook(address)
void GC_free_hook(void* address)
{
#if defined(GC_DEBUG)
GC_debug_free(address);
#else
GC_free(address);
#endif
allocated -= addressTable[address];
addressTable.erase(address);
}
在发出GC_EVENT_END
事件时(假设发生了一些空闲事件),应该检查跟踪的指针是否仍在GC堆上。我不确定,但是也许GC_is_valid_displacement
函数可以提供帮助。
// The pointer is not valid.
GC_is_valid_displacement_print_proc = [](void* ptr)
{
allocated -= addressTable[ptr];
addressTable.erase(ptr);
};
GC_set_on_collection_event([](GC_EventType evtType)
{
if (GC_EVENT_END != evtType)
return;
// Loop on all the tracked pointers and check their validity after GC.
auto iter = addressTable.begin();
while (iter != addressTable.end()) {
GC_is_valid_displacement(iter->first);
iter++;
}
});
您怎么看?哪种检查内存分配是否更好的解决方案?
GC时间(发生GC最终确定时)会影响峰值内存的值。因此,当我多次运行应用程序时,可能会分配不同的峰值。 BDWGC中是否有任何功能可以帮助同时运行GC终结器(使我的应用程序始终具有相同的峰值分配值)?