2012-03-01 16 views
10

जेमलोक (या कोई अन्य malloc कार्यान्वयन) के साथ सी ++ एसटीएल कंटेनरों का उपयोग करना संभव है?सी ++ एसटीएल जेमलोक

क्या यह jemalloc/jemalloc.h शामिल है जितना आसान है? या मुझे उनके लिए आवंटन लिखना चाहिए?

संपादित करें: मैं आवंटन पर काम कर रहा हूं और अपने जीवनकाल में अपेक्षाकृत छोटी वस्तुओं को मुक्त करता हूं। मैं डिफ़ॉल्ट आवंटक को प्रतिस्थापित करना चाहता हूं, क्योंकि बेंचमार्क से पता चला है कि एप्लिकेशन 2 कोर से अधिक नहीं है। प्रोफाइलिंग ने दिखाया कि यह स्मृति आवंटन की प्रतीक्षा कर रहा था, यही वजह है कि स्केलिंग के मुद्दों का कारण बन गया। जैसा कि मैं समझता हूं, jemalloc उसमें सहायता करेगा।


मैं एक समाधान देखना चाहते हैं, कि मंच के तटस्थ के रूप में आवेदन दोनों लिनक्स और विंडोज पर काम करने की है। (लिनक्स के तहत एक अलग कार्यान्वयन के खिलाफ लिंक करना आसान है, लेकिन जहां तक ​​मुझे पता है विंडोज़ पर यह बहुत मुश्किल है।)

उत्तर

6

सी ++ आपको operator new को प्रतिस्थापित करने की अनुमति देता है। यदि यह प्रतिस्थापन operator newje_malloc पर कॉल करता है, तो std::allocator अप्रत्यक्ष रूप से je_malloc पर कॉल करेगा, और बदले में सभी मानक कंटेनर होंगे।

यह अब तक का सबसे आसान दृष्टिकोण है। एक कस्टम आवंटक लिखने के लिए एक पूरी कक्षा लिखने की आवश्यकता है। जगह malloc पर्याप्त नहीं हो सकता है, और यह जोखिम एड्रियन मैकार्थी द्वारा जैसा कि पहले उल्लेख

1

रचनाकारों को नहीं कहा जाएगा क्योंकि समस्याएं हो सकती हैं। आप operator new के अलग-अलग विकल्पों का उपयोग कर सकते हैं (केवल new से अधिक विकल्प हैं) जो कन्स्ट्रक्टर को कॉल किए बिना स्मृति आवंटित कर सकते हैं, या कन्स्ट्रक्टर को पहले ही आवंटित मेमोरी में कॉल कर सकते हैं। http://www.cplusplus.com/reference/std/new/operator%20new%5B%5D/

3

एक आवंटन लिखना सबसे आसान समाधान होगा, क्योंकि एसएलएल को विनिमेय आवंटकों के लिए डिज़ाइन किया गया था। यह सबसे आसान रास्ता होगा।

कुछ प्रोजेक्ट्स गेम गेम malloc कार्यान्वयन को malloc और new को संकलक के सहयोगी पुस्तकालय द्वारा प्रदान करने के लिए कार्यान्वयन करने का प्रयास करते हैं। यह सभी प्रकार के मुद्दों के लिए प्रवण है क्योंकि आप अपने कंपाइलर के विशिष्ट कार्यान्वयन विवरण और सामान्य रूप से उपयोग की जाने वाली लाइब्रेरी पर भरोसा करते हैं। यह रास्ता खतरे से भरा हुआ है।

विश्व स्तर पर malloc बदलने का प्रयास करने से कुछ खतरों:

  • स्टेटिक प्रारंभकर्ता क्रम सी में की गारंटी देता है सीमित है ++। पहले कॉलर का उपयोग करने की कोशिश करने से पहले आवंटन प्रतिस्थापन की शुरुआत करने का कोई तरीका नहीं है, जब तक कि आप स्थैतिक ऑब्जेक्ट्स को प्रतिबंधित न करें जो स्मृति आवंटित कर सकें। रनटाइम में यह समस्या नहीं है, क्योंकि संकलक और रनटाइम यह सुनिश्चित करने के लिए एक साथ काम करता है कि किसी भी स्टेटिक्स को शुरू करने से पहले रनटाइम पूरी तरह प्रारंभ हो गया है।
  • यदि आप गतिशील रूप से रनटाइम लाइब्रेरी से लिंक करते हैं, तो यह सुनिश्चित करने का कोई तरीका नहीं है कि कुछ रनटाइम लाइब्रेरी का कोड पहले से ही अपने कार्यान्वयन के लिए बाध्य नहीं है। कंपाइलर की रनटाइम लाइब्रेरी को संशोधित करने का प्रयास करने से आपके एप्लिकेशन को पुनर्वितरण करते समय लाइसेंसिंग समस्याएं हो सकती हैं।
  • आवंटन के सभी अन्य तरीके हमेशा अंततः malloc पर भरोसा नहीं कर सकते हैं। उदाहरण के लिए, new का कार्यान्वयन बड़े आवंटन के लिए malloc को बाईपास कर सकता है और ओएस को स्मृति आवंटित करने के लिए सीधे कॉल कर सकता है। इसके लिए यह सुनिश्चित करने के लिए ट्रैकिंग की आवश्यकता है कि ऐसे आवंटन को free प्रतिस्थापन में गलती से भेजा नहीं गया है।

मेरा मानना ​​है कि क्रोमियम और Firefox दोनों संभाजक प्रतिस्थापित है, लेकिन वे कुछ गंदा चाल खेलते हैं और शायद संकलक, लिंकर, और क्रम Evolve के रूप में उनके दृष्टिकोण को अपडेट करना होगा।

+0

से नकल कर रहा है मैं अपने का जवाब देने के लिए मेरे सवाल का अद्यतन किया गया। 'new' को बदलने के साथ किस तरह के मुद्दे हैं? – KovBal

+0

यदि आप सामान्य सी ++ शेनानिगन्स के साथ 'नया' को प्रतिस्थापित करने की कोशिश कर रहे हैं, तो आप इसे प्राप्त कर सकते हैं। ऐसा तब होता है जब लोग पूरे कार्यक्रम में 'मॉलोक' को प्रतिस्थापित करने का प्रयास करते हैं जो वास्तव में बालों वाली हो जाती है। –

+0

यह वही है जो मैं करना चाहता हूं: पूरे कार्यक्रम में 'malloc' को प्रतिस्थापित करें। लेकिन मैं अपना खुद का कार्यान्वयन लिखना नहीं चाहता; मैं बस एक और (अच्छी तरह से परीक्षण) एक का उपयोग करना चाहता हूँ। – KovBal

6

यदि आप अपने प्रोग्राम में हर जगह malloc को प्रतिस्थापित करना चाहते हैं (जो मैं चाहता हूं और केवल तार्किक समाधान भी दिखता हूं), तो आपको बस इसके खिलाफ लिंक करना होगा।

इसलिए, यदि आप gcc का उपयोग तो तुम सब करने की है:

g++ yourprogram.cpp -ljemalloc 

लेकिन, अगर यह संभव नहीं है, तो आप जैसे अन्य कार्यों के माध्यम से jemalloc उपयोग करने के लिए je_malloc और je_free, और फिर आपको new और delete ऑपरेटरों को अधिभारित करना होगा।

यदि आप कार्यान्वयन-विशिष्ट विशेषताओं (आंकड़े, अधिकतर) का उपयोग नहीं करते हैं तो किसी भी शीर्षलेख को शामिल करने की आवश्यकता नहीं है।

1

खुद संभाजक बनाओ है (कोई गारंटी नहीं है कि गैर प्रतिस्थापित operator new कॉल malloc वहाँ है)। इस तरह कार्य करें:

#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

+0

एक आवंटक एक अच्छा विचार हो सकता है। यदि अधिकांश डेटा आवंटक-जागरूक कंटेनर में संग्रहीत किया जाता है, तो यह एक बहुत अच्छा समाधान है। – KovBal

संबंधित मुद्दे