2012-03-01 40 views
10

Làm thế nào là nó có thể sử dụng container ++ STL C với jemalloc (hoặc bất kỳ malloc thi khác)?C++ STL với jemalloc

Có đơn giản như bao gồm jemalloc/jemalloc.h? Hoặc tôi nên viết một phân bổ cho họ?

Chỉnh sửa: Ứng dụng tôi đang phân bổ và giải phóng các đối tượng tương đối nhỏ trong suốt thời gian tồn tại của nó. Tôi muốn thay thế cấp phát mặc định, bởi vì điểm chuẩn cho thấy rằng ứng dụng không vượt quá 2 lõi. Profiling cho thấy rằng nó đang chờ phân bổ bộ nhớ, đó là những gì gây ra các vấn đề mở rộng quy mô. Theo tôi hiểu, jemalloc sẽ trợ giúp về điều đó.


Tôi muốn thấy một giải pháp, đó là nền tảng trung lập như các ứng dụng phải làm việc trên cả Linux và Windows. (Liên kết chống lại một thực hiện khác nhau rất dễ dàng trong Linux, nhưng nó rất cứng trên Windows như xa như tôi biết.)

Trả lời

6

C++ cho phép bạn thay thếoperator new. Nếu thay thế operator new cuộc gọi je_malloc, sau đó std::allocator sẽ gián tiếp gọi je_malloc và ngược lại tất cả các vùng chứa tiêu chuẩn sẽ.

Đây là cách tiếp cận đơn giản nhất. Viết một trình phân bổ tùy chỉnh yêu cầu viết toàn bộ một lớp. Thay thế malloc có thể không đủ (không đảm bảo rằng không được thay thế operator new cuộc gọi malloc) và có những rủi ro được ghi nhận trước đó bởi Adrian McCarthy

1

Có thể có vấn đề như các nhà thầu sẽ không được gọi. Bạn có thể sử dụng tùy chọn differnt của operator new (có tùy chọn nhiều hơn chỉ new) mà chỉ có thể cấp phát bộ nhớ mà không gọi constructor, hoặc gọi các nhà xây dựng trong bộ nhớ đã được phân bổ. http://www.cplusplus.com/reference/std/new/operator%20new%5B%5D/

3

Viết trình phân bổ sẽ là giải pháp dễ nhất, vì stl được thiết kế để có các bộ phân bổ hoán đổi cho nhau. Đây sẽ là con đường dễ nhất.

Một số dự án chơi trò chơi cố gắng thực hiện thay thế malloc để thay thế mallocnew s do thư viện đồng hành của trình biên dịch cung cấp. Đó là dễ bị tất cả các loại vấn đề bởi vì bạn sẽ chỉ dựa vào chi tiết thực hiện cụ thể của trình biên dịch của bạn và thư viện nó thường sử dụng. Con đường này đầy nguy hiểm.

Một số nguy hiểm của việc cố gắng thay thế malloc toàn cầu:

  • tĩnh để khởi tạo đã hạn chế đảm bảo trong C++. Không có cách nào để đảm bảo việc thay thế cấp phát được khởi tạo trước khi người gọi đầu tiên cố gắng sử dụng nó, trừ khi bạn cấm các đối tượng tĩnh có thể cấp phát bộ nhớ. Thời gian chạy không có vấn đề này, vì trình biên dịch và thời gian chạy làm việc cùng nhau để đảm bảo thời gian chạy được khởi tạo hoàn toàn trước khi khởi tạo bất kỳ thống kê nào.
  • Nếu bạn liên kết động với thư viện thời gian chạy, thì không có cách nào để đảm bảo một số mã của thư viện thời gian chạy không bị ràng buộc với việc triển khai của chính nó. Cố gắng sửa đổi thư viện thời gian chạy của trình biên dịch có thể dẫn đến các vấn đề cấp phép khi phân phối lại ứng dụng của bạn.
  • Tất cả các phương pháp khác phân bổ có thể không phải lúc nào cuối cùng dựa vào malloc. Ví dụ, một thực hiện new có thể bỏ qua malloc cho phân bổ lớn và trực tiếp gọi hệ điều hành để cấp phát bộ nhớ. Điều đó yêu cầu theo dõi để đảm bảo phân bổ như vậy không vô tình được gửi đến số free thay thế.

Tôi tin rằng Chromium và Firefox đã thay thế trình phân bổ, nhưng chúng chơi một số thủ thuật bẩn và có thể phải cập nhật cách tiếp cận của họ như trình biên dịch, trình liên kết và thời gian chạy.

+0

tôi cập nhật câu hỏi của tôi để trả lời của bạn. Loại vấn đề nào là thay thế 'mới'? – KovBal

+0

Nếu bạn chỉ đang cố gắng thay thế 'mới' bằng các shenanigans C++ thông thường, bạn có thể nhận được bằng. Đó là khi mọi người cố gắng thay thế 'malloc' trong toàn bộ chương trình mà thực sự là lông. –

+0

Đây chính xác là những gì tôi muốn làm: thay thế 'malloc' trong toàn bộ chương trình. Nhưng tôi không muốn viết thực hiện của riêng tôi; Tôi chỉ muốn sử dụng một cái khác (được thử nghiệm tốt). – KovBal

6

Nếu bạn muốn thay thế malloc ở khắp mọi nơi trong chương trình của bạn (mà tôi muốn và cũng có vẻ là giải pháp hợp lý duy nhất), thì tất cả những gì bạn phải làm là liên kết với nó.

Vì vậy, nếu bạn sử dụng gcc sau đó tất cả các bạn phải làm là:

g++ yourprogram.cpp -ljemalloc 

Nhưng, nếu đó là không thể, sau đó bạn phải sử dụng jemalloc qua chức năng khác ví dụ je_mallocje_free và sau đó bạn phải quá tải các toán tử newdelete.

Không cần bao gồm bất kỳ tiêu đề nào nếu bạn không sử dụng các tính năng dành riêng cho việc triển khai (thống kê, chủ yếu).

1

Làm cho chính bạn cấp phát. Làm như thế này:

#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; 
} 

Mã này được sao chép từ here

+0

Một người cấp phát có thể là một ý tưởng hay. Nếu hầu hết dữ liệu được lưu trữ trong các thùng chứa nhận thức phân bổ, thì đó là một giải pháp rất tốt. – KovBal

Các vấn đề liên quan