带有jemalloc的C ++ STL

时间:2012-03-01 17:43:54

标签: c++ memory-management stl malloc

如何使用带有jemalloc(或任何其他malloc实现)的C ++ STL容器?

是否像include jemalloc/jemalloc.h一样简单?或者我应该为他们写一个分配器?

编辑:我正在处理的应用程序在其生命周期内分配和释放相对较小的对象。我想替换默认的分配器,因为基准测试显示应用程序不会超过2个核心。分析显示它正在等待内存分配,这就是导致扩展问题的原因。据我了解,jemalloc将有助于此。


我希望看到一个解决方案,这是平台中立的,因为应用程序必须在Linux和Windows上运行。 (在Linux下链接不同的实现很容易,但据我所知,在Windows上这很难实现。)

5 个答案:

答案 0 :(得分:8)

C ++允许您替换 operator new。如果此替换operator new调用je_malloc,则std::allocator会间接调用je_malloc,反过来所有标准容器都会调用。

这是迄今为止最简单的方法。编写自定义分配器需要编写整个类。替换malloc可能还不够(无法保证未替换的operator new调用malloc),并且它具有Adrian McCarthy先前提到的风险

答案 1 :(得分:6)

如果你想在程序的任何地方替换malloc(我想要的,也似乎是唯一的逻辑解决方案),那么你所要做的就是链接它。

因此,如果您使用gcc,那么您所要做的就是:

g++ yourprogram.cpp -ljemalloc

但是,如果不可能,那么你必须通过其他功能使用jemalloc,例如je_mallocje_free,然后您必须重载newdelete运算符。

如果您不使用特定于实现的功能(主要是统计信息),则无需包含任何标头。

答案 2 :(得分:3)

编写分配器将是最简单的解决方案,因为stl旨在具有可互换的分配器。这将是最简单的途径。

某些项目玩游戏尝试使用备用malloc实现来替换编译器的伴随库提供的mallocnew。这容易出现各种各样的问题,因为您最终依赖于编译器的特定实现细节以及它通常使用的库。这条道路充满了危险。

尝试全局替换malloc的一些危险:

  • 静态初始化程序顺序在C ++中具有有限的保证。除非您禁止可能分配内存的静态对象,否则无法保证在第一个调用者尝试使用它之前初始化分配器替换。运行时没有这个问题,因为编译器和运行时一起工作以确保在初始化任何静态之前完全初始化运行时。
  • 如果动态链接到运行时库,则无法确保某些运行时库的代码尚未绑定到自己的实现。在重新分发应用程序时,尝试修改编译器的运行时库可能会导致许可问题。
  • 所有其他分配方法可能并不总是最终依赖于malloc。例如,new的实现可能会绕过malloc进行大量分配,并直接调用操作系统来分配内存。这需要跟踪以确保不会意外地将此类分配发送到替换free

我相信Chromium和Firefox都取代了分配器,但是他们发挥了一些肮脏的技巧,可能不得不随着编译器,链接器和运行时的发展而更新他们的方法。

答案 3 :(得分:1)

可能存在问题,因为构造函数不会被调用。您可以使用operator new的不同选项(除了new之外有更多选项),它们可以在不调用构造函数的情况下分配内存,或者在已分配的内存中调用构造函数。 http://www.cplusplus.com/reference/std/new/operator%20new%5B%5D/

答案 4 :(得分:1)

让自己成为分配者。这样做:

#include <vector>

template<typename T>
struct RemoveConst
{
    typedef T value_type;
};

template<typename T>
struct RemoveConst<const T>
{
    typedef T value_type;
};

template <class T>
class YourAlloc {
public:
    // type definitions
    typedef RemoveConst<T>              Base;
    typedef typename Base::value_type   value_type;
    typedef value_type*                 pointer;
    typedef const value_type*           const_pointer;
    typedef value_type&                 reference;
    typedef const value_type&           const_reference;
    typedef std::size_t                 size_type;
    typedef std::ptrdiff_t              difference_type;

    // rebind allocator to type U
    template <class U>
    struct rebind {
        typedef YourAlloc<U> other;
    };

    // return address of values
    pointer address(reference value) const {
        return &value;
    }
    const_pointer address(const_reference value) const {
        return &value;
    }

    /* constructors and destructor
    * - nothing to do because the allocator has no state
    */
    YourAlloc() throw() {
    }
    YourAlloc(const YourAlloc&) throw() {
    }
    template <class U>
    YourAlloc(const YourAlloc<U>&) throw() {
    }
    ~YourAlloc() throw() {
    }

    // return maximum number of elements that can be allocated
    size_type max_size() const throw() {
        return std::numeric_limits<std::size_t>::max() / sizeof(T);
    }

    // allocate but don't initialize num elements of type T
    pointer allocate(size_type num, const void* = 0) {
        return (pointer)je_malloc(num * sizeof(T));
    }

    // initialize elements of allocated storage p with value value
    void construct(pointer p, const T& value) {
        // initialize memory with placement new
        new((void*)p)T(value);
    }

    // destroy elements of initialized storage p
    void destroy(pointer p) {
        // destroy objects by calling their destructor
        p->~T();
    }

    // deallocate storage p of deleted elements
    void deallocate(pointer p, size_type num) {
        je_free(p);
    }
};

// return that all specializations of this allocator are interchangeable
template <class T1, class T2>
bool operator== (const YourAlloc<T1>&,
    const YourAlloc<T2>&) throw() {
    return true;
}
template <class T1, class T2>
bool operator!= (const YourAlloc<T1>&,
    const YourAlloc<T2>&) throw() {
    return false;
}

int main()
{
    std::vector<int, YourAlloc<int>> vector;

    return 0;
}

代码是从here

复制的