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

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

इस पेज पर, कम मेमोरी की वजह से होने वाली उन समस्याओं से बचने के लिए किए जाने वाले चरणों के बारे में बताया गया है जो आपके गेम पर असर डाल सकती हैं.

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.
            }
        }
    }
}

मेमोरी बजट को कम रखना

मेमोरी खत्म होने से बचने के लिए, मेमोरी बजट को कम रखें. यहां कुछ चीज़ें दी गई हैं जिन पर ध्यान दिया जा सकता है:

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

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

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

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

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

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

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

Meminfo

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

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

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

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

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

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

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

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

heapprofd

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

bugreport

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

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