2012-05-08 12 views
9

का उपयोग करते समय std :: string/std :: वेक्टर सदस्य चर के साथ काम करना मैं एक प्रदर्शन महत्वपूर्ण अनुप्रयोग लिख रहा हूं जिसमें मैं आदेश देने के लिए समान प्रकार की वस्तुओं की बड़ी संख्या बना रहा हूं। मैं स्मृति आवंटित करने के लिए boost::singleton_pool का उपयोग कर रहा हूं। अंततः मेरी कक्षा इस तरह दिखती है।बूस्ट :: सिंगलटन_पूल

class MyOrder{ 
    std::vector<int> v1_; 
    std::vector<double> v2_; 

    std::string s1_; 
    std::string s2_; 

public: 
    MyOrder(const std::string &s1, const std::string &s2): s1_(s1), s2_(s2) {} 

    ~MyOrder(){} 

    static void * operator new(size_t size); 
    static void operator delete(void * rawMemory) throw(); 
    static void operator delete(void * rawMemory, std::size_t size) throw(); 

}; 

struct MyOrderTag{}; 
typedef boost::singleton_pool<MyOrderTag, sizeof(MyOrder)> MyOrderPool; 

void* MyOrder:: operator new(size_t size) 
{ 
    if (size != sizeof(MyOrder)) 
     return ::operator new(size); 

    while(true){ 
     void * ptr = MyOrderPool::malloc(); 
     if (ptr != NULL) return ptr; 

     std::new_handler globalNewHandler = std::set_new_handler(0); 
     std::set_new_handler(globalNewHandler); 

     if(globalNewHandler) globalNewHandler(); 
     else throw std::bad_alloc(); 

    } 
} 

void MyOrder::operator delete(void * rawMemory) throw() 
{ 
    if(rawMemory == 0) return; 
    MyOrderPool::free(rawMemory); 
} 

void MyOrder::operator delete(void * rawMemory, std::size_t size) throw() 
{ 
    if(rawMemory == 0) return; 
    if(size != sizeof(Order)) { 
     ::operator delete(rawMemory); 
    } 
    MyOrderPool::free(rawMemory); 
} 

मैं हाल ही में बढ़ावा :: singleton_pool का उपयोग करने में प्रदर्शन लाभ के बारे में question तैनात। जब मैंने boost::singleton_pool और डिफ़ॉल्ट आवंटक के प्रदर्शन की तुलना की, तो मुझे कोई प्रदर्शन लाभ नहीं मिला। जब किसी ने इंगित किया कि मेरी कक्षा के प्रकार std :: स्ट्रिंग के सदस्य हैं, जिनके आवंटन को मेरे कस्टम आवंटक द्वारा शासित नहीं किया जा रहा था, मैंने std :: string variables को हटा दिया और परीक्षणों को फिर से चलाया। इस बार मैंने एक काफी प्रदर्शन बढ़ावा देखा।

  1. अब, मेरे वास्तविक आवेदन में, मैं समय std :: string और std :: vector के सदस्य चर से छुटकारा नहीं पा सकता हूं। क्या मुझे अपने std :: string और std :: vector सदस्य चर के साथ boost::pool_allocator का उपयोग करना चाहिए?

  2. बढ़ावा :: pool_allocator एक अंतर्निहित std :: singleton_pool से स्मृति आवंटित करता है। क्या इससे कोई फर्क नहीं पड़ता कि अलग-अलग सदस्य चर (मेरे पास MyOrder क्लास में एक से अधिक std :: स्ट्रिंग/std :: वेक्टर प्रकार हैं। इसके अलावा मैं MyOrder के अलावा अन्य कक्षाओं के लिए पूल नियोजित कर रहा हूं जिसमें std :: string/std :: वेक्टर प्रकार शामिल हैं सदस्यों के रूप में भी) एक ही मेमोरी पूल का उपयोग करें? अगर ऐसा होता है, तो मैं कैसे सुनिश्चित कर सकता हूं कि वे एक या दूसरे तरीके से करते हैं?

+1

कॉन्स और अपने कन्स्ट्रक्टर में उपयोग करें। –

+1

@EternalLearner गुड प्वाइंट। यह एक प्रति को रोक देगा। किया हुआ। – sank

+0

क्या वास्तव में std :: weak_ptr या std :: स्ट्रिंग्स में कुछ का उपयोग करने के लिए थोड़ा और उचित नहीं होगा? निजी आंतरिक प्रतियों के संदर्भ लेना हमेशा मुझे गलत लगता है। भले ही आप प्रतिलिपि को रोक दें ... –

उत्तर

2
  1. अब, मेरे वास्तविक आवेदन में, मैं समय एसटीडी के सदस्य चर :: स्ट्रिंग और std :: वेक्टर छुटकारा नहीं मिल सकता है। क्या मुझे अपने std :: स्ट्रिंग और std :: वेक्टर सदस्य चर के साथ boost :: pool_allocator का उपयोग करना चाहिए?

मैं बढ़ावा के उस हिस्से में देखा कभी नहीं किया है, लेकिन आप जहां तार उनके स्मृति को आबंटित बदलना चाहते हैं, तो आप संकलन समय पर std::basic_string<> के लिए एक अलग संभाजक पारित करने के लिए की जरूरत है। और कोई रास्ता नहीं है। हालांकि, आपको इसके डाउनसाइड्स से अवगत होना चाहिए: उदाहरण के लिए, ऐसे स्ट्रिंग std::string को अब असाइन करने योग्य नहीं होंगे। (हालांकि रोजगार c_str() काम करेगा, यह एक छोटे से प्रदर्शन जुर्माना लगा सकता है।)

  1. बढ़ावा :: pool_allocator एक अंतर्निहित std :: singleton_pool से स्मृति आवंटित करता है। क्या इससे कोई फर्क नहीं पड़ता कि अलग-अलग सदस्य चर (मेरे पास MyOrder क्लास में एक से अधिक std :: स्ट्रिंग/std :: वेक्टर प्रकार हैं। इसके अलावा मैं MyOrder के अलावा अन्य कक्षाओं के लिए पूल नियोजित कर रहा हूं जिसमें std :: string/std :: वेक्टर प्रकार शामिल हैं सदस्यों के रूप में भी) एक ही मेमोरी पूल का उपयोग करें? अगर ऐसा होता है, तो मैं कैसे सुनिश्चित कर सकता हूं कि वे एक या दूसरे तरीके से करते हैं?

पूल का पूरा बिंदु इसमें एक से अधिक ऑब्जेक्ट रखना है। अगर यह सिर्फ एक था, तो आपको पूल की आवश्यकता नहीं होगी। तो, हाँ, आप कई ऑब्जेक्ट्स को इसमें डाल सकते हैं, जिसमें कई std::string ऑब्जेक्ट्स की गतिशील स्मृति शामिल है।

चाहे यह आपको कोई प्रदर्शन लाभ प्राप्त करता है, हालांकि, देखा जाना बाकी है। आप पूल का उपयोग करते हैं क्योंकि आपके पास यह मानने के कारण हैं कि यह सामान्य प्रयोजन आवंटक से अधिक तेज़ है (इसे उपयोग करने के बजाए, उदाहरण के लिए, किसी विशेष क्षेत्र से साझा स्मृति जैसे स्मृति आवंटित करें)। आम तौर पर ऐसा पूल तेज होता है क्योंकि यह आवंटित वस्तुओं के आकार पर धारणाएं कर सकता है।यह निश्चित रूप से आपके MyOrder वर्ग के लिए सच है: इसकी वस्तुओं का हमेशा एक ही आकार होता है, अन्यथा (बड़े व्युत्पन्न कक्षाएं) आप उन्हें पूल में आवंटित नहीं करेंगे।
std::string के लिए यह अलग है। एक गतिशील आवंटित स्ट्रिंग क्लास का उपयोग करने का पूरा बिंदु यह है कि यह किसी भी स्ट्रिंग लम्बाई को अनुकूलित करता है। इसके लिए आवश्यक मेमोरी भाग अलग-अलग आकार के होते हैं (अन्यथा आप इसके बजाय चार सरणी कर सकते हैं)। मुझे पूल आवंटन के लिए सामान्य उद्देश्य उद्देश्य आवंटक में सुधार करने के लिए थोड़ा कमरा दिखाई देता है।


एक तरफ ध्यान दें पर: आपके अतिभारित operator new() रिटर्न वैश्विक एक लागू करने का परिणाम है, लेकिन अपने operator delete बस कुछ भी है कि पूल के free() करने के लिए अपने रास्ते आने से गुजरता है। यह मेरे लिए बहुत संदिग्ध लगता है।

+0

मैंने अपने प्रश्न में "विभिन्न चर" पर विस्तार से बताया। – sank

+0

मैं प्रभावी सी ++ (तीसरा संस्करण) आइटम 49 और 51 में वर्णित सटीक प्रक्रिया का पालन कर रहा हूं (http://my.safaribooksonline.com/0321334876) – sank

+1

@sank: मुझे अभी भी एक प्रतिलिपि प्राप्त करने का समय नहीं मिला है पुस्तक के बारे में और इसे देखो, लेकिन मैंने स्कॉट मेयर्स की तरफ से एक लिंक निकाल दिया, और उसने मुझे लिखा कि (मैं इसे जर्मन से फिर से अनुवाद कर रहा हूं) "पेज 255 पर 'ऑपरेटर डिलीट' के दो संस्करण हैं। पहला गैर-सदस्य संस्करण है, और यह वह है जिसकी उन्होंने प्रतिलिपि बनाई है। दूसरा संस्करण सदस्य संस्करण है और वह वह है जिसे उसने कॉपी किया था। इसमें वह परीक्षण शामिल है जिसे आपने माना था: [...] 'if (size! = आकार (आधार)) '[...]"। तो आप वापस जाना और इसे और अधिक अच्छी तरह से पढ़ना चाह सकते हैं। HTH! – sbi

1

std::string/std::vector के लिए एक कस्टम आवंटक का उपयोग करके आपकी कक्षा में काम करेगा (आवंटन मानना ​​सही है) - लेकिन केवल प्रदर्शन परीक्षण देखेंगे कि क्या आपको वास्तव में कोई लाभ दिखाई देता है।

वैकल्पिक रूप से, अगर आप जानते हैं कि std::string/std::vector ऊपरी सीमा है, यदि आप एक std::array चारों ओर एक पतली आवरण को लागू कर सकता है (या सामान्य सरणी अगर आप C++ 11 नहीं है) यह प्रतिस्थापन में एक बूंद है कि बनाता है ।

यहां तक ​​कि अगर आकार असीम है, अगर वहाँ कुछ आकार कि सबसे मूल्यों की तुलना में कम हो सकता है, आप ऊपर std::array आधारित कार्यान्वयन का विस्तार कर सकता है अपने जमा संभाजक साथ आवंटन अगर वे भरने से विस्तार योग्य होना है।