如何使用 EASTL 跟踪内存使用情况? [英] How to track memory usage using EASTL?

查看:27
本文介绍了如何使用 EASTL 跟踪内存使用情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Electronic Arts EASTL 图书馆的 east::allocator 需要用户实现一个特殊的 new 运算符(如这个 示例).这个 new 运算符有一个 const char* name,它应该用于记录有关内存 分配 执行 EASTL 容器的应用程序特定信息.EASTL 最佳实践指南也提到应该命名容器以跟踪内存使用情况."

The Electronic Arts EASTL library's east::allocator requires the user to implement a special new operator (as shown in this sample). This new operator has a const char* name, which is supposed to be used to log application-specific information about memory allocations performed EASTL containers. The EASTL Best Practices guide also mentions that one should "Name containers to track memory usage."

然而,eastl::allocator::deallocate 似乎没有任何对应的const char* name 传递,所以似乎没有一个build- 记录内存解除分配的方式.

However, there does not appear to be any corresponding const char* name passed by eastl::allocator::deallocate, so there does not appear to be a built-in way to log memory deallocations.

这个 EASTL 调试功能打算如何使用?我想我一定错过了一些东西.一位 EA 软件工程师也在 2015 年进行了相关的演示,展示了一些内部工具由 EA 开发用于内存调试,似乎建议他们同时跟踪分配和释放(例如,确保在游戏级别 2"开始时释放游戏级别 1"的内存).

How is this EASTL debugging functionality intended to be used? I think I must be missing something. An EA Software Engineer also gave a related presentation in 2015, where he showed some internal tools developed by EA for memory debugging, and it seems to suggest that they tracking both allocations and deallocations (for example, to ensure that the memory for "game level 1" is freed when "game level 2" begins).

推荐答案

EASTL 的分配器是有状态的并且绑定到容器的实例;这意味着它们是在实例级别定义的:

The allocators by the EASTL are stateful and bound to the instance of the container; meaning they are defined at instance level:

EASTL 所做的是使用更熟悉的内存分配模式因此只有一个分配器类接口,它由所有容器.此外,EASTL 容器可让您访问它们的分配器并查询它们、命名它们、更改它们等.

What EASTL does is use a more familiar memory allocation pattern whereby there is only one allocator class interface and it is used by all containers. Additionally EASTL containers let you access their allocators and query them, name them, change them, etc.

EASTL 选择使分配器不在容器之间复制在容器交换和分配操作期间.这意味着如果容器 A 与容器 B 交换其内容,两个容器保留其原始分配器.类似地,将容器 A 分配给容器 B 使容器 B 保留其原始分配器.等效的容器应通过 operator== 报告;东航如果分配器相等,将进行智能交换,并进行蛮力交换否则.

EASTL has chosen to make allocators not be copied between containers during container swap and assign operations. This means that if container A swaps its contents with container B, both containers retain their original allocators. Similarly, assigning container A to container B causes container B to retain its original allocator. Containers that are equivalent should report so via operator==; EASTL will do a smart swap if allocators are equal, and a brute-force swap otherwise.

来自 https://github.com/questor/Eastl/blob/master/doc/EASTL%20Design.html

所以我会向分配器类添加一个成员并跟踪其中的内存计数,如下所示:

So I would add a member to the allocator class and track the memory count inside it, like following:

#ifndef EASTL_CUSTOM_ALLOCATOR_H_
#define EASTL_CUSTOM_ALLOCATOR_H_

#include "new_implementation.hpp"
#include <EASTL/list.h>
#include <iostream>

#define DEBUG_MACRO

class EASTL_CustomAllocator {
public:
    EASTL_CustomAllocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME))
        : m_pName(pName), m_totalAmountOfBytesAllocated(0) {
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": default construct allocator" << std::endl;
#endif
    }
    EASTL_CustomAllocator(const EASTL_CustomAllocator& x)
        : m_pName(x.m_pName),
          m_totalAmountOfBytesAllocated(x.m_totalAmountOfBytesAllocated) {
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": copy construct allocator" << std::endl;
#endif
    }
    EASTL_CustomAllocator(const EASTL_CustomAllocator& x, const char* pName)
        : m_pName(pName),
          m_totalAmountOfBytesAllocated(x.m_totalAmountOfBytesAllocated) {
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": copy construct allocator" << std::endl;
#endif
    }

    EASTL_CustomAllocator& operator=(const EASTL_CustomAllocator& x) {
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": copy assignment" << std::endl;
#endif
        m_pName = x.m_pName;
        m_totalAmountOfBytesAllocated = x.m_totalAmountOfBytesAllocated;
        return *this;
    }

    void* allocate(size_t num_of_bytes, int flags = 0) {
        m_totalAmountOfBytesAllocated += num_of_bytes;
        void* p = ::new((char*)0, flags, 0, (char*)0,        0) char[num_of_bytes];
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": allocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
#endif
        return p;
    }
    void* allocate(size_t num_of_bytes, size_t alignment, size_t offset, int flags = 0) {
        m_totalAmountOfBytesAllocated += num_of_bytes;
        void* p = ::new(alignment, offset, (char*)0, flags, 0, (char*)0,        0) char[num_of_bytes];
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": allocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
#endif
        return p;
    }
    void  deallocate(void* p, size_t num_of_bytes) {
        m_totalAmountOfBytesAllocated -= num_of_bytes;
#ifdef DEBUG_MACRO
        std::cout << m_pName << ": deallocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
#endif
        delete[](char*)p;
    }

    const char* get_name() const {
        return m_pName;
    }
    void        set_name(const char* pName) {
        m_pName = pName;
    }
    size_t get_totalAmountOfBytesAllocated() const {
        return m_totalAmountOfBytesAllocated;
    }

protected:
    const char* m_pName;    // Debug name, used to track memory.
    size_t m_totalAmountOfBytesAllocated;   // keeps track of the memory currently allocated
};


bool operator==(const EASTL_CustomAllocator& a, const EASTL_CustomAllocator& b) {
    if (&a == &b) {
        return true;    // allocator a and b are equal if they are the same
    }
    else {
        return false;   // otherwhise, return false, because the state m_totalAmountOfBytesAllocated needs to be increased/decreased on splice and swap
    }
}
bool operator!=(const EASTL_CustomAllocator& a, const EASTL_CustomAllocator& b) {
    return false;
}


#endif /* EASTL_CUSTOM_ALLOCATOR_H_ */

将该自定义分配器类型作为模板参数传递给如以下的东西(您也可以在构造时使用用户定义的名称设置实例,甚至稍后通过 set_allocator()):

Pass that custom allocator type as a template parameter to a eastl container like following (also you can set a instance with a user-defined name at construction and even later by set_allocator()):

eastl::list<int, EASTL_CustomAllocator> 
list(EASTL_CustomAllocator("EASTL Some Name"));

但我不确定如何使用调试功能.

But I'm not sure how the debugging functionality is intended to be used.

这篇关于如何使用 EASTL 跟踪内存使用情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆