2011-10-22 12 views
13

मान लीजिए कि मेरे पास एक कन्स्ट्रक्टर के साथ मेमोरी पूल ऑब्जेक्ट है जो मेमोरी पीआरटी और आकार एन के बड़े हिस्से में पॉइंटर लेता है। अगर मैं कई यादृच्छिक आवंटन करता हूं और विभिन्न आकारों के विघटन करता हूं तो मुझे इस तरह की स्थिति में स्मृति मिल सकती है कि मैं नहीं कर सकता स्मृति में एक एम बाइट ऑब्जेक्ट को आवंटित करें, भले ही बहुत कुछ हो! साथ ही, मैं स्मृति को कॉम्पैक्ट नहीं कर सकता क्योंकि इससे उपभोक्ताओं पर एक खतरनाक सूचक बन जाएगा। इस मामले में एक विखंडन कैसे हल करता है?मेमोरी पूल में विखंडन के साथ काम करना?

+0

क्या आप एक ऑपरेटिंग सिस्टम को लागू करने की कोशिश कर रहे हैं या कम से कम इसका एक हिस्सा? सामान्य आवंटन पर स्मृति पूल को प्राथमिकता देने का एकमात्र कारण यह है कि सामान्य आवंटन विखंडन के साथ होता है। – Dani

उत्तर

8

मैं केवल 2 सेंट जोड़ना चाहता था क्योंकि किसी और ने यह नहीं बताया कि आपके विवरण से ऐसा लगता है कि आप मानक ढेर आवंटक (i।ई जब हम malloc() या ऑपरेटर को कॉल करते हैं तो हम सभी पहले से ही क्या उपयोग करते हैं)।

एक ढेर वास्तव में ऐसी वस्तु है, जो वर्चुअल मेमोरी मैनेजर पर जाती है और स्मृति के बड़े हिस्से (जिसे आप "पूल" कहते हैं) के लिए पूछते हैं। इसके बाद विभिन्न आकार के हिस्सों को आवंटित करने और उन्हें मुक्त करने के सबसे प्रभावी तरीके से निपटने के लिए सभी प्रकार के अलग-अलग एल्गोरिदम होते हैं। इसके अलावा, कई लोगों ने वर्षों में इन एल्गोरिदम को संशोधित और अनुकूलित किया है। लंबे समय तक विंडोज़ कम-विखंडन ढेर (एलएफएच) नामक एक विकल्प के साथ आया था जिसे आप मैन्युअल रूप से सक्षम करना चाहते थे। विस्टा एलएफएच से शुरू होने से डिफ़ॉल्ट रूप से सभी ढेर के लिए उपयोग किया जाता है।

ढेर सही नहीं हैं और जब वे ठीक से उपयोग नहीं किए जाते हैं तो वे निश्चित रूप से प्रदर्शन को कम कर सकते हैं। चूंकि ओएस विक्रेता संभावित रूप से हर परिदृश्य की उम्मीद नहीं कर सकते हैं जिसमें आप ढेर का उपयोग करेंगे, उनके ढेर प्रबंधकों को "औसत" उपयोग के लिए अनुकूलित किया जाना चाहिए। लेकिन अगर आपके पास एक आवश्यकता है जो एक नियमित ढेर (यानी कई वस्तुओं, अलग-अलग आकार ....) के लिए आवश्यकताओं के समान है, तो आपको केवल ढेर का उपयोग करने पर विचार करना चाहिए और इसे पुन: पेश नहीं करना चाहिए क्योंकि संभावना है कि आपका कार्यान्वयन ओएस से कम होगा पहले से ही आपके लिए प्रदान करता है।

स्मृति आवंटन के साथ, केवल एक ही समय में आप केवल ढेर का उपयोग करके प्रदर्शन प्राप्त नहीं कर सकते हैं, यह कुछ अन्य पहलू (आवंटन ओवरहेड, आवंटन जीवनकाल ....) छोड़कर आपके विशिष्ट अनुप्रयोग के लिए महत्वपूर्ण नहीं है।

उदाहरण के लिए, हमारे आवेदन में हमें 1KB से कम के कई आवंटन की आवश्यकता थी, लेकिन इन आवंटन का उपयोग केवल बहुत ही कम समय (मिलीसेकंड) के लिए किया जाता था। ऐप को अनुकूलित करने के लिए, मैंने बूस्ट पूल लाइब्रेरी का उपयोग किया लेकिन इसे विस्तारित किया ताकि मेरा "आवंटक" वास्तव में बूस्ट पूल ऑब्जेक्ट्स का संग्रह हो, प्रत्येक एक विशिष्ट आकार को 16 बाइट्स से 1024 तक (4 के चरणों में) आवंटित करने के लिए जिम्मेदार होता है। यह लगभग सभी वस्तुओं (ओ (1) जटिलता) आवंटन/इन वस्तुओं से मुक्त प्रदान करता है लेकिन पकड़ यह है कि ए) स्मृति उपयोग हमेशा बड़ा होता है और कभी भी नीचे नहीं जाता है, भले ही हमारे पास आवंटित एक ऑब्जेक्ट न हो, बी) बूस्ट पूल कभी नहीं यह स्मृति को मुक्त करता है (कम से कम उस मोड में जिसे हम इसका उपयोग कर रहे हैं) ताकि हम केवल उन वस्तुओं के लिए इसका उपयोग कर सकें जो बहुत लंबे समय तक नहीं टिकते हैं।

तो सामान्य मेमोरी आवंटन का कौन सा पहलू आप अपने ऐप में छोड़ने को तैयार हैं?

+1

उत्कृष्ट स्पष्टीकरण धन्यवाद। – user805547

6

सिस्टम के आधार पर ऐसा करने के कुछ तरीके हैं।

पहली जगह में विखंडन से बचने की कोशिश करें, यदि आप 2 की शक्तियों में ब्लॉक आवंटित करते हैं तो आपके पास इस तरह के विखंडन के कारण कम संभावना है। इसके आस-पास के कुछ अन्य तरीके हैं लेकिन यदि आप कभी भी इस राज्य तक पहुंचते हैं तो आप उस बिंदु पर ओओएम करते हैं क्योंकि स्मृति के लिए पूछे जाने वाले प्रक्रिया को मारने के अलावा इसे संभालने का कोई नाजुक तरीका नहीं है, जब तक आप स्मृति आवंटित नहीं कर लेते हैं, अपने आवंटन क्षेत्र के रूप में वापस लौट रहा है।

एक और तरीका पॉइंटर्स को आपके डेटा के पॉइंटर्स को पास करना है (उदा: int **)। फिर आप प्रोग्राम के नीचे मेमोरी को पुनर्व्यवस्थित कर सकते हैं (थ्रेड सुरक्षित मैं उम्मीद करता हूं) और आवंटन को कॉम्पैक्ट कर सकता हूं ताकि आप नए ब्लॉक आवंटित कर सकें और डेटा को पुराने ब्लॉक से रख सकें (एक बार जब सिस्टम इस स्थिति में हो जाता है हालांकि यह भारी ओवरहेड बन जाता है लेकिन शायद ही कभी सामाप्त करो)।

मेमोरी "बिनिंग" मेमोरी के तरीके भी हैं ताकि आपके पास संगत पृष्ठ हों, उदाहरण के लिए केवल 1 पृष्ठ को केवल 512 और उससे कम आवंटन के लिए समर्पित करें, दूसरा 1024 और उससे कम, आदि के लिए ... यह निर्णय लेना आसान बनाता है कौन सा बिन उपयोग करने के लिए और सबसे बुरे मामले में आप अगले उच्चतम बिन से विभाजित हो जाते हैं या निचले बिन से विलय करते हैं जो कई पृष्ठों में विखंडन का मौका कम कर देता है।

0
  • आवंटन की सूची के रूप में संचालित करने के लिए पूल लिखें, फिर आप आवश्यकतानुसार विस्तार और नष्ट कर सकते हैं। यह विखंडन को कम कर सकता है।
  • और/या आवंटन स्थानांतरण (या चाल) समर्थन लागू करें ताकि आप सक्रिय आवंटन को कॉम्पैक्ट कर सकें। ऑब्जेक्ट/धारक को आपकी सहायता करने की आवश्यकता हो सकती है, क्योंकि पूल को यह नहीं पता होना चाहिए कि प्रकारों को कैसे स्थानांतरित करना है। यदि पूल को संग्रह प्रकार के साथ प्रयोग किया जाता है, तो कॉम्पैक्टिंग/ट्रांसफर को पूरा करना कहीं अधिक आसान होता है।
3

आपके द्वारा आवंटित ऑब्जेक्ट्स के लिए object pools लागू करने के लिए आपके मेमोरी आवंटक को बदलने की आवश्यकता के बिना काफी कम विखंडन ड्राइव करेगा।

1

यह जानना उपयोगी होगा कि आप वास्तव में क्या करने की कोशिश कर रहे हैं, क्योंकि इससे निपटने के कई तरीके हैं।
लेकिन, पहला सवाल यह है: क्या यह वास्तव में हो रहा है, या यह एक सैद्धांतिक चिंता है?

ध्यान में रखना एक बात यह है कि आपके पास सामान्य रूप से भौतिक स्मृति की तुलना में बहुत अधिक वर्चुअल मेमोरी एड्रेस स्पेस उपलब्ध है, इसलिए जब भी भौतिक स्मृति खंडित होती है, तब भी बहुत अधिक वर्चुअल मेमोरी मेमोरी होती है। (बेशक, भौतिक स्मृति नीचे बंद है लेकिन आपका कोड यह नहीं देखता है।)

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

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