测量峰值内存消耗

时间:2019-05-01 13:40:58

标签: boehm-gc

我想计算应用程序的峰值内存消耗。为此,我想监视分配和释放。以下是对该概念的简短描述。希望您可以对此进行验证/纠正。

分配监控

钩住所有分配器宏(GC_MALLOCGC_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收集事件)

在发出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终结器(使我的应用程序始终具有相同的峰值分配值)?

0 个答案:

没有答案