Android 17 और इसके बाद के वर्शन में, मेमोरी लिमिटर की सुविधा उपलब्ध है. यह एक सिस्टम सर्विस है, जो Linux cgroup v2 का इस्तेमाल करके, ऐप्लिकेशन की प्रोसेस के लिए मेमोरी के इस्तेमाल की निगरानी करती है और उसे सीमित करती है. मेमोरी लिमिटर, अलग-अलग ऐप्लिकेशन को सिस्टम की ज़्यादा मेमोरी इस्तेमाल करने से रोकता है. इससे, सिस्टम की मेमोरी पर पड़ने वाला दबाव कम होता है. साथ ही, ज़रूरी प्रोसेस को मेमोरी से बाहर (OOM) करने से रोका जा सकता है.
मैकेनिज़्म
मेमोरी लिमिटर, प्रोसेस के लाइफ़साइकल इवेंट और स्थिति में होने वाले बदलावों को ट्रैक करने के लिए, Activity Manager Service (AMS) के साथ इंटिग्रेट होता है. मेमोरी लिमिटर, Linux कर्नल cgroup v2 फ़ाइल सिस्टम का इस्तेमाल करके, मेमोरी की सीमाएं लागू करता है.
मेमोरी लिमिटर का इस्तेमाल करने के लिए, डिवाइस के कर्नल में cgroup v2 और memory कंट्रोलर की सुविधा होनी चाहिए. यह सेवा, खास तौर पर इन एट्रिब्यूट पर निर्भर करती है:
memory.high- यह एक सॉफ़्ट लिमिट है. अगर यह सीमा पार हो जाती है, तो प्रोसेस को थ्रॉटल किया जाता है. साथ ही, कर्नल उससे मेमोरी वापस पाने की कोशिश करता है.
memory.swap.max- इससे, स्वैप स्पेस की उस सीमा का पता चलता है जिसका इस्तेमाल प्रोसेस कर सकती है.
ऐप्लिकेशन पर पड़ने वाला असर
मेमोरी लिमिटर का असर उन ऐप्लिकेशन पर नहीं पड़ता जो अपनी मेमोरी की सीमाओं से ज़्यादा मेमोरी इस्तेमाल नहीं करते.
जब कोई ऐप्लिकेशन, memory.high की सीमा पार कर लेता है, तो कर्नल, ऐप्लिकेशन की फ़ाइल-बैक मेमोरी को हटा देता है. साथ ही, ऐप्लिकेशन को सीमा में रखने के लिए, उसकी एनॉनिमस मेमोरी को स्वैप कर देता है. मेमोरी को हटाने और स्वैप करने की वजह से, ऐप्लिकेशन धीरे चल सकता है.
अगर ऐप्लिकेशन, एनॉनिमस मेमोरी को असाइन करता रहता है और डिवाइस में स्वैप स्पेस खत्म हो जाता है, तो ऐप्लिकेशन को मेमोरी असाइन नहीं की जा सकती. ऐसे में, ऐप्लिकेशन क्रैश हो सकता है.
प्रोसेस की निगरानी करना
मेमोरी लिमिटर, डिफ़ॉल्ट रूप से ऐप्लिकेशन की प्रोसेस (UID >= 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 की सीमा पार कर लेती है, तो मेमोरी लिमिटर को इस इवेंट का पता चल जाता है. इसके बाद, वह डीबग करने से जुड़ी कार्रवाइयां ट्रिगर कर सकता है. जैसे, मेमोरी प्रोफ़ाइल कैप्चर करना या statsd में गड़बड़ी लॉग करना.
कॉन्फ़िगरेशन
मेमोरी लिमिटर को कॉन्फ़िगर करने के लिए, vendor पार्टीशन पर मौजूद एक्सएमएल फ़ाइल का इस्तेमाल करें. कॉन्फ़िगरेशन की मदद से, डिवाइस की मेमोरी से जुड़ी खास पाबंदियों के आधार पर, मेमोरी की पूरी सीमाओं को ट्यून किया जा सकता है.
फ़ाइल का पाथ:
/vendor/etc/memory-limiter-config.xmlडिफ़ॉल्ट कॉन्फ़िगरेशन: अगर कॉन्फ़िगरेशन फ़ाइल नहीं मिलती है या उसे पढ़ा नहीं जा सकता या वह अमान्य है, तो मेमोरी लिमिटर बंद हो जाता है.
एक्सएमएल फ़ॉर्मैट
कॉन्फ़िगरेशन फ़ाइल, memory-limiter-config.xsd में तय किए गए स्कीमा के मुताबिक होती है. इस फ़ाइल की मदद से, सीमाओं के कई सेट तय किए जा सकते हैं. सेवा, डिवाइस की उपलब्ध रैम के आधार पर सबसे सही सेट चुनती है. मेमोरी की सभी वैल्यू, मेबिबाइट (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) है जो नहीं दिखने वाली प्रोसेस के लिए तय की जाती है.
कॉन्फ़िगरेशन में बदलाव करना
सिस्टम की सभी सीमाओं में बदलाव करने के लिए, यह तरीका अपनाएं:
/vendor/etc/memory-limiter-config.xmlमें बदलाव करें.- बदलावों को लागू करने के लिए, डिवाइस को रीबूट करें या
system_serverको रीस्टार्ट करें.
Shell कमांड
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
ignore सब-कमांड की मदद से, किसी यूआईडी या सभी प्रोसेस को कुछ समय के लिए, सीमा से बाहर रखा जा सकता है. यह कार्रवाई, परफ़ॉर्मेंस की जांच करने या किसी खास ऐप्लिकेशन को अपनी सीमाओं से ज़्यादा मेमोरी इस्तेमाल करने की अनुमति देने के लिए काम की है.
adb shell am memory-limiter ignore 10087 // Ignore a specific UIDadb shell am memory-limiter ignore all // Ignore all processes (effectively disables limiting)adb shell am memory-limiter ignore none // Resume normal operation
manual
manual सब-कमांड की मदद से, किसी खास प्रोसेस (प्रोसेस आईडी या पीआईडी के हिसाब से) के लिए, कैलकुलेट की गई सीमाओं को मेगाबाइट (एमबी) में कस्टम वैल्यू के साथ बदला जा सकता है:
adb shell am memory-limiter manual 1234 1024 // Set a 1024 MB limit for PID 1234adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234
मैन्युअल तरीके से किए गए बदलाव, सिर्फ़ प्रोसेस के लाइफ़साइकल पर लागू होते हैं. अगर प्रोसेस रीस्टार्ट होती है, तो वह अपनी स्थिति के आधार पर, डिफ़ॉल्ट सीमाओं पर वापस आ जाती है.