सौभाग्य से, जैसा कि आपने बताया, COMPACT मोनो एक जेनेशनल GC का उपयोग करता है (माइक्रोसॉफ्ट वालों के विपरीत, जैसे WinMo / WinPhone / XBox, जो सिर्फ एक फ्लैट सूची बनाए रखते हैं)।
यदि आपका गेम सरल है, तो GC को इसे ठीक से संभालना चाहिए, लेकिन यहां कुछ संकेत दिए गए हैं जिन्हें आप देखना चाहते हैं।
समय से पहले अनुकूलन
पहले यह सुनिश्चित कर लें कि इसे ठीक करने की कोशिश करने से पहले यह वास्तव में आपके लिए एक समस्या है।
पूलिंग महंगा संदर्भ प्रकार
आपको उन संदर्भ प्रकारों को पूल करना चाहिए जिन्हें आप या तो अक्सर बनाते हैं, या जिनकी गहरी संरचनाएं हैं। प्रत्येक का एक उदाहरण होगा:
- अक्सर बनाया गया: बुलेट-नर्क गेम
Bullet
में एक ऑब्जेक्ट ।
- गहरी संरचना: एक एआई कार्यान्वयन के लिए निर्णय का पेड़।
आपको Stack
अपने पूल के रूप में (अधिकांश कार्यान्वयनों के विपरीत Queue
) का उपयोग करना चाहिए । इसका कारण यह है क्योंकि Stack
यदि आप किसी वस्तु को पूल में वापस करते हैं और कुछ और इसे तुरंत पकड़ लेता है; यह एक सक्रिय पृष्ठ में होने की अधिक संभावना है - या सीपीयू कैश में भी अगर आप भाग्यशाली हैं। यह सिर्फ इतना छोटा सा तेज है। इसके अलावा हमेशा अपने पूलों को आकार-सीमित करें (यदि आपकी सीमा पार हो गई है तो 'चेकइन की अवहेलना करें')।
उन्हें साफ़ करने के लिए नई सूची बनाने से बचें
List
जब आप वास्तव में इससे मतलब रखते हैं Clear()
तो एक नया निर्माण न करें । आप बैकएंड सरणी का फिर से उपयोग कर सकते हैं और सरणी आवंटन और प्रतियों के भार को बचा सकते हैं। इसी तरह एक सार्थक प्रारंभिक क्षमता के साथ इस सूची को बनाने और बनाने की कोशिश करें (याद रखें, यह एक सीमा नहीं है - बस एक शुरुआती क्षमता) - इसे सटीक होने की आवश्यकता नहीं है, बस एक अनुमान है। यह मूल रूप से किसी भी संग्रह प्रकार पर लागू होना चाहिए - एक को छोड़कर LinkedList
।
जहाँ संभव हो, स्ट्रक्चर एरेज़ (या सूचियाँ) का उपयोग करें
यदि आप उन्हें वस्तुओं के बीच में से गुजरते हैं, तो आप उपयोग की संरचनाओं (या सामान्य रूप से मूल्य प्रकार) से बहुत कम लाभ प्राप्त करते हैं। उदाहरण के लिए, अधिकांश 'अच्छे' कण प्रणालियों में व्यक्तिगत कणों को एक विशाल सरणी में संग्रहित किया जाता है: सरणी और सूचकांक को कण के बजाय चारों ओर से पारित किया जाता है। यह अच्छी तरह से काम करता है इसका कारण यह है कि जब जीसी को सरणी इकट्ठा करने की आवश्यकता होती है तो यह पूरी तरह से सामग्री को छोड़ सकता है (यह एक आदिम सरणी है - यहां कुछ भी नहीं करना है)। तो 10 000 वस्तुओं को देखने के बजाय जीसी को केवल 1 सरणी को देखने की आवश्यकता है: भारी लाभ! फिर, यह केवल मूल्य प्रकारों के साथ काम करेगा ।
रॉयटी के बाद। कुछ व्यवहार्य और रचनात्मक प्रतिक्रिया प्रदान की मुझे लगता है कि मुझे इस पर और विस्तार करने की आवश्यकता है। आपको केवल इस तकनीक का उपयोग करना चाहिए जब आप भारी मात्रा में संस्थाओं (हजारों से हजारों) के साथ काम कर रहे हों। इसके अलावा यह चाहिए एक struct जो हो नहीं होना चाहिए किसी भी संदर्भ प्रकार क्षेत्र होते हैं और एक स्पष्ट टाइप सरणी में जीना चाहिए। उनकी प्रतिक्रिया के विपरीत, हम इसे एक सरणी में रख रहे हैं, जो एक वर्ग में एक क्षेत्र की संभावना है - जिसका अर्थ है कि यह ढेर तक जा रहा है (हम एक ढेर आवंटन से बचने की कोशिश नहीं कर रहे हैं - केवल जीसी काम से बचना)। हम वास्तव में इस तथ्य की परवाह करते हैं कि यह बहुत सारे मूल्यों के साथ स्मृति का एक सन्निहित हिस्सा है जिसे जीसी केवल एक O(1)
ऑपरेशन के बजाय एक O(n)
ऑपरेशन में देख सकता है।
विखंडन होने की संभावना को कम करने के लिए आपको इन सरणियों को अपने एप्लिकेशन स्टार्टअप के पास भी आवंटित करना चाहिए , या जीसी के रूप में अत्यधिक काम करने की कोशिश करता है, ताकि इन टुकड़ों को इधर-उधर करने की कोशिश की जाए, और अंतर्निहित प्रकार के बजाय एक हाइब्रिड लिंक्ड सूची का उपयोग करने पर विचार List
करें। )।
GC.Collect ()
यह निश्चित रूप से पैर में खुद को गोली मारने का सबसे अच्छा तरीका है (देखें: "प्रदर्शन विचार") एक जनरेशनल जीसी के साथ। आप केवल यह बुलाना चाहिए जब आप एक बनाया है चरम कचरा की राशि - और एक उदाहरण है, जहां कि एक मुद्दा हो सकता है सिर्फ तुम्हारे जाने के बाद एक स्तर के लिए सामग्री भरी हुई है - और फिर भी आपको चाहिए शायद ही कलेक्ट पहली पीढ़ी ( ) तीसरी पीढ़ी में वस्तुओं को बढ़ावा देने से रोकने के लिए।GC.Collect(0);
IDisposable और फील्ड नलिंग
जब आप किसी ऑब्जेक्ट की आवश्यकता नहीं करते हैं, तो फ़ील्ड को शून्य करना सार्थक होगा (अधिक-विवश वस्तुओं पर)। इसका कारण यह है कि जीसी कैसे काम करता है, इसके विवरण में: यह केवल उन वस्तुओं को हटाता है जो जड़ नहीं हैं (अर्थात संदर्भित) भले ही उस वस्तु को वर्तमान संग्रह में हटाए जाने के कारण अन्य वस्तुओं को हटा दिया गया हो ( नोट: यह जीसी पर निर्भर करता है स्वाद में उपयोग - कुछ वास्तव में जंजीरों को साफ करते हैं)। इसके अलावा, यदि कोई वस्तु किसी संग्रह से बच जाती है, तो उसे अगली पीढ़ी को तुरंत पदोन्नत कर दिया जाता है - इसका मतलब है कि खेतों में आस-पास पड़ी कोई भी वस्तु एक संग्रह के दौरान प्रचारित हो जाएगी। प्रत्येक क्रमिक पीढ़ी तेजी से इकट्ठा करने के लिए अधिक महंगा है (और अक्सर होता है)।
निम्नलिखित उदाहरण लें:
MyObject (G1) -> MyNestedObject (G1) -> MyFurtherNestedObject (G1)
// G1 Collection
MyNestObject (G2) -> MyFurtherNestedObject (G2)
// G2 Collection
MyFurtherNestedObject (G3)
यदि MyFurtherNestedObject
बहु-मेगाबाइट ऑब्जेक्ट सम्मिलित है, तो आप इसकी गारंटी दे सकते हैं कि जीसी काफी लंबे समय तक इसे नहीं देखेगा - क्योंकि आपने अनजाने में इसे G3 में प्रचारित कर दिया है। इस उदाहरण के साथ विरोध करें:
MyObject (G1) -> MyNestedObject (G1) -> MyFurtherNestedObject (G1)
// Dispose
MyObject (G1)
MyNestedObject (G1)
MyFurtherNestedObject (G1)
// G1 Collection
डिस्पोज़र पैटर्न आपको वस्तुओं को उनके निजी क्षेत्रों को साफ़ करने के लिए कहने के लिए एक पूर्वानुमानित तरीका सेट करने में मदद करता है। उदाहरण के लिए:
public class MyClass : IDisposable
{
private MyNestedType _nested;
// A finalizer is only needed IF YOU CONTROL UNMANAGED RESOURCES
// ~MyClass() { }
public void Dispose()
{
_nested = null;
}
}