टूल और परफ़ॉर्मेंस

अपने ऐप्लिकेशन के बिट मैप मेमोरी फ़ुटप्रिंट को कम करने के लिए, काम की रणनीतियां

स्पीकर

इसके बारे में

बातचीत के बारे में जानकारी

बिट मैप के लिए मेमोरी मैनेज करना ज़रूरी है, ताकि विज़ुअल से भरपूर Android ऐप्लिकेशन में, आउट-ऑफ़-मेमोरी (ओओएम) के जोखिमों को कम किया जा सके. डेवलपर को इमेज का साइज़ कम करने के बारे में पता होता है. हालांकि, ऐप्लिकेशन को लंबे समय तक स्टेबल बनाए रखने के लिए, दो अन्य मुख्य बातों पर ध्यान देना ज़रूरी है: फिर से इस्तेमाल करना और रीसाइकल करना. इस सेशन में, मेमोरी की परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए एक प्रैक्टिकल प्लेबुक दी गई है. इसमें आधुनिक टूल, Glide और Coil जैसी ओपन-सोर्स लाइब्रेरी, और सिस्टम-लेवल के एपीआई का इस्तेमाल किया गया है.

इस सेशन में, आपको Android Vitals का इस्तेमाल करके, असल दुनिया में मेमोरी रिग्रेशन का पता लगाने का तरीका बताया जाएगा. साथ ही, Glide और Coil की मदद से, कैश मेमोरी में डेटा सेव करने के बेहतर पैटर्न (फिर से इस्तेमाल करना) लागू करने और onTrimMemory कॉलबैक का इस्तेमाल करके, मेमोरी को रिलीज़ करने (रीसाइकल करना) का तरीका बताया जाएगा.

खास जानकारी

  • Google Play, मेमोरी की परफ़ॉर्मेंस के लिए थ्रेशोल्ड लागू कर रहा है. ये थ्रेशोल्ड, फ़रवरी 2027 से लागू होंगे. 90वें पर्सेंटाइल की सीमा को पार करने से, आपके ऐप्लिकेशन की परफ़ॉर्मेंस के आकलन पर सीधा असर पड़ता है. साथ ही, Play Store पर आपके ऐप्लिकेशन के दिखने की संभावना कम हो सकती है.
  • डिकोड होने पर, बिट मैप डाइमेंशन और कलर डेप्थ के हिसाब से बड़े हो जाते हैं. इस वजह से, ज़्यादातर ऐप्लिकेशन में ये सबसे ज़्यादा मेमोरी का इस्तेमाल करते हैं. फ़ुल रिज़ॉल्यूशन वाली कुछ इमेज ही सैकड़ों मेगाबाइट की जगह ले सकती हैं.
  • मेमोरी की खपत कम करने के लिए, इमेज को डाउनसैंपल करें और सिर्फ़ दिखने वाले हिस्सों को डिकोड करें. सीडीएन का इस्तेमाल करके, इमेज के डाइमेंशन मैच करने का अनुरोध करें या BitmapRegionDecoder जैसे एपीआई का इस्तेमाल करें. इससे आपको बड़ी और फ़ुल रिज़ॉल्यूशन वाली इमेज लोड करने की ज़रूरत नहीं पड़ेगी.
  • एक से ज़्यादा इमेज लोडर का इस्तेमाल करने से, डिफ़ॉल्ट मेमोरी हीप कैश मेमोरी का इस्तेमाल बढ़ जाता है. साथ ही, सेव किए गए बिट मैप डुप्लीकेट हो जाते हैं. एक ही लोडर का इस्तेमाल करें या मौजूदा लोडर के लिए, मेमोरी बजट सेट करें.
  • जब आपका ऐप्लिकेशन बैकग्राउंड में चला जाए, तो onTrimMemory को हैंडल करके इमेज मेमोरी को रिलीज़ करें. बैकग्राउंड में मेमोरी के इस्तेमाल को बढ़ने से रोकने के लिए, onStop में बैकग्राउंड पोलिंग और ऐनिमेशन बंद करें.

संसाधन

Gemini Notebook

विषय

  • bitmap-optimization
  • android-memory
  • android-vitals
  • इमेज-कैशिंग
  • मेमोरी-प्रोफ़ाइलर

ट्रांसक्रिप्ट

ट्रांसक्रिप्ट डाउनलोड करें

बिट मैप मेमोरी के बारे में खास जानकारी

  • Fung Lam

    हां, लंच में करीब एक घंटा बचा है. इसलिए, कृपया मेरे साथ बने रहें.

  • मैं फ़ंग लैम हूं. मैं लंदन में Android के लिए डेवलपर रिलेशंस इंजीनियर हूं.

  • हां, धन्यवाद.

  • शुरू करने से पहले, क्या मैं एक सवाल पूछ सकता हूं?

  • आपमें से कितने लोगों ने इस साल नया फ़ोन खरीदा?

  • वाह!

  • वाह!

  • ईमानदारी से बताओ, अगर तुम Pixel नहीं खरीद रहे हो, तो मैं तुम्हें दोष नहीं दूंगा.

  • नए फ़ोन के लिए, यह ज़्यादा महंगा है.

  • हां, इसलिए आप में से कुछ लोगों ने नया फ़ोन नहीं खरीदा.

  • यह ज़्यादा महंगा क्यों है?

  • क्या आपको पता है?

  • नहीं.

  • रैम.

  • रैम, हां, हां.

  • हां, रैम Android, हमारे, और डेवलपर के लिए वाकई एक चुनौती है.

  • इसलिए, आज मैं आपको यह बताने आया हूं कि हम मेमोरी और रैम से जुड़ी समस्या को कैसे हल कर सकते हैं.

  • इससे पहले, Google I/O और Google I/O Connect में, हमने मेमोरी के बारे में कुछ सेशन किए थे. इनमें हमने बताया था कि ऑपरेटिंग सिस्टम, मेमोरी को कैसे ऐलोकेट करता है, ऐप्लिकेशन को कैसे प्रोफ़ाइल किया जा सकता है, और R8 का इस्तेमाल करके कोड को कैसे ऑप्टिमाइज़ किया जा सकता है. इसके अलावा, मैंने उस समय बिटमैप के बारे में भी थोड़ी जानकारी दी थी.

  • स्क्रीनशॉट में मेरी फ़ोटो दिख सकती हैं.

  • मेमोरी ऑप्टिमाइज़ेशन एक बड़ा डोमेन है, जो Android रनटाइम, गार्बेज कलेक्शन, परफ़ॉर्मेंस टूल, ऑब्जेक्ट मेमोरी का बंटवारा, कंपाइलर वगैरह जैसे अलग-अलग क्षेत्रों में काम करता है. इस सेशन में, इन 30 मिनटों में, मैं आपको बिट मैप मेमोरी को ऑप्टिमाइज़ करने के बारे में कुछ जानकारी दूंगा.

  • आप पूछ सकते हैं कि बिटमैप ही क्यों?

  • हमें बिट मैप मेमोरी पर क्यों फ़ोकस करना चाहिए?

  • क्योंकि एक इमेज, हज़ारों शब्दों से बेहतर होती है.

  • यह सच है. मैं आपको इसकी वजह बताऊंगा.

  • फ़ोन की स्क्रीन पर, मान लें कि Pixel 7, Pixel 9 या Pixel 11 Pro वर्शन पर, स्क्रीन रिज़ॉल्यूशन करीब 2,500 1,200, 1,400 है.

  • इसलिए, हर पिक्सल के लिए, हम 32 बिट की कलर डेप्थ का इस्तेमाल करते हैं.

  • इसलिए, फ़ुल स्क्रीन की इमेज के लिए, ओह, मेरे पास ज़रूरत के मुताबिक उंगलियां नहीं हैं, लेकिन इसमें करीब 15 एमबी मेमोरी लगेगी, 50 एमबी.

  • इसलिए, ओएस सिस्टम में एक वर्ड 64-बिट का होता है. इसका मतलब है कि यह 8 बाइट का होता है.

  • एक हज़ार शब्दों का साइज़ सिर्फ़ आठ एमबी होता है.

  • हां, 8K.

  • इसलिए, एक इमेज हज़ारों शब्दों से बेहतर होती है.

  • हां, यह ज़रूरी है.

  • एक इमेज का साइज़ पहले से ही 15 एमबी है.

  • अगर आपके ऐप्लिकेशन में 10 या 100 इमेज हैं, तो क्या होगा?

  • यह एक बड़ी संख्या है.

  • इसलिए, बिट मैप आम तौर पर आपके ऐप्लिकेशन में सबसे ज़्यादा मेमोरी का इस्तेमाल करता है.

  • जब इमेज को मेमोरी में डिकोड किया जाता है, तो जैसा कि मैंने बताया, यह डाइमेंशन और कलर डेप्थ के हिसाब से बड़ा हो जाता है.

  • यह इस बारे में नहीं है कि फ़ाइल का साइज़ कितना है, यह JPEG या PNG फ़ॉर्मैट में है या नहीं.

  • नहीं, इसे डिकोड किया जाएगा और मेमोरी का इस्तेमाल किया जाएगा.

  • इसलिए, फ़ुल-रिज़ॉल्यूशन वाली कुछ इमेज ही आपके डिवाइस की सैकड़ों मेगाबाइट मेमोरी भर देंगी.

  • दूसरा, जब मेमोरी बहुत कम होती है, तो ऑपरेटिंग सिस्टम को मेमोरी के इस्तेमाल को मैनेज करने के लिए ज़्यादा बैटरी खर्च करनी पड़ती है.

  • इससे यूज़र इंटरफ़ेस (यूआई) में रुकावट आ सकती है.

  • इसके अलावा, ओएस आपके ऐप्लिकेशन को बंद कर सकता है, ताकि मेमोरी खाली हो सके.

  • इसके अलावा, आपके ऐप्लिकेशन में मेमोरी खत्म होने की गड़बड़ी या मेमोरी खत्म होने का अपवाद भी दिखेगा.

  • अच्छी बात यह है कि इस वॉच फ़ेस को आसानी से सेट किया जा सकता है.

  • मेमोरी के इस्तेमाल में होने वाली ज़्यादातर बढ़ोतरी, आम तौर पर होने वाली गलतियों की वजह से होती है. इनसे बचा जा सकता है. साथ ही, हम इमेज की क्वालिटी से समझौता किए बिना इसे ठीक कर सकते हैं.

  • अब आपको पता है कि बिट मैप मेमोरी आपके ऐप्लिकेशन के लिए ज़रूरी है. इससे न सिर्फ़ ऐप्लिकेशन को आसानी से इस्तेमाल किया जा सकता है, बल्कि उसकी परफ़ॉर्मेंस को बेहतर बनाने और उपयोगकर्ताओं को अपने साथ जोड़े रखने में भी मदद मिलती है.

  • इसलिए, आज हम पांच आसान चरणों के बारे में जानेंगे, ताकि आपका ऐप्लिकेशन बिना किसी रुकावट के काम करता रहे.

  • सबसे पहले, हम Google Play पर तकनीकी क्वालिटी और इससे जुड़ी नई ज़रूरी शर्त के बारे में जानेंगे. इसमें, मेमोरी की सीमा से जुड़ी आने वाली नई शर्त और इस सीमा को आसानी से देखने का तरीका शामिल है.

  • दूसरा, मैं 500 Android ऐप्लिकेशन के बारे में अपनी केस स्टडी शेयर करूंगा. इसमें बताया जाएगा कि वे मेमोरी का इस्तेमाल कैसे करते हैं, क्या वे सही तरीके से ऐसा कर रहे हैं या क्या इससे हमें कुछ सीखने को मिल सकता है?

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

  • आखिर में, हम कुछ ऐसे टूल शेयर करेंगे जिनकी मदद से अपने ऐप्लिकेशन की जांच की जा सकती है.

Google Play के क्वालिटी स्टैंडर्ड और आम तौर पर आने वाली समस्याएं

  • Fung Lam

    सबसे पहले, Google Play पर क्वालिटी से जुड़ी नई ज़रूरी शर्त के बारे में जानते हैं.

  • आप Google Play Console का कितना इस्तेमाल करते/करती हैं?

  • हर महीने?

  • हर हफ़्ते?

  • कभी नहीं?

  • हंसने का मतलब है कि हां, है न?

  • नहीं?

  • नहीं.

  • क्या आपने Android की ज़रूरी जानकारी वाले सेक्शन पर विज़िट किया था?

  • हां, हां.

  • हां, तो आपको इस बारे में पहले से ही कुछ पता है.

  • इसलिए, Google Play पर परफ़ॉर्मेंस थ्रेशोल्ड के लिए, क्वालिटी से जुड़ी नई ज़रूरी शर्तें लागू की गई हैं.

  • Android और Google Play, उपयोगकर्ताओं को अच्छी क्वालिटी वाले ऐप्लिकेशन उपलब्ध कराना चाहते हैं.

  • इसलिए, यह थ्रेशोल्ड भी कुछ ऐसा है, जिसे हम असली उपयोगकर्ता के लिए सबसे बेहतर बनाने की कोशिश करते हैं.

  • आसान शब्दों में कहें, तो "जब आपका ऐप्लिकेशन बैकग्राउंड में या फ़ोरग्राउंड में चल रहा हो, तब मेमोरी के इस्तेमाल का 90 पर्सेंटाइल इस थ्रेशोल्ड से ज़्यादा नहीं होना चाहिए.

  • ऐसा न करने पर, हो सकता है कि Play Store पर आपके ऐप्लिकेशन को कम दिखाया जाए या कुछ और हो."

  • ऐप्लिकेशन और गेम के लिए, यह नीति फ़रवरी 2027 से लागू होगी.

  • इस थ्रेशोल्ड को पार करने से, आपके ऐप्लिकेशन की परफ़ॉर्मेंस के आकलन पर सीधा असर पड़ता है.

  • इसलिए, Google Play Console पर जाकर यह ज़रूर देखें कि "आज मेरा 90 पर्सेंटाइल क्या है?"

  • साथ ही, तय समयसीमा से पहले सुधार करें.

  • यह ऐनिमेशन है.

  • "अगर Google Play Console पर जाएं, तो आपको Android की ज़रूरी जानकारी दिखेगी.

  • यह मेमोरी का एक हिस्सा है.

  • साथ ही, आपको 90 पर्सेंटाइल दिख सकता है.

  • इस पर क्लिक करने पर, आपको समय के साथ मेमोरी के इस्तेमाल का औसत दिखेगा.

  • साथ ही, रैम, डिवाइस के नाप या साइज़, स्क्रीन डेंसिटी, और ओएस वर्शन के हिसाब से अलग-अलग टियर होते हैं. इनकी मदद से, एंट्री-लेवल के किसी डिवाइस या ऐप्लिकेशन की किसी रिलीज़ पर, मेमोरी की कमी की समस्या को अलग किया जा सकता है.

  • अब मुझे पता है कि आप कह सकते हैं, "मुझे यह बताने के लिए धन्यवाद कि मेरे ऐप्लिकेशन की क्रैश रेट थ्रेशोल्ड से ज़्यादा है.

  • लेकिन मुझे नहीं पता कि क्या गड़बड़ी है.

  • क्या तुम मेरी मदद करोगी?"

  • हां, इसलिए मैं आपकी मदद करने के लिए यहां हूं.

  • मैं इसे आपके लिए आसान बनाने की कोशिश करूंगा. जैसे, अगर टीवी देखते समय उसमें वीडियो या ऑडियो न आए, तो क्या किया जाएगा?

  • आपने टीवी का मैन्युअल निकाला और उसके आखिरी कुछ पेजों पर गए. आम तौर पर, इन पेजों पर समस्या हल करने की गाइड होती है. इसमें लिखा होता है, "अगर आपके टीवी से आवाज़ नहीं आ रही है, तो यह बटन दबाएं या वह बटन दबाएं."

  • हां, इसी तरह आज मुझे कुछ सामान्य समस्याएं मिलीं.

  • उम्मीद है कि इससे आपको समस्या हल करने में मदद मिलेगी.

  • आम तौर पर, जब हम टीवी की गाइड पढ़ते हैं, तो हमें पहले पेज से शुरुआत करनी चाहिए. आम तौर पर, पहले पेज पर डाइग्नोस्टिक टूलकिट के बारे में जानकारी होती है. इससे आपको यह समझने में मदद मिलती है कि टीवी कैसे काम करता है.

  • हालांकि, अब मुझे पता है कि ये कम दिलचस्प हैं. इसलिए, आज मुझे पहले समस्या हल करने की अनुमति दें. हम बाद में वापस आएंगे.

  • सच कहूं, तो मैं टीवी का मैन्युअल इसी तरह पढ़ता हूं.

  • Android ईकोसिस्टम में, बिट मैप के लिए मेमोरी के इस्तेमाल से जुड़ी सबसे आम समस्या का पता लगाने के लिए, मैंने Android पर मौजूद करीब 500 लोकप्रिय ऐप्लिकेशन पर रिसर्च की.

  • मैं ऐप्लिकेशन को चलाता हूं, उसे शुरू करता हूं, लॉग इन करता हूं, अलग-अलग पेजों पर जाता हूं, गहराई से जांच करता हूं, और वापस आता हूं.

  • मैं ऐप्लिकेशन को अलग-अलग रैम और डिवाइसों पर टेस्ट करता हूं. जैसे, 2 जीबी मेमोरी वाला Android Go डिवाइस, कम सुविधाओं वाला 4 जीबी रैम वाला डिवाइस, मिड-लेवल का 4 जीबी रैम वाला डिवाइस, 6 जीबी से 8 जीबी रैम वाला डिवाइस या 16 जीबी मेमोरी वाला प्रीमियम फ़ोल्ड किया जा सकने वाला डिवाइस, जिसकी स्क्रीन बहुत बड़ी और अच्छी क्वालिटी की हो.

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

  • इस तरह, अलग-अलग गतिविधि की स्थितियों में मेमोरी बदलती है.

  • इस विश्लेषण से, हमें 15 से ज़्यादा सामान्य समस्याओं का पता चलता है. इनमें इमेज का साइज़ ज़्यादा होने से लेकर, बैकग्राउंड कैश मेमोरी बढ़ने तक की समस्याएं शामिल हैं.

  • इसलिए, आज हम इस केस स्टडी को एक्सप्लोर करेंगे और शेयर करेंगे.

केस स्टडी: बिटमैप का साइज़ तय करना और उन्हें डिकोड करना

  • Fung Lam

    हां, मैं अब जो केस स्टडी शेयर कर रहा हूं वह 500 ऐप्लिकेशन पर की गई रिसर्च के बारे में है.

  • आप यहां हैं, तो मुझे लगता है कि हम सभी को Android पसंद है, है न?

  • हम सभी को Android पसंद है.

  • मान लें कि हममें से किसी को Android पसंद है, लेकिन वह Android डेवलपमेंट का एक्सपर्ट नहीं है.

  • इसलिए, उन्होंने Android फ़िगुरिन का ऑर्डर देने के लिए, एक Android ऐप्लिकेशन बनाया.

  • हालांकि, इसमें कुछ गलतियां हैं.

  • चलिए, बात करते हैं. देखते हैं कि शायद यह पहली गलती है.

  • "नमस्ते, प्रॉडक्ट पेज पर, हमारे पास दो कॉलम वाला लेआउट है. इसमें Android की अलग-अलग फ़िगुरिन दिख रही हैं.

  • हर कॉलम के लिए, इमेज का साइज़ करीब 400 x 400 पिक्सल होता है.

  • हालांकि, ऐप्लिकेशन असल में सर्वर से एक ही इमेज डाउनलोड कर रहा है. इससे कोई फ़र्क़ नहीं पड़ता कि मेरी स्क्रीन कितनी बड़ी है.

  • यह 3000 x 3000 पिक्सल की इमेज डाउनलोड कर रहा है.

  • हां, क्योंकि डेवलपर के तौर पर, "अरे, Android बहुत ही शानदार और कमाल का है.

  • मैं उपयोगकर्ता को सबसे अच्छा कॉन्टेंट दिखाना चाहता हूं."

  • लेकिन असल में ऐसा नहीं है, क्योंकि यह इमेज व्यू के डाइमेंशन से सीमित है.

  • इसलिए, बड़ी इमेज डाउनलोड करने के बाद भी, वह उपयोगकर्ता को सबसे अच्छी क्वालिटी में नहीं दिखती.

  • इसके अलावा, इस बड़ी इमेज की वजह से ज़्यादा मेमोरी की ज़रूरत पड़ी.

  • अगर हम इसे डाउनसैंपल भी करते हैं, तो डाउनसैंपल की प्रोसेस में भी अतिरिक्त मेमोरी का इस्तेमाल होता है.

  • इस डेवलपर को इस समस्या को ठीक करने में हम कैसे मदद कर सकते हैं?

  • अगर आपको सीडीएन के बारे में पता है, तो आपको यह भी पता होगा कि सीडीएन, इमेज से जुड़े कुछ काम कर सकता है. जैसे, इमेज को काटना, उसका साइज़ बदलना, उसे घुमाना, उस पर फ़िल्टर लगाना, और उसे स्क्वेयर से गोल इमेज में बदलना.

  • एचटीटीपी अनुरोध की मदद से, सीडीएन कुछ चीज़ों को मैनेज कर सकता है.

  • इसलिए, भले ही आपके सर्वर-साइड पर सिर्फ़ एक इमेज होस्ट की जा रही हो, फिर भी सीडीएन का इस्तेमाल करके, अपने डिवाइस पर इमेज का साइज़ बदलकर भेजा जा सकता है.

  • इसलिए, पहली बात यह है कि इमेज का अनुरोध करते समय, सीडीएन का इस्तेमाल करें. इससे आपको ImageView के साइज़ के हिसाब से इमेज का अनुरोध करने में मदद मिलेगी.

  • हालांकि, अगर ऐसा करना मुमकिन न हो, जैसे कि कभी-कभी यह ImageView से थोड़ा बड़ा हो सकता है, तो कोड में इसका साइज़ बदलने के लिए, डाउनसैंपल करना न भूलें.

  • इसलिए, जब इसे मेमोरी में लोड किया जाता है, तो यह छोटी इमेज लोड करता है. यह इमेज को फ़ुल रिज़ॉल्यूशन में लोड नहीं करता.

  • यहां Coil के लिए एक कोड सैंपल दिया गया है.

    // 1. Ask CDN for the exact UI card dimensions (e.g. 540x675)
    val sizedUrl = "$cdnBaseUrl?w=$cardWidthPx&h=$cardHeightPx&fmt=webp"
    
    // 2. Enforce exact downsampling + Hardware Bitmap config
    AsyncImage(
        model = ImageRequest.Builder(LocalContext.current)
            .data(sizedUrl)
            .size(cardWidthPx, cardHeightPx) // Never use Size.ORIGINAL!
            .precision(Precision.EXACT)      // Downsample to exact card size
            .bitmapConfig(Bitmap.Config.HARDWARE)
            .build(),
        contentDescription = product.title
    )
  • साइज़ को पीले रंग में लिखे गए टेक्स्ट के तौर पर पास किया जा सकता है.

  • हां, एचटीटीपी अनुरोध में साइज़ को एचटीटीपी के तौर पर पास किया जा सकता है.

  • इसके बाद, यहां हाइलाइट किए गए कोड में, क्या आपको हाइलाइट दिख रहा है? हां, हां, Size.ORIGINAL का इस्तेमाल न करें.

  • हां, चौड़ाई और ऊंचाई का इस्तेमाल करें, ताकि इसे पैरामीटर के तौर पर पास किया जा सके.

  • इमेज को सटीक साइज़ में डाउनसैंपल करने के लिए, सटीक साइज़ का इस्तेमाल करें.

  • अगर हो सके, तो Bitmap.Config.HARDWARE का इस्तेमाल करें. इससे कम मेमोरी का इस्तेमाल होता है, क्योंकि इमेज सीधे वीआरएएम में सेव होगी.

  • इसी तरह, इस ऐप्लिकेशन पर, Android के कलेक्टेबल का नया वर्शन रिलीज़ किया गया है. इसलिए, यहां एक लंबी इमेज है, जिसे उपयोगकर्ता बाएं और दाएं स्वाइप करके, Android के नए फ़िगर के अलग-अलग डिज़ाइन देख सकता है.

  • हालांकि, यहां एक और समस्या है.

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

  • क्या हम इसे और बेहतर बना सकते हैं?

  • हां.

  • हम इसे छोटी-छोटी इमेज में बांट सकते हैं और सिर्फ़ स्क्रीन पर दिखने वाली इमेज को लोड कर सकते हैं.

  • स्क्रीन से बाहर मौजूद इमेज लोड नहीं होंगी या अनलोड हो जाएंगी.

  • इसलिए, यह कम मेमोरी का इस्तेमाल करेगा.

  • इसी तरह, इस मामले में करीब 60% मेमोरी की बचत हुई.

  • ज़ाहिर है कि अगर छोटे रेक्टैंगल में ट्रिम किया जाए, तो ज़्यादा बचत होगी.

  • इसी तरह, अगर कोई उपयोगकर्ता किसी उपयोगकर्ता को कोई सुविधा देना चाहता है, तो Android फ़िगुरिन की हर जानकारी देखने के लिए, ज़ूम इन और ज़ूम इन किया जा सकता है. कुछ सामान्य गलतियां वे फिर से लोड करते हैं, फिर से बहुत बड़ी इमेज, ताकि इसे ज़ूम किया जा सके और फिर से ज़ूम किया जा सके.

  • हालांकि, आपको ऐसा करने की ज़रूरत नहीं है.

  • इससे बेहतर तरीका यह है कि जब उपयोगकर्ता पहले से लोड की गई कम रिज़ॉल्यूशन वाली ओरिजनल इमेज को ज़ूम इन करे और पिंच करना बंद कर दे, तब कोऑर्डिनेट का हिसाब लगाएं और फिर हाई रिज़ॉल्यूशन वाली इमेज से सिर्फ़ उस हिस्से को लोड करें जिसका हिसाब लगाया गया है.

  • इसलिए, सिर्फ़ दिखने वाले हिस्से को मेमोरी में लोड किया जाएगा.

  • ऐसा कैसे करें?

  • BitmapRegionDecoder नाम का एक एपीआई है, जो किसी इमेज के खास हिस्से को लोड करने में मदद करता है.

  • बेशक, कुछ टूल और लाइब्रेरी भी आपकी मदद कर सकती हैं.

  • इसे GitHub पर खोजा जा सकता है.

  • कॉमिक्स से जुड़े कुछ ऐप्लिकेशन या कुछ मैप पहले से ही इसका इस्तेमाल कर रहे हैं.

  • इनका इस्तेमाल रेफ़रंस के तौर पर किया जा सकता है.

  • इसके अलावा, हम इंसान हैं और हमसे गलतियां होती हैं.

  • एआई से भी गलतियां हो सकती हैं.

  • इसलिए, गलतियों से बचने के लिए, इमेज लोड करते समय कुछ सीमाएं भी जोड़ी जा सकती हैं.

  • उदाहरण के लिए, इस मामले में, मैं कह सकता हूं, "अरे, विंडो के साइज़ या स्क्रीन के डाइमेंशन को सीमा के तौर पर इस्तेमाल करें और इसे कम से कम फ़ंक्शन में डालें, अनुरोध की चौड़ाई या बाउंड की चौड़ाई कम से कम."

    // Query active window bounds instead of hardcoding 1080 / 1920
    val bounds = WindowMetricsCalculator.getOrCreate()
        .computeCurrentWindowMetrics(activity).bounds
    
    // Clamp target dimensions so Bitmap NEVER exceeds the active window
    val safeWidth  = minOf(requestedWidthPx,  bounds.width())
    val safeHeight = minOf(requestedHeightPx, bounds.height())
    
    val bitmap = Bitmap.createBitmap(safeWidth, safeHeight, config)
  • इसलिए, इस फ़ंक्शन की मदद से, जब भी कोई इमेज लोड की जाएगी, तो वह कभी भी बाउंड्री से बाहर नहीं जाएगी.

  • इसलिए, यह स्क्रीन रिज़ॉल्यूशन से बड़ी इमेज लोड नहीं करेगा.

  • याद रखें, इमेज के सिर्फ़ उस हिस्से को डिकोड करें जो दिख रहा है. इससे आपकी मेमोरी बचेगी.

मेमोरी, डुप्लीकेट, और कैश मेमोरी मैनेज करना

  • Fung Lam

    साथ ही, यह भी पता चलता है कि इस ऐप्लिकेशन को किसी एक डेवलपर ने नहीं बनाया है.

  • दरअसल, यह कई योगदान देने वाले लोगों के लिए है और हो सकता है कि वे अलग-अलग टूल का इस्तेमाल कर रहे हों.

  • उदाहरण के लिए, इसका एक हिस्सा है, "ओह, माफ़ करें" का इस्तेमाल करना.

  • मैं फिर से शुरू करता हूँ.

  • इस ऐप्लिकेशन के लिए भी यही बात लागू होती है.

  • नमस्ते, प्रॉडक्ट पेज पर मेरे पास प्रॉडक्ट की एक सूची है और मैंने यह इमेज देखी. मैंने इसे शॉपिंग कार्ट में जोड़ दिया.

  • कुछ मिनट बाद, जब मैं चेकआउट करने जाता हूं, तो मुझे वही इमेज फिर से दिखती है.

  • लेकिन क्या यह वाकई में एक ही इमेज है या मेमोरी में मौजूद दो अलग-अलग ऑब्जेक्ट हैं?

  • हां, हमें एक आम गड़बड़ी मिली है. जैसे, ऐप्लिकेशन में बहुत सारी इमेज लोड हो रही हैं.

  • हालांकि, उनके पास मेमोरी में डुप्लीकेट इमेज भी बहुत ज़्यादा हैं.

  • अगर इमेज लोडर का इस्तेमाल किया जा रहा है, तो कैश मेमोरी में सेव करने के लिए एक कुंजी पास की जा सकती है.

  • इसलिए, जब एक ही इमेज का इस्तेमाल किया जाता है, तो नया ऑब्जेक्ट बनाने के बजाय, पहले से असाइन किए गए बिटमैप ऑब्जेक्ट का इस्तेमाल किया जा सकता है.

  • Android Studio में, मेमोरी प्रोफ़ाइलर का इस्तेमाल करके यह पता लगाया जा सकता है कि क्या आपके ऐप्लिकेशन में डुप्लीकेट बिट मैप है?

  • मैंने अपने Google I/O सेशन में इस बारे में बताया था. इसलिए, YouTube पर जाकर वीडियो देखा जा सकता है.

  • अगर Android Studio का इस्तेमाल नहीं किया जा रहा है, तो हीप डंप को कैप्चर करने के लिए, adb कमांड का इस्तेमाल किया जा सकता है. इसके बाद, Perfetto हीप ग्राफ़ एसक्यूएल लैंग्वेज का इस्तेमाल करके, यह क्वेरी की जा सकती है कि मेरे ऐप्लिकेशन में डुप्लीकेट बिटमैप है या नहीं.

  • यह Coil में कोड का एक उदाहरण है. इसमें बताया गया है कि बिटमैप कैश मेमोरी के लिए कुंजी कैसे जोड़ी जाती है.

    // Strip volatile query tokens (?from=list / ?sig=...) for cache key
    val canonicalKey = MemoryCache.Key(productUrl.substringBefore("?"))
    
    // On Checkout Screen: reuse the 200x200 Bitmap already loaded in the List!
    AsyncImage(
        model = ImageRequest.Builder(context)
            .data(productUrl)
            .placeholderMemoryCacheKey(canonicalKey) // Instant zero-decode reuse!
            .memoryCacheKey(canonicalKey)
            .diskCacheKey(productUrl.substringBefore("?"))
            .build(),
        contentDescription = product.title
    )
  • और अब, हां.

  • मैं पिछले उदाहरण पर वापस जाता हूं.

  • नमस्ते, मेरे ऐप्लिकेशन का डेवलपर अलग है.

  • कुछ हिस्सा व्यू का इस्तेमाल कर रहा है. इसलिए, यह इमेज लोडर के तौर पर Glide का इस्तेमाल कर रहा है.

  • इनमें से कुछ Coil का इस्तेमाल कर रहे हैं, क्योंकि वे Compose का इस्तेमाल कर रहे हैं.

  • तो क्या यह वही है जिसके बारे में आपने अभी बताया था. इमेज लोडर, कैश मेमोरी में डेटा सेव करने में हमारी मदद करता है. इसलिए, क्या एक से ज़्यादा इमेज लोडर होने पर कोई गड़बड़ी हो सकती है?

  • ज़रूर, इसमें कोई गड़बड़ी है.

  • इसलिए, इमेज लोडर के लिए, वे डिफ़ॉल्ट रूप से हीप मेमोरी साइज़ के X% हिस्से को डिफ़ॉल्ट कैश मेमोरी साइज़ के तौर पर इस्तेमाल करेंगे.

  • इसलिए, अगर आपके पास एक इमेज लोडर है, तो वह आपकी मेमोरी का X% इस्तेमाल करता है.

  • अगर आपके पास दो इमेज लोडर हैं, तो मेमोरी दोगुनी हो जाएगी.

  • अगर आपके पास तीन इमेज लोडर हैं, तो यह तीन गुना हो जाएगा.

  • अगर आपका इमेज लोडर एक ही पूल को शेयर नहीं करता है, तो भी ऐसा ही होगा.

  • जैसे, प्रॉडक्ट पेज में, मैं Glide का इस्तेमाल करके इमेज लोड करता हूं. इसके बाद, चेकआउट पेज में, Coil का इस्तेमाल करके वही इमेज लोड की जाएगी.

  • हालांकि, यादें में दो इमेज दिखेंगी.

  • यह सही नहीं है.

  • हां, इसलिए इसे ठीक करने के लिए, आम तौर पर हम कैश मेमोरी के लिए सिर्फ़ एक इमेज लोडर या एक शेयर किए गए पूल का इस्तेमाल करते हैं.

  • लेकिन अगर इसमें बहुत ज़्यादा इंजीनियरिंग का काम है, तो मैं इसे नहीं कर पाऊंगा.

  • ओह, इसे ठीक करने का एक आसान तरीका यह होगा कि मैं यह मेज़र करूं कि इस इमेज लोडर से इमेज का कितना प्रतिशत हिस्सा हैंडल किया जाएगा, दूसरे इमेज लोडर से इमेज का कितना प्रतिशत हिस्सा हैंडल किया जाएगा, और अलग-अलग इमेज लोडर के लिए वेट सेट करूं, जैसा कि इस कोड में किया गया है.

    val totalBudgetBytes = computeAdaptiveCacheBytes(context)
    val numberOfLoaders = 2 // e.g., Team A (Glide) + Team B (Coil)
    
    // Approach A (With Stats): Weight by image traffic (70% Team A / 30% Team B)
    val loaderABudget = (totalBudgetBytes * 0.70).toInt()
    val loaderBBudget = (totalBudgetBytes * 0.30).toInt()
    
    // Approach B (Simple Fix without stats): Divide by number of loaders!
    val simpleSplitBudget = totalBudgetBytes / numberOfLoaders
    
    MemoryCache.Builder()
        .maxSizeBytes(simpleSplitBudget)
        .build()
  • मैं loaderABudget को 70% और loaderBBudget को 30% पर सेट कर सकता हूं. यह एक और तरीका है.

  • अगर आपको वाकई नहीं पता कि हर लोडर कितनी इमेज हैंडल करेगा, तो भी बेहतर होगा कि आप उन्हें बांट दें.

  • मेरे पास दो इमेज लोडर हैं, तो दो से भाग दें; तीन इमेज लोडर हैं, तो तीन से भाग दें. डिफ़ॉल्ट वैल्यू का इस्तेमाल न करें, क्योंकि इससे मेमोरी का ज़्यादा इस्तेमाल होगा.

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

  • इसलिए, आम तौर पर हम 50 इमेज या 50 एमबी की इमेज को कैश मेमोरी में सेव कर सकते हैं.

  • लेकिन, अगर ऐप्लिकेशन बैकग्राउंड में चला जाए, तो क्या होगा?

  • अगर ऐप्लिकेशन बैकग्राउंड में है, तो हो सकता है कि उपयोगकर्ता ब्राउज़ न कर रहा हो.

  • अगर उपयोगकर्ता ब्राउज़ नहीं कर रहा है, तो क्या मुझे अब भी इस मेमोरी में कैश मेमोरी में सेव की गई इमेज की इतनी संख्या रखनी चाहिए?

  • नहीं, हमें इसे रिलीज़ करना चाहिए.

  • हां, हमें onTrimMemory कॉलबैक का पालन करना चाहिए.

  • हां, असल में कई ऐप्लिकेशन, फ़िलहाल onTrimMemory कॉलबैक को लागू नहीं करते या उसका पालन नहीं करते.

  • onTrimMemory कॉलबैक के लिए, हमें दो सिग्नल का ध्यान रखना चाहिए.

  • पहला है UI_HIDDEN. यह तब होता है, जब उपयोगकर्ता होम बटन दबाता है. हालांकि, यह होम बटन दबाने के तुरंत बाद नहीं होता, बल्कि होम बटन दबाने के कुछ समय बाद होता है. इसका मतलब है कि "आपका ऐप्लिकेशन असल में ऐसी स्थिति में है जहां उपयोगकर्ता को कोई यूज़र इंटरफ़ेस (यूआई) नहीं दिखता."

  • हम यह उम्मीद कर सकते हैं कि "अरे, उपयोगकर्ता आपके ऐप्लिकेशन का इस्तेमाल नहीं कर रहा है.

  • आपको ओएस के लिए संसाधन रिलीज़ करने चाहिए."

  • इसलिए, हमें कैश मेमोरी का साइज़ कम करना चाहिए.

  • दूसरा है TRIM_MEMORY_BACKGROUND. इसका मतलब है कि ऐप्लिकेशन लंबे समय से बैकग्राउंड में है और अब ओएस को कुछ संसाधनों की ज़रूरत है.

  • इस स्टेज में, आपको ज़्यादा से ज़्यादा मेमोरी खाली करनी चाहिए. यह करीब 100% होनी चाहिए.

  • ऐसा करने से, ओएस की वजह से आपके ऐप्लिकेशन के बंद होने का जोखिम भी कम हो जाता है.

  • Because like, "Hey, they want memory, you give them, then that OS handle it."

  • अगर नहीं, तो ओएस के पास कोई विकल्प नहीं होता. उसे कुछ न कुछ करना ही पड़ता है.

बैकग्राउंड में मेमोरी के इस्तेमाल को बढ़ने से रोकना

  • Fung Lam

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

  • हालांकि, मैंने देखा कि ऐप्लिकेशन बैकग्राउंड में ज़्यादा मेमोरी इस्तेमाल कर रहे थे.

  • क्यों?

  • इसलिए, मैं रिसर्च करता हूं.

  • मैंने इसकी वजह जानने की कोशिश की.

  • इसकी एक वजह यह है कि "अरे, उनके ऐप्लिकेशन में कुछ ऐनिमेशन या कैरसेल है.

  • उदाहरण के लिए, वे हर 15 सेकंड में एक नई इमेज डाउनलोड करते हैं और उपयोगकर्ता को एक नई इमेज दिखाते हैं."

  • हालांकि, डेवलपर ने ऐप्लिकेशन के बैकग्राउंड में जाने पर ऐनिमेशन को बंद नहीं किया.

  • इसलिए, ऐप्लिकेशन के बैकग्राउंड में होने पर भी कोड चलता रहता है. साथ ही, नई इमेज मिलती रहती है, उसे डिकोड किया जाता है, और ज़्यादा मेमोरी का इस्तेमाल किया जाता है.

  • इसलिए, ऐप्लिकेशन को ऐसा नहीं करना चाहिए.

  • हाँ।

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

  • इसलिए, अगर आपको गतिविधि के लाइफ़ साइकल के बारे में पता है, तो onPause, onStop इवेंट मौजूद हैं. पक्का करें कि आपने ऐनिमेशन को रोकने के लिए, onStop, onPause, onDestroyView को लागू किया हो. हां, इमेज पुल करने के अनुरोधों को रोकने के लिए या काम से जुड़ी अन्य चीज़ों को रोकने के लिए, जिन पर उपयोगकर्ता का ध्यान खींचने की ज़रूरत नहीं है.

    override fun onStop() {
        super.onStop()
        // 1. Stop animations so they don't decode next frames in background!
        bannerAnimationView.cancelAnimation()
        animatedImageDrawable?.stop()
    
        // 2. Cancel next-image buffering / prefetch queues!
        nextImagesBufferingJob?.cancel()
        Glide.with(this).pauseRequests()
    }
    
    override fun onDestroyView() {
        super.onDestroyView()
        bannerAnimationView.clearAnimation() // Release resources!
    }

याददाश्त को बेहतर बनाने के लिए 3R फ़्रेमवर्क

  • Fung Lam

    मुझे पता है कि मैंने आपके साथ कई मामलों पर बात की है. हालांकि, मैंने कहा था, "मेरे पास 15 से ज़्यादा मामले हैं."

  • मुझे पता है कि अगर मैंने आपके साथ सभी मामलों के बारे में बात की, तो हो सकता है कि आप सब कुछ भूल जाएं.

  • घर वापस जाने के बाद, Google पर बस यह खोजें, "अरे, मैं याददाश्त से जुड़ी समस्याओं को कैसे ठीक करूं?"

  • इसलिए, मैं आपके लिए इसे याद रखना आसान बना देती हूँ.

  • हाँ।

  • मैं इसे जाने-माने 3R फ़्रेमवर्क से लिंक करूंगा, ताकि आपको इन्हें याद रखने में मदद मिल सके.

  • मुझे लगता है कि सभी ने इस 3R फ़्रेमवर्क के बारे में सुना होगा.

  • पहला तरीका है, इमेज लोड करते समय मेमोरी का इस्तेमाल कम करना.

  • बिल्कुल, जैसा कि मैंने बताया, हम इमेज को डाउनसैंपल कर सकते हैं. सर्वर से इमेज मिलने पर, हम उसका सही डाइमेंशन पा सकते हैं.

  • हम कलर डेप्थ को ऑप्टिमाइज़ करते हैं या अगर मुमकिन हो, तो हार्डवेयर बिटमैप का इस्तेमाल करते हैं.

  • अगर सीडीएन का इस्तेमाल नहीं किया जा रहा है, तो सीडीएन का इस्तेमाल करके देखें.

  • इसलिए, जब हम सर्वर से इमेज लेते हैं, तो हमें सिर्फ़ वही इमेज मिलती है जो साइज़ के हिसाब से सबसे सही होती है.

  • इमेज को फिर से इस्तेमाल करने के लिए, हम कैश मेमोरी का इस्तेमाल करते हैं. इससे मेमोरी में लोड की गई इमेज का फिर से इस्तेमाल किया जा सकेगा और हमारी मेमोरी में डुप्लीकेट बिट मैप इमेज नहीं होगी.

  • साथ ही, अपने कोड में कई इमेज लोडर न रखें, क्योंकि इससे कोड की परफ़ॉर्मेंस कम हो जाती है.

  • कम करना, दोबारा इस्तेमाल करना, और तीसरा क्या है?

  • क्या आपको पता है?

  • रीसाइकल करें.

  • फिर से कोशिश करें?

  • रीसाइकल, हां, रीसाइकल.

  • हां, हमने प्राइमरी स्कूल में कम इस्तेमाल करना, दोबारा इस्तेमाल करना, और रीसाइकल करना सीखा. हालांकि, हमने प्राइमरी स्कूल में कोडिंग नहीं सीखी.

  • हां, रीसाइकल करना, हां.

  • हां, यह मेमोरी को रिलीज़ करने के बारे में है, ताकि अन्य ऐप्लिकेशन या ओएस, मेमोरी का इस्तेमाल कर सकें.

  • रीसाइकल करने से जुड़ी चीज़ें भी हैं.

  • सबसे पहले, मैंने onTrimMemory इवेंट के बारे में बताया था. इसके तहत, ओएस आपको दो सिग्नल भेजेगा. पहला सिग्नल तब भेजा जाएगा, जब आपका यूज़र इंटरफ़ेस (यूआई) छिपा हुआ होगा और दूसरा तब भेजा जाएगा, जब ओएस को वाकई संसाधनों की ज़रूरत होगी.

  • हाँ, इस अनुरोध को पूरा करने की कोशिश करो.

  • इसके अलावा, अगर आपके पास ऐनिमेशन, इमेज लोडर या फ़ोरग्राउंड में होने वाला कोई दूसरा काम है, तो पक्का करें कि onPause, onStop इवेंट के दौरान उसे रोक दिया जाए.

  • इसलिए, कम करें, दोबारा इस्तेमाल करें, और रीसाइकल करें.

  • याद रखना आसान है, है न?

डेवलपर के लिए डायग्नोस्टिक टूलकिट और एआई की मदद से विश्लेषण

  • Fung Lam

    अब हम टीवी मैन्युअल के कम दिलचस्प हिस्से पर वापस जा रहे हैं.

  • मेमोरी से जुड़ी इस समस्या का पता लगाने और उसे असरदार तरीके से मापने के लिए, हम अलग-अलग टूलकिट का इस्तेमाल कैसे करते हैं?

  • पहला है Google Play Console, Android की ज़रूरी जानकारी, और Reporting API.

  • हां, Google Play Console में 90वें पर्सेंटाइल की जांच करें.

  • आप अभी कहां हैं?

  • अगर आपको वेब पेज पर नहीं जाना है, तो Reporting API का इस्तेमाल करें.

  • वैल्यू पाने के लिए, अब भी एपीआई का इस्तेमाल किया जा सकता है.

  • हां, पक्का करें कि थ्रेशोल्ड 200 एमबी और 400 एमबी हो.

  • पक्का करें कि आपने तय सीमा से ज़्यादा बार अनुरोध न किया हो.

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

    adb shell dumpsys meminfo <pkg>  # watch Native Heap!
    adb shell am send-trim-memory <pkg> UI_HIDDEN
  • अगर Android Studio का इस्तेमाल किया जा रहा है, तो अच्छी बात है.

  • हालांकि, यह हमेशा आपका अच्छा दोस्त होता है.

  • हीप डंप को कैप्चर करने के लिए, Android Studio प्रोफ़ाइलर का इस्तेमाल किया जा सकता है. इससे आपको एक यूज़र इंटरफ़ेस (यूआई) मिलेगा, जिसमें आपको यह जानकारी मिलेगी कि असल में मेमोरी का इस्तेमाल कितना है और मेमोरी का बंटवारा कितना है.

  • ज़ाहिर है, हम Android Studio में Gemini के साथ एआई या Android की अन्य सुविधाओं के बारे में बात करते हैं.

  • इससे आपको हीप डंप का विश्लेषण करने और Perfetto SQL ट्रेस का इस्तेमाल करके बिटमैप ढूंढने में मदद मिलती है. इससे आम तौर पर यह पता चलता है कि कैश मेमोरी का मालिक कौन है.

  • क्या मेरी इमेज, Glide या Coil से लोड की गई है?

  • क्या मेरे ऐप्लिकेशन में कोई और मेमोरी लीक है?

  • मुझे पता है कि आप में से कुछ लोग कहेंगे, "अरे, मैं तो अब आईडीई का इस्तेमाल नहीं करता.

  • मैं एक प्रॉम्प्ट इंजीनियर हूं.

  • मैं कोड लिखने के लिए, एआई एजेंट को प्रॉम्प्ट भेजता हूं."

  • हां, मुझे पता है.

  • मैं अपने खाली समय में वाइब कोडिंग भी करता हूं.

  • इसलिए, मैं आपके साथ एक सैंपल शेयर कर रहा हूं.

  • हां, यह उस प्रॉम्प्ट का हिस्सा है जिसका इस्तेमाल मैं 500 ऐप्लिकेशन की रिसर्च के लिए करता हूं.

  • हां, बस कुछ हिस्सा.

  • आपको पता है कि स्क्रीन बड़ी नहीं है.

  • अगर मैं ज़्यादा डालता, तो आपको यह मुश्किल से ही दिखता.

  • हालांकि, इससे आपको यह आइडिया मिलता है कि एआई का इस्तेमाल करके, मेमोरी के इस्तेमाल को कैप्चर करने की प्रोसेस को कैसे ऑटोमेट किया जा सकता है. इसमें हीप डंप को कैप्चर करना, उसका विश्लेषण करना, और आपको नतीजे उपलब्ध कराना शामिल है.

  • इसके अलावा, मैं यहां एक और वाक्य जोड़ सकता हूं. जैसे, "कृपया मेरे कोड को ठीक करने के लिए कोड भी दें."

  • हां, मुझे उम्मीद है कि इससे आपका डर कम हो सकता है. जैसे, "अरे, मेमोरी एक बड़ा डोमेन है.

  • मैंने अपनी यूनिवर्सिटी में कंप्यूटर साइंस की पढ़ाई के दौरान, ऑपरेटिंग सिस्टम या कंप्यूटर सिस्टम आर्किटेक्चर नहीं पढ़ा.

  • लेकिन असल में, यह इतना डरावना नहीं है, यह इतना मुश्किल नहीं है."

  • हां, इससे अपने ऐप्लिकेशन का विश्लेषण करना आसान हो जाता है.

  • कृपया इसे आज़माएं.

  • हालांकि, एआई से गलतियां हो सकती हैं. इसलिए, मेमोरी के इस्तेमाल के बारे में बुनियादी जानकारी होना अब भी ज़रूरी है. साथ ही, यह जानना भी ज़रूरी है कि ओएस, मेमोरी को कैसे ऐलोकेट करता है.

  • इसलिए, मेरी बातचीत में शामिल हों और YouTube पर हमारा वीडियो देखें.

खास बातें और खास जानकारी

  • Fung Lam

    तो चलिए, एक बार रीकैप कर लेते हैं.

  • सबसे पहले, कम करें.

  • पक्का करें कि इमेज का साइज़ सही हो.

  • इमेज को छोटे-छोटे हिस्सों में बांट दिया जाता है, ताकि मेमोरी पर ज़्यादा लोड न पड़े. इससे सिर्फ़ वही इमेज मेमोरी में लोड होती है जो उपयोगकर्ता को दिखती है.

  • जब भी संभव हो, हार्डवेयर bitmapConfig या RGB_565 का इस्तेमाल करें.

  • इमेज को फिर से इस्तेमाल करें. इसके लिए, पक्का करें कि आपके पास कैश मेमोरी में सेव करने की रणनीति हो. साथ ही, इमेज लोडर का इस्तेमाल करें, ताकि मेमोरी में डुप्लीकेट बिट मैप की संख्या कम की जा सके.

  • साथ ही, एक से ज़्यादा बिट मैप इमेज का इस्तेमाल न करें. भले ही, आपने उन इमेज लोडर के डिफ़ॉल्ट कैश साइज़ को ओवरराइट करने की कोशिश की हो.

  • हम न तो उन्हें दोबारा इस्तेमाल करते हैं और न ही रीसाइकल करते हैं.

  • हाँ।

  • आपके ऐप्लिकेशन की मेमोरी को मैनेज करने की सुविधा, ऐप्लिकेशन की स्थिति के हिसाब से काम करनी चाहिए.

  • अगर यूज़र इंटरफ़ेस (यूआई) छिपा हुआ है, तो आपको कम मेमोरी का इस्तेमाल करना चाहिए.

  • अगर ओएस आपसे मेमोरी खाली करने के लिए कहता है, तो ज़्यादा से ज़्यादा मेमोरी खाली करें.

  • साथ ही, संसाधनों का इस्तेमाल कम से कम करें. भले ही, वे बिटमैप, पावर या कंप्यूटेशनल संसाधन हों.

  • हां, बैनर का टाइमर रोकें, ऐनिमेशन रोकें, और इमेज पूलिंग रोकें.

  • आखिर में, यह पक्का करें कि आप मॉनिटर करें.

  • Google Play Console पर नियमित तौर पर जाएं.

  • पक्का करें कि यह एक प्रैक्टिस हो.

  • इससे आपको यह समझने में मदद मिलेगी कि आपके ऐप्लिकेशन के उपयोगकर्ताओं की कुल संख्या में से, 90वें पर्सेंटाइल के लिए मेमोरी के इस्तेमाल की मौजूदा स्थिति क्या है?

  • इससे आपको समस्या का जल्द पता लगाने में भी मदद मिलेगी.

  • हाँ।

  • लोकल लेवल पर प्रोफ़ाइलिंग करने के लिए, Android Studio के मेमोरी प्रोफ़ाइलर का इस्तेमाल किया जा सकता है.

  • हमारे पास कुछ एडीबी कमांड भी हैं.

  • हमारे पास Android स्किल भी है.

  • हालांकि, अगर आपको असल उपयोगकर्ताओं के आंकड़े देखने हैं, तो Google Play Console पर जाएं.

  • इसके अलावा, Google Play Reporting API भी है. इसकी मदद से, Play Console में लॉग इन किए बिना ही एपीआई का इस्तेमाल करके डेटा हासिल किया जा सकता है.

  • हमेशा की तरह, अगर आपको ज़्यादा जानकारी चाहिए, तो developer.android.com/memory पर जाएं.

  • इससे कचरा कम करें, दोबारा इस्तेमाल करें, और रीसाइकल करें.

  • हम एक बेहतर Android नेटवर्क बना सकते हैं. मुझे उम्मीद है कि हम सब मिलकर एक बेहतर Android नेटवर्क बना सकते हैं, ताकि हम अपनी चुनौतियों का सामना कर सकें.

  • धन्यवाद और कोडिंग करते रहें.

  • मैं जल्द ही ऑफ़िस के बाहर उपलब्ध रहूंगा. इसलिए, अगर आपका कोई सवाल है, तो बेझिझक मुझसे पूछें.

  • अगले स्पीकर को आने में थोड़ा समय लगेगा. इसलिए, कृपया इंतज़ार करें. बहुत-बहुत धन्यवाद.

कोड

कोड स्निपेट

"केस स्टडी:बिटमैप का साइज़ बदलना और उन्हें डिकोड करना" में 11: 50 पर Kotlin स्निपेट
// 1. Ask CDN for the exact UI card dimensions (e.g. 540x675)
val sizedUrl = "$cdnBaseUrl?w=$cardWidthPx&h=$cardHeightPx&fmt=webp"

// 2. Enforce exact downsampling + Hardware Bitmap config
AsyncImage(
    model = ImageRequest.Builder(LocalContext.current)
        .data(sizedUrl)
        .size(cardWidthPx, cardHeightPx) // Never use Size.ORIGINAL!
        .precision(Precision.EXACT)      // Downsample to exact card size
        .bitmapConfig(Bitmap.Config.HARDWARE)
        .build(),
    contentDescription = product.title
)
"केस स्टडी:बिटमैप का साइज़ तय करना और उन्हें डिकोड करना" में 14: 45 पर Kotlin स्निपेट
// Query active window bounds instead of hardcoding 1080 / 1920
val bounds = WindowMetricsCalculator.getOrCreate()
    .computeCurrentWindowMetrics(activity).bounds

// Clamp target dimensions so Bitmap NEVER exceeds the active window
val safeWidth  = minOf(requestedWidthPx,  bounds.width())
val safeHeight = minOf(requestedHeightPx, bounds.height())

val bitmap = Bitmap.createBitmap(safeWidth, safeHeight, config)
"मेमोरी, डुप्लीकेट, और कैश मेमोरी मैनेज करना" में 16:51 पर Kotlin स्निपेट
// Strip volatile query tokens (?from=list / ?sig=...) for cache key
val canonicalKey = MemoryCache.Key(productUrl.substringBefore("?"))

// On Checkout Screen: reuse the 200x200 Bitmap already loaded in the List!
AsyncImage(
    model = ImageRequest.Builder(context)
        .data(productUrl)
        .placeholderMemoryCacheKey(canonicalKey) // Instant zero-decode reuse!
        .memoryCacheKey(canonicalKey)
        .diskCacheKey(productUrl.substringBefore("?"))
        .build(),
    contentDescription = product.title
)
"मेमोरी, डुप्लीकेट, और कैश मेमोरी मैनेज करना" में 18:17 पर Kotlin स्निपेट
val totalBudgetBytes = computeAdaptiveCacheBytes(context)
val numberOfLoaders = 2 // e.g., Team A (Glide) + Team B (Coil)

// Approach A (With Stats): Weight by image traffic (70% Team A / 30% Team B)
val loaderABudget = (totalBudgetBytes * 0.70).toInt()
val loaderBBudget = (totalBudgetBytes * 0.30).toInt()

// Approach B (Simple Fix without stats): Divide by number of loaders!
val simpleSplitBudget = totalBudgetBytes / numberOfLoaders

MemoryCache.Builder()
    .maxSizeBytes(simpleSplitBudget)
    .build()
"बैकग्राउंड में मेमोरी के इस्तेमाल को बढ़ने से रोकना" में 22:05 पर Kotlin स्निपेट
override fun onStop() {
    super.onStop()
    // 1. Stop animations so they don't decode next frames in background!
    bannerAnimationView.cancelAnimation()
    animatedImageDrawable?.stop()

    // 2. Cancel next-image buffering / prefetch queues!
    nextImagesBufferingJob?.cancel()
    Glide.with(this).pauseRequests()
}

override fun onDestroyView() {
    super.onDestroyView()
    bannerAnimationView.clearAnimation() // Release resources!
}
"डेवलपर के लिए डाइग्नोस्टिक टूलकिट और एआई की मदद से विश्लेषण" में 25:17 पर शेल स्निपेट
adb shell dumpsys meminfo <pkg>  # watch Native Heap!
adb shell am send-trim-memory <pkg> UI_HIDDEN