c# यूनिटी बोर्ड गेम ऐ के कारण मेमोरी लीक




multithreading unity3d (4)

मैं टिक टीएसी को पैर की अंगूठी के समान एक बोर्ड गेम बना रहा हूं, और मैंने उस गेम को खेलने के लिए एक ए बनाया है। ऐ बहुत सीपीयू गहन है, इसलिए मैंने इसे अपने ही धागे पर रखने का फैसला किया। मैं multithreading करने के लिए इस प्लगइन का उपयोग कर रहा हूं: https://www.assetstore.unity3d.com/en/#!/content/15717

मेरे पास यह IEnumerator है:

static IEnumerator executeAITurn(Turn turn) {
    Vector2[] move = mctsManager.mcts(new State(sections, null, turn), AIIterations)[0, 0].metaData.lastMove;

    yield return Ninja.JumpToUnity;

    input(move, true);

    yield return Ninja.JumpBack;

    Debug.Log("DONE!");
}

और मैं इसे का उपयोग कर चलाते हैं

gameManager.StartCoroutineAsync(executeAITurn((AITurn == Turn.X) ? Turn.O : Turn.X));

आम तौर पर जब मैं निष्पादित करता हूं आम तौर पर यह समस्याओं के बिना सामान्य रूप से काम करता है, लेकिन किसी कारण के कारण कभी-कभी मैं इसे चलाता हूं, ऐसा करता है, लेकिन कार्य प्रबंधक में मेरी मेमोरी सिर्फ 30 mb / sec की तरह बढ़ जाती है। स्मृति 1000 एमबी के लिए सभी तरह से बढ़ जाती है और गेम वास्तव में धीमा हो जाता है जब मैं खेल मोड को बंद करता हूं, तो स्मृति कभी-कभी बढ़ती रहती है या बस यह रुक जाती है जहां यह है। स्मृति को मुक्त करने के लिए मुझे कार्य प्रबंधक के माध्यम से एकता समाप्त करना होगा।

एक बात मैंने कोशिश की है जो लूप के लिए नियमित रूप से अग्रक लूप की जगह लेता है और इससे मदद मिलती है जिस दर पर स्मृति बढ़ रही थी वह बहुत कम हुई (शुरू में यह लगभग 100 एमबी / सेक में बढ़ेगी)।

किसी भी सहायता की सराहना की जाएगी।

यहाँ executeAITurn में शामिल कुछ कोड है:

mctsManager कक्षा: https://pastebin.com/yzeHrY2p

इनपुट फ़ंक्शन: https://pastebin.com/8f2hzZws


यह एक कचरा संग्रहण मुद्दे की तरह अधिक लगता है। मैंने एमसीटीएस के लिए अपना कोड देखा और निम्नलिखित पर गौर किया।

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {

यह आपके पहले कोड से गायब थी, सी # इनपुट फ़ंक्शन असल में, यह एक अद्यतन फ़ंक्शन को लागू कर रहा है। जैसा कि आप देख सकते हैं, यह कहते हैं कि अपडेट फ़ंक्शन को प्रति फ्रेम एक बार कहा जाता है। इस https://unity3d.com/learn/tutorials/topics/performance-optimization/optimizing-garbage-collection-unity-games का संदर्भ लें

मैं एक कैश की सिफारिश करेगा

उम्मीद है की वो मदद करदे।


पहले कार्य प्रबंधक भी स्मृति मांग के प्रदर्शन को मापने के लिए एक वैध उपकरण नहीं है। आंकड़े उच्च और रास्ते कम करने के लिए दोनों तरह से हो सकते हैं। संभवतः एक ही समय में

दूसरे, कचरा कलेक्टर की प्रकृति की माप कितनी मेमोरी वास्तव में बहुत मुश्किल है इसका इस्तेमाल करता है। जीसी जितना संभव हो उतना कम से कम चलाने की कोशिश करेगा। और अगर यह केवल आवेदन समापन पर चलता है, तो यह आदर्श मामला है।

यदि आपने इसे बाहर रखा है, तो यह उन दो सामान्य गलत धारणाओं में से एक है, आमतौर पर एक प्रबंधित रनटाइम में स्मृति लीक एक बात है: आप एक संग्रह (ऐरे, सूची <>, शब्दकोश <,>) में कुछ जोड़ते हैं लेकिन इसे फिर से बाहर करना भूल जाते हैं । यह एकमात्र तरीका है जो मेमोरी रिसाव हो सकता है। विशेष रूप से जीसी में ऐसा होता है कि हम कभी भी "मैं स्मृति को मुक्त करने के लिए भूल गया" समस्या में फिर से नहीं चला

एक दुर्लभ मामला निपटान के साथ गलती है। यदि आप सीधे umanaged संसाधनों को सौंपते हैं तो आपको पहले अपना अंतिम रूप लिखना चाहिए, दूसरा निपटाना अगर आप किसी भी तरह से संभालते हैं जो अजीब तरीके से लागू होता है, तो हमेशा भी अमान्य हो सकता है, भले ही आपके सभी विच्छेदन () में मौजूद उदाहरण के लिए आदेश रिले हो। कभी अंतिम रूप से कोई आदेश रिले न करें, जो कि उदाहरण और जीसी के बीच है।


इस प्रश्न के सभी उत्तर वास्तव में मुझे बेहतर ढंग से स्मृति को प्रबंधित करने में मदद मिली हैं मैंने सोचा था कि मैं एक ही सवाल में हर चीज से बड़े चीजों का सार होगा।

सबसे पहले, रॉबर्ट लिविंग्स्टोन के उत्तर में उन्होंने इस लेख का उल्लेख किया है: https://unity3d.com/learn/tutorials/topics/performance-optimization/optimizing-garbage-collection-unity-games , जो वाकई सब कुछ शामिल करता है जो मेरी मदद करता था मेरी इच्छा है कि मैंने पहले ही पढ़ा था।

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

मेमोरी में सबसे बड़ी मदद शायद सूची को साफ कर रहा था, क्योंकि उन्हें बहुत बार बनाया जा रहा था, लेकिन मैं उन्हें कचरा बनाने के लिए बहुत से कचरा पैदा करने की कोशिश नहीं कर रहा था। (यही कारण है कि मैंने उस व्यक्ति को इनाम दिया जो क्लियरिंग सूचियों का उल्लेख करता है)

वैसे भी, सभी मदद के लिए धन्यवाद


जब मेमोरी लीक से निपटते हैं, तो आपको सावधान रहना होगा, क्योंकि आपके आवेदन में हर कदम महत्वपूर्ण है।

शुरुआती के लिए, आपके पास प्रत्येक लूप, स्मृति में वृद्धि का कारण हो सकता है शब्दकोशों और हैश तालिका के साथ काम करने के लिए छोरों का प्रयोग करने से पीछे की कोशिश करें, यह आपको 'आउट-ऑफ-ऑर्डर' डेटा के साथ खर्च करेगा, क्योंकि यह हैश कोड की तुलना कर रहा है, लेकिन मुझे नहीं लगता कि आपको अपने डेटा के लिए एक निश्चित ऑर्डर चाहिए खेल।

स्पष्टीकरण: यदि आप अपने सरणी के सटीक आकार को जानते हैं, तो आपके पास सरणी की प्रत्येक सूची, ArrayList का उपयोग करें यदि आप सूची का उपयोग करते हैं, तो उसे शब्दकोश में स्विच करें, यदि सूची का प्रकार आपको जाना जाता है या यदि हां टैब नहीं है इस तरह से आप जानकारी को कुंजी-मूल्य के तरीके में प्राप्त करने में समर्थ होंगे, जो तेज और प्रदर्शन को बेहतर बनाता है

दूसरा, सिंटैक्स का उपयोग करने का प्रयास करें जब कभी आप किसी नए ऑब्जेक्ट को इन्स्तांत करते हैं, तो यह आपको वस्तुओं के निपटान के लिए iDisposable इंटरफ़ेस को प्रभावी ढंग से लागू करने में मदद करेगा

तीसरा, अपने कोड को मुक्केबाजी चर से जितना हो सके रोकें! मुक्केबाजी मतलब है, ढेर में बजाय एक ढेर में एक मूल्य प्रकार के भंडारण की प्रक्रिया है, इसलिए स्टैक में आप केवल चर के स्थान का एक संदर्भ देते हैं

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







memory-leaks