मेमोरी लिमिटर

Android 17 और इसके बाद के वर्शन में, मेमोरी लिमिटर की सुविधा काम करती है. यह एक सिस्टम सर्विस है. यह Linux cgroup v2 का इस्तेमाल करने वाली ऐप्लिकेशन प्रोसेस की मेमोरी के इस्तेमाल पर नज़र रखती है और उसे सीमित करती है. मेमोरी लिमिटर, किसी ऐप्लिकेशन को सिस्टम की ज़्यादा मेमोरी इस्तेमाल करने से रोकता है. इससे सिस्टम की मेमोरी पर पड़ने वाला दबाव कम होता है. साथ ही, यह ज़रूरी प्रोसेस को मेमोरी से बाहर निकालने (ओओएम) से रोकता है.

मैकेनिज़्म

मेमोरी लिमिटर, ऐक्टिविटी मैनेजर सर्विस (एएमएस) के साथ इंटिग्रेट होता है. इससे प्रोसेस के लाइफ़साइकल इवेंट और स्थिति में होने वाले बदलावों को ट्रैक किया जा सकता है. मेमोरी लिमिटर, Linux कर्नल cgroup v2 फ़ाइल सिस्टम का इस्तेमाल करके मेमोरी की सीमाएं लागू करता है.

मेमोरी लिमिटर का इस्तेमाल करने के लिए, डिवाइस के कर्नल को cgroup v2 और memory कंट्रोलर के साथ काम करना चाहिए. यह सेवा, खास तौर पर इन एट्रिब्यूट पर निर्भर करती है:

memory.high
सॉफ़्ट लिमिट. सीमा से ज़्यादा होने पर, प्रोसेस को थ्रॉटल कर दिया जाता है और कर्नल, उससे मेमोरी वापस पाने की कोशिश करता है.
memory.swap.max
इससे प्रोसेस के लिए, स्वैप स्पेस के इस्तेमाल की सीमा तय की जाती है.

ऐप्लिकेशन पर असर

जिन ऐप्लिकेशन में मेमोरी की सीमाएं पार नहीं की जाती हैं उन पर MemoryLimiter का कोई असर नहीं पड़ता.

जब कोई ऐप्लिकेशन अपनी memory.high सीमा से ज़्यादा मेमोरी इस्तेमाल करता है, तो कर्नल ऐप्लिकेशन की फ़ाइल-बैक मेमोरी को हटा देता है. साथ ही, ऐप्लिकेशन को सीमा के अंदर रखने के लिए, उसकी ऐनॉनमस मेमोरी को स्वैप कर देता है. ऐप्लिकेशन को बंद करने और स्वैप करने की वजह से, ऐप्लिकेशन धीरे चल सकता है.

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

प्रोसेस मॉनिटर करना

मेमोरी लिमिटर, डिफ़ॉल्ट रूप से ऐप्लिकेशन प्रोसेस (यूआईडी >= 10000) की निगरानी करता है. सिस्टम प्रोसेस को आम तौर पर छूट दी जाती है, ताकि मुख्य सिस्टम की स्थिरता की पुष्टि करने में मदद मिल सके.

मेमोरी लिमिटर, प्रोसेस की स्थिति के आधार पर मेमोरी की सीमाएं तय करता है:

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

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

यहां दी गई टेबल में, प्रोसेस की अलग-अलग स्थितियों को मेमोरी की सीमाओं के साथ मैप किया गया है:

प्रोसेस की स्थितिमेमोरी की सीमा
PERSISTENTअप्रतिबंधित
PERSISTENT_UIअप्रतिबंधित
TOPज़्यादा लोगों को दिखे
BOUND_TOPज़्यादा लोगों को दिखे
FOREGROUND_SERVICEनहीं दिखेगा
BOUND_FOREGROUND_SERVICEनहीं दिखेगा
IMPORTANT_FOREGROUNDज़्यादा लोगों को दिखे
IMPORTANT_BACKGROUNDनहीं दिखेगा
TRANSIENT_BACKGROUNDनहीं दिखेगा
BACKUPनहीं दिखेगा
SERVICEनहीं दिखेगा
RECEIVERनहीं दिखेगा
TOP_SLEEPINGज़्यादा लोगों को दिखे
HEAVY_WEIGHTनहीं दिखेगा
HOMEनहीं दिखेगा
LAST_ACTIVITYनहीं दिखेगा
CACHED_ACTIVITYसंचित
CACHED_ACTIVITY_CLIENTसंचित
CACHED_RECENTसंचित
CACHED_EMPTYसंचित

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

जब कोई प्रोसेस, असाइन की गई memory.high की सीमा से ज़्यादा मेमोरी का इस्तेमाल करती है, तो Memory Limiter उस इवेंट का पता लगाता है. साथ ही, डीबग करने से जुड़ी कार्रवाइयां ट्रिगर कर सकता है. जैसे, मेमोरी प्रोफ़ाइल कैप्चर करना या statsd में गड़बड़ी लॉग करना.

कॉन्फ़िगरेशन

vendor पार्टिशन पर मौजूद एक्सएमएल फ़ाइल का इस्तेमाल करके, मेमोरी लिमिटर को कॉन्फ़िगर करें. कॉन्फ़िगरेशन की मदद से, डिवाइस की मेमोरी से जुड़ी खास सीमाओं के आधार पर, मेमोरी की कुल सीमाओं को अडजस्ट किया जा सकता है.

  • फ़ाइल पाथ: /vendor/etc/memory-limiter-config.xml

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

एक्सएमएल फ़ॉर्मैट

कॉन्फ़िगरेशन फ़ाइल, memory-limiter-config.xsd में तय किए गए स्कीमा के मुताबिक होती है. इस फ़ाइल की मदद से, सीमा के कई सेट तय किए जा सकते हैं. सेवा, डिवाइस में उपलब्ध RAM के आधार पर सबसे सही सेट चुनती है. मेमोरी की सभी वैल्यू, मेबिबाइट (MiB) की इकाइयों में तय की जाती हैं.

<MemoryLimiterConfig>
  <version>1</version>
  <configList>
    <limitSet>
      <!-- Limits for a phone with at least 14G of ram: 8G/4G/4G/4G -->
      <minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
      <memVisible>8192</memVisible>
      <memNotVisible>4096</memNotVisible>
      <swapVisible>4096</swapVisible>
      <swapNotVisible>4096</swapNotVisible>
    </limitSet>
  </configList>
</MemoryLimiterConfig>
version
कॉन्फ़िगरेशन के वर्शन की पहचान करने वाला पॉज़िटिव पूर्णांक. यह 1 होना चाहिए.
minimumRequiredMemTotal
इस सीमा को लागू करने के लिए, सिस्टम में कम से कम इतनी मेमोरी उपलब्ध होनी चाहिए.
memVisible
विज़िबल प्रोसेस के लिए मेमोरी की सीमा (memory.high) तय की जाती है.
memNotVisible
यह मेमोरी की वह सीमा (memory.high) है जो उन प्रोसेस के लिए तय की जाती है जो नहीं दिखती हैं.
swapVisible
विज़िबल प्रोसेस के लिए स्वैप की सीमा (memory.swap.max) तय की जाती है.
swapNotVisible
प्रोसेस के लिए स्वैप की सीमा (memory.swap.max) तय की जाती है.

डिवाइस की मेमोरी की सीमा से जुड़े दिशा-निर्देश

अपने डिवाइस के लिए मेमोरी की सीमाएं कॉन्फ़िगर करते समय, इन दिशा-निर्देशों का पालन करें:

  • हार्डवेयर की क्षमताओं के हिसाब से सीमाएं तय करना: डिवाइस बनाने वाली कंपनियां, ऐसी सीमाएं सेट कर सकती हैं जो उनके डिवाइस के हार्डवेयर की क्षमताओं के हिसाब से तय की गई हों. Android, इन रेंज का सुझाव देता है:

    • दिखने वाली प्रोसेस: कुल फ़िज़िकल रैम का कम से कम 1/2 और ज़्यादा से ज़्यादा 2/3 हिस्सा.
    • प्रोसेस नहीं दिख रही हैं: कुल फ़िज़िकल रैम का 1/4 से 1/3 हिस्सा. ओईएम, डिवाइस की क्षमताओं और इस्तेमाल के उदाहरणों के आधार पर अलग-अलग फ़ैसले ले सकते हैं.
  • ऐप्लिकेशन के लिए कोई रनटाइम एपीआई नहीं है: Android 17 (SDK 37) के बाद से, ऐप्लिकेशन के पास रन टाइम पर मेमोरी की सीमाओं के बारे में क्वेरी करने के लिए कोई एपीआई नहीं है. ओईएम को इस बात का ध्यान रखना चाहिए और सीमाएं बहुत कम सेट नहीं करनी चाहिए. इससे यह पक्का किया जा सकेगा कि ऐप्लिकेशन, इस्तेमाल के सामान्य मामलों में सीमाओं तक न पहुंचें.

  • यूनिवर्सल कॉन्फ़िगरेशन: ये सीमाएं, डिवाइस पर मौजूद सभी ऐप्लिकेशन प्रोसेस पर लागू होती हैं. इनमें पहले से इंस्टॉल किए गए ऐप्लिकेशन भी शामिल हैं. कुछ ऐप्लिकेशन को इन सीमाओं से छूट देने के लिए, अनुमति पा चुके ऐप्लिकेशन की कोई सूची नहीं है.

कॉन्फ़िगरेशन में बदलाव करना

सिस्टम-वाइड सीमाओं को बदलने के लिए, यह तरीका अपनाएं:

  1. /vendor/etc/memory-limiter-config.xml में बदलाव करें.
  2. बदलावों को लागू करने के लिए, डिवाइस को रीबूट करें या system_server को रीस्टार्ट करें.

शेल कमांड

am memory-limiter कमांड की मदद से, डेवलपर और आप डेवलपमेंट और टेस्टिंग के लिए, रन टाइम में सेवा से इंटरैक्ट कर सकते हैं:

am memory-limiter <SUB-COMMAND>

स्थिति

status सब-कमांड, मेमोरी लिमिटर की ऑपरेशनल स्थिति की जानकारी देता है:

adb shell am memory-limiter status

आउटपुट का उदाहरण:

Memory limiter
  enabled                  monitoring=true          ignored=none
  visibleMem=1948MB        visibleSwap=974MB
  notVisibleMem=974MB      notVisibleSwap=487MB
  started=36               watched=36               watch-failed=0
  events=0                 processes=36             process-hwm=36

आउटपुट में ये मुख्य फ़ील्ड शामिल होते हैं:

monitoring
इससे पता चलता है कि लिमिटर, प्रोसेस पर नज़र रख रहा है या नहीं.
visibleMem और notVisibleMem
हर स्थिति के लिए, कैलकुलेट की गई मेमोरी की कुल सीमाएं दिखाएं.
events
किसी प्रोसेस के तय सीमा से ज़्यादा बार इस्तेमाल होने की संख्या.
processes
मॉनिटर की गई प्रोसेस की संख्या.

अनदेखा करें

ignore सब-कमांड, कुछ समय के लिए किसी यूआईडी या सभी प्रोसेस को सीमित होने से रोकती है. यह कार्रवाई, परफ़ॉर्मेंस की जांच करने या किसी ऐप्लिकेशन को उसकी सीमाएं पार करने की अनुमति देने के लिए काम आती है.

adb shell am memory-limiter ignore 10087  // Ignore a specific UID
adb shell am memory-limiter ignore all    // Ignore all processes (effectively disables limiting)
adb shell am memory-limiter ignore none   // Resume normal operation

मैन्युअल

manual सब-कमांड, किसी प्रोसेस (प्रोसेस आईडी या पीआईडी) के लिए कैलकुलेट की गई सीमाओं को बदल देती है. इसके लिए, मेगाबाइट (एमबी) में कस्टम वैल्यू का इस्तेमाल किया जाता है:

adb shell am memory-limiter manual 1234 1024   // Set a 1024 MB limit for PID 1234
adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234

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