गेम में मेमोरी को बेहतर तरीके से मैनेज करें

Android प्लैटफ़ॉर्म पर, सिस्टम ज़्यादा से ज़्यादा सिस्टम मेमोरी (RAM) का इस्तेमाल करने की कोशिश करता है. साथ ही, ज़रूरत पड़ने पर जगह खाली करने के लिए, मेमोरी को ऑप्टिमाइज़ करता है. इन ऑप्टिमाइज़ेशन से आपके गेम पर बुरा असर पड़ सकता है. ऐसा हो सकता है कि गेम धीमा हो जाए या पूरी तरह से बंद हो जाए. इन ऑप्टिमाइज़ेशन के बारे में ज़्यादा जानने के लिए, प्रोसेस के बीच मेमोरी का बंटवारा विषय पढ़ें.

इस पेज पर, कम मेमोरी की वजह से गेम पर पड़ने वाले असर से बचने के तरीके बताए गए हैं.

onTrimMemory() को जवाब देना

सिस्टम, onTrimMemory() का इस्तेमाल करके आपके ऐप्लिकेशन को लाइफ़साइकल इवेंट की सूचना देता है. इससे आपके ऐप्लिकेशन को मेमोरी का इस्तेमाल कम करने का अच्छा मौका मिलता है. साथ ही, लो-मेमोरी किलर (एलएमके) से बंद होने से बचने का मौका मिलता है, ताकि अन्य ऐप्लिकेशन मेमोरी का इस्तेमाल कर सकें.

अगर आपका ऐप्लिकेशन बैकग्राउंड में बंद हो जाता है, तो अगली बार जब उपयोगकर्ता आपका ऐप्लिकेशन लॉन्च करेगा, तो उसे कोल्ड स्टार्ट होने में ज़्यादा समय लगेगा. बैकग्राउंड में जाने पर, मेमोरी का इस्तेमाल कम करने वाले ऐप्लिकेशन के बैकग्राउंड में बंद होने की संभावना कम होती है.

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

Kotlin

class MainActivity : AppCompatActivity(), ComponentCallbacks2 {
    override fun onTrimMemory(level: Int) {
        if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            // Release memory related to UI elements, such as bitmap caches.
        }
        if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
            // Release memory related to background processing, such as by
            // closing a database connection.
        }
    }
}

Java

public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
    public void onTrimMemory(int level) {
        switch (level) {
            if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
                // Release memory related to UI elements, such as bitmap caches.
            }
            if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
                // Release memory related to background processing, such as by
                // closing a database connection.
            }
        }
    }
}

C#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

class LowMemoryTrigger : MonoBehaviour
{
    private void Start()
    {
        Application.lowMemory += OnLowMemory;
    }
    private void OnLowMemory()
    {
        // Respond to low memory condition (e.g., Resources.UnloadUnusedAssets())
    }
}

मेमोरी बजट को लेकर ज़्यादा सतर्क रहें

मेमोरी खत्म होने से बचाने के लिए, बजट की मेमोरी को कम से कम रखें. इन बातों का ध्यान रखें:

  • फ़िज़िकल रैम का साइज़: गेम अक्सर डिवाइस पर मौजूद फ़िज़िकल रैम का ¼ से ½ हिस्सा इस्तेमाल करते हैं.
  • ज़ेडरैम का ज़्यादा से ज़्यादा साइज़: ज़ेडरैम का साइज़ ज़्यादा होने का मतलब है कि गेम के पास मेमोरी को असाइन करने के लिए ज़्यादा जगह है. यह रकम, डिवाइस के हिसाब से अलग-अलग हो सकती है. इस वैल्यू को ढूंढने के लिए, SwapTotal में /proc/meminfo देखें.
  • ओएस के लिए मेमोरी का इस्तेमाल: जिन डिवाइसों में सिस्टम प्रोसेस के लिए ज़्यादा रैम तय की जाती है उनमें आपके गेम के लिए कम मेमोरी बचती है. सिस्टम, सिस्टम प्रोसेस को बंद करने से पहले आपके गेम की प्रोसेस को बंद कर देता है.
  • इंस्टॉल किए गए ऐप्लिकेशन के लिए मेमोरी का इस्तेमाल: अपने गेम को उन डिवाइसों पर टेस्ट करें जिन पर कई ऐप्लिकेशन इंस्टॉल किए गए हैं. सोशल मीडिया और चैट ऐप्लिकेशन लगातार चलते रहते हैं. इससे डिवाइस के स्टोरेज पर असर पड़ता है.

अगर आपको मेमोरी के लिए तय किए गए बजट का पालन करने में मुश्किल हो रही है, तो ज़्यादा लचीला तरीका अपनाएं. अगर सिस्टम में मेमोरी कम होने की वजह से समस्याएं आ रही हैं, तो गेम के लिए इस्तेमाल की जा रही मेमोरी को कम करें. उदाहरण के लिए, onTrimMemory() के जवाब में कम रिज़ॉल्यूशन वाले टेक्सचर असाइन करें या कम शेडर सेव करें. मेमोरी को डाइनैमिक तरीके से असाइन करने के लिए, डेवलपर को ज़्यादा काम करना पड़ता है. खास तौर पर, गेम डिज़ाइन के चरण में.

थ्रैशिंग से बचना

थ्रैशिंग तब होती है, जब मेमोरी कम होती है, लेकिन गेम को बंद करने के लिए काफ़ी नहीं होती. इस स्थिति में, kswapd ने उन पेजों को वापस ले लिया है जिनकी गेम को अब भी ज़रूरत है. इसलिए, यह मेमोरी से पेजों को फिर से लोड करने की कोशिश करता है. मेमोरी में ज़रूरत के मुताबिक जगह नहीं है. इसलिए, पेजों को लगातार स्वैप किया जा रहा है. सिस्टम ट्रेसिंग इस स्थिति को थ्रेड के तौर पर रिपोर्ट करती है. इसमें kswapd लगातार चलता रहता है.

थ्रैशिंग का एक लक्षण यह है कि फ़्रेम को रेंडर होने में ज़्यादा समय लगता है. ऐसा हो सकता है कि फ़्रेम को रेंडर होने में एक सेकंड या इससे ज़्यादा समय लगे. इस समस्या को हल करने के लिए, गेम के मेमोरी फ़ुटप्रिंट को कम करें.

उपलब्ध टूल इस्तेमाल करना

Android में कई टूल होते हैं. इनसे यह समझने में मदद मिलती है कि सिस्टम मेमोरी को कैसे मैनेज करता है.

Meminfo

यह टूल, मेमोरी के आंकड़े इकट्ठा करता है. इससे यह पता चलता है कि कितनी पीएसएस मेमोरी असाइन की गई थी और इसका इस्तेमाल किन कैटगरी के लिए किया गया था.

meminfo के आंकड़ों को इनमें से किसी एक तरीके से प्रिंट करें:

  • adb shell dumpsys meminfo package-name कमांड का इस्तेमाल करें.
  • Android Debug API से MemoryInfo कॉल का इस्तेमाल करें.

PrivateDirty आंकड़े से पता चलता है कि प्रोसेस में मौजूद कितनी रैम को डिस्क पर पेज नहीं किया जा सकता. साथ ही, इसे किसी अन्य प्रोसेस के साथ शेयर नहीं किया जाता. जब प्रोसेस बंद हो जाती है, तब इस मेमोरी का ज़्यादातर हिस्सा सिस्टम के लिए उपलब्ध हो जाता है.

मेमोरी ट्रेसपॉइंट

मेमोरी ट्रेसपॉइंट, आपके गेम में इस्तेमाल की जा रही आरएसएस मेमोरी को ट्रैक करते हैं. आरएसएस के लिए मेमोरी के इस्तेमाल का हिसाब लगाना, पीएसएस के लिए मेमोरी के इस्तेमाल का हिसाब लगाने से ज़्यादा तेज़ होता है. आरएसएस का हिसाब लगाना आसान होता है. इसलिए, यह पीक मेमोरी के इस्तेमाल का ज़्यादा सटीक मेज़रमेंट करने के लिए, मेमोरी साइज़ में होने वाले बदलावों के बारे में ज़्यादा जानकारी दिखाता है. इसलिए, उन पीक को आसानी से देखा जा सकता है जिनकी वजह से गेम में मेमोरी की समस्या हो सकती है.

Perfetto और लंबे ट्रेस

Perfetto, डिवाइस पर परफ़ॉर्मेंस और मेमोरी की जानकारी इकट्ठा करने वाले टूल का एक सुइट है. यह जानकारी को वेब-आधारित यूज़र इंटरफ़ेस (यूआई) में दिखाता है. यह लंबे समय तक के ट्रेस को सपोर्ट करता है, ताकि यह देखा जा सके कि समय के साथ आरएसएस में कैसे बदलाव होता है. यह ऑफ़लाइन प्रोसेसिंग के लिए, जनरेट किए गए डेटा पर SQL क्वेरी भी जारी कर सकता है. सिस्टम ट्रेसिंग ऐप्लिकेशन से, लंबे समय तक चलने वाले ट्रेस चालू करें. पक्का करें कि ट्रेस के लिए, memory:Memory कैटगरी चालू हो.

heapprofd

heapprofd एक मेमोरी ट्रैकिंग टूल है, जो Perfetto का हिस्सा है. यह टूल, मेमोरी लीक का पता लगाने में आपकी मदद कर सकता है. इसके लिए, यह दिखाता है कि malloc का इस्तेमाल करके मेमोरी कहां असाइन की गई थी. heapprofd को Python स्क्रिप्ट का इस्तेमाल करके शुरू किया जा सकता है. साथ ही, इस टूल का ओवरहेड कम होता है. इसलिए, यह Malloc Debug जैसे अन्य टूल की तरह परफ़ॉर्मेंस पर असर नहीं डालता.

गड़बड़ी की रिपोर्ट

bugreport एक लॉगिंग टूल है. इससे यह पता चलता है कि मेमोरी खत्म होने की वजह से आपका गेम क्रैश हुआ है या नहीं. इस टूल का आउटपुट, logcat का इस्तेमाल करने के मुकाबले ज़्यादा जानकारी वाला होता है. यह मेमोरी डीबग करने के लिए मददगार है. इससे पता चलता है कि मेमोरी खत्म होने की वजह से आपका गेम क्रैश हुआ है या LMK ने इसे बंद कर दिया है.

ज़्यादा जानकारी के लिए, बग रिपोर्ट कैप्चर करना और उन्हें पढ़ना लेख पढ़ें.