Android 17 और इसके बाद के वर्शन में, सिस्टम प्रोसेस की मेमोरी को मैनेज करने के लिए, Linux cgroup v2 के दो पूरक मैकेनिज़्म का इस्तेमाल किया जाता है. ये मैकेनिज़्म, ऐप्लिकेशन के लिए सामान्य तौर पर इस्तेमाल होने वाले मेमोरी लिमिटर के साथ काम करते हैं:
- सिस्टम डीमन के लिए सुरक्षा फ़्लोर (
SystemMemoryBudgetManagerके साथmemory.min): खुद को ट्यून करने वाले cgroup v2memory.minरिज़र्वेशन (हर डीमन के सेटल किए गए रेज़िडेंट वर्किंग सेट के 90% पर सेट किया गया है और कुल फ़िज़िकल रैम के 10% पर सेट किया गया है), मेमोरी के दबाव में अहम इंटरैक्टिव डीमन और शेल प्रोसेस (system_server,surfaceflinger, ग्राफ़िक्सcomposerएचएएल,audioserver,cameraserver,netd,SystemUI, और होम लॉन्चर) को सुरक्षित रखते हैं. साथ ही, स्टैटिकPinnerServicemlockफ़ाइल पिनिंग को बदलते हैं. - सिस्टम ऐप्लिकेशन के लिए मेमोरी की सीमाएं (
<memory-budget>के साथmemory.high): वर्कलोड के हिसाब से तय की गई cgroup v2memory.highकी सॉफ़्ट सीमाएं (आम तौर पर 30 एमबी से 190 एमबी तक) मेनिफ़ेस्ट फ़ाइलों में बताई गई हैं. ये सीमाएं, लगातार और बैकग्राउंड में चलने वाले सिस्टम ऐप्लिकेशन (Bluetooth,Nfc,CalendarProvider,Traceur,MediaProvider,:PhotoPicker,NetworkStack,AppSearch, औरTeleService) के लिए हैं. ये सीमाएं, ग्लोबल मेमोरी प्रेशर होने से पहले, कोल्ड फ़ाइल पेज कैश और पोस्ट-बर्स्ट एनॉनिमस हीप को पहले से ही वापस ले लेती हैं.
यहां दी गई टेबल में, दोनों तरीकों की तुलना की गई है:
| डाइमेंशन | सिस्टम डीमन प्रोटेक्शन फ़्लोर | सिस्टम ऐप्लिकेशन के लिए मेमोरी की सीमाएं |
|---|---|---|
| प्लैटफ़ॉर्म सर्विस | SystemMemoryBudgetManager |
MemoryLimiter |
| Cgroup v2 कंट्रोल | memory.min हार्ड प्रोटेक्शन फ़्लोर |
memory.high सॉफ़्ट रिक्लेम सीलिंग |
| टारगेट प्रोसेस | इंटरैक्टिव डीमन और शेल यूज़र इंटरफ़ेस (यूआई) के लिए, इंतज़ार का समय कम होना ज़रूरी है (system_server, surfaceflinger, composer एचएएल, audioserver, cameraserver, netd, SystemUI, और होम ऐप्लिकेशन) |
लगातार और हेडलेस सिस्टम ऐप्लिकेशन, कॉन्टेंट देने वाले, और बैकग्राउंड में चलने वाली सेवाएं (जैसे कि Bluetooth, Nfc, MediaProvider, NetworkStack, AppSearch, और TeleService) |
| साइज़िंग मॉडल | रन टाइम के दौरान, खुद को ट्यून करने की सुविधा (90% सेटल वर्किंग सेट, जो दुनिया भर में कुल रैम के 10% पर सीमित है). इसमें हर डिवाइस के लिए, ट्यूनिंग टेबल की संख्या शून्य होती है | डिक्लेरेटिव <memory-budget> मेनिफ़ेस्ट एक्सएमएल एट्रिब्यूट, रैम टियर, प्रोसेस की स्थिति, और डिसप्ले पिक्सल की संख्या के हिसाब से कैलिब्रेट किए गए हैं |
| मुख्य फ़ायदा | स्टैटिक PinnerService mlock फ़ाइल सूचियों को बदलते समय, मेमोरी प्रेशर की वजह से इंटरैक्टिव यूज़र इंटरफ़ेस (यूआई) में होने वाली रुकावट और वेकअप स्टॉल को रोकता है |
यह सुविधा, एक बार इस्तेमाल होने वाली फ़ाइल की कैश मेमोरी और बर्स्ट के बाद के हीप को लगातार हटाती है. इससे फ़ोरग्राउंड और कैश मेमोरी में सेव किए गए ऐप्लिकेशन के लिए, ज़्यादा फ़िज़िकल रैम उपलब्ध होती है |
<memory-budget> सिंटैक्स, एक्सएमएल एट्रिब्यूट, रनटाइम एपीआई, और ओएस मेमोरी अकाउंटिंग के बारे में ज़्यादा जानने के लिए, ऐप्लिकेशन के लिए मेमोरी बजट सेट करना और Android मेमोरी को समझना और उससे जुड़ी समस्या हल करना लेख पढ़ें.
SystemMemoryBudgetManager की मदद से, ज़रूरी इंटरैक्टिव डीमन को सुरक्षित रखना
SystemMemoryBudgetManager, उन प्रोसेस को फ़िज़िकल रैम में बनाए रखता है जो मेमोरी प्रेशर के दौरान, उपयोगकर्ता के इंटरैक्टिव पाथ पर सीधे तौर पर मौजूद होती हैं. mlock की मदद से, APK, ODEX, और VDEX फ़ाइलों की स्टैटिक सूची को मेमोरी में पिन करने के बजाय, SystemMemoryBudgetManager डाइनैमिक cgroup v2 memory.min फ़्लोर को इन प्रोसेस के लिए असाइन करता है. ऐसा PinnerService, config_defaultPinnerServiceFiles और config_pinnerHomePinBytes के लिए करता है:
- सिस्टम का मुख्य स्लाइस (
/sys/fs/cgroup/system):system_server,surfaceflinger, ग्राफ़िक्सcomposerएचएएल,audioserver,cameraserver, औरnetd. साथ ही,config_systemMemoryBudgetAdditionalSystemProcessesमें लिस्ट किया गया कोई भी नेटिव सिस्टम या वेंडर डीमन, जो किसी खास फ़ॉर्म-फ़ैक्टर के लिए हो. उदाहरण के लिए, एक्सआर डिवाइसों परandroid.hardware.perceptionhostऔरauracamerahal. - इंटरैक्टिव ऐप्लिकेशन स्लाइस (
/sys/fs/cgroup/apps): कॉन्फ़िगर किए गए SystemUI पैकेज (config_systemUi) की मुख्य प्रोसेस और मौजूदा उपयोगकर्ता के होम रोल होल्डर की मुख्य प्रोसेस.
होम रोल होल्डर के साथ-साथ config_systemUi को सुरक्षित रखने से, सभी डिवाइसों के साइज़, डाइमेंशन या कॉन्फ़िगरेशन पर कवरेज मिलती है. ऐसे डिवाइसों पर जहां config_systemUi एक लाइटवेट कंपैटिबिलिटी पैकेज है (जैसे कि Wear OS, जहां वॉच फ़ेस, सूचनाएं, और टाइल, Home ऐप्लिकेशन के अंदर चलती हैं), उपयोगकर्ता को दिखने वाले शेल को अब भी वर्किंग-सेट की पूरी सुरक्षा मिलती है. अगर होम इंटेंट, config_systemUi पैकेज पर रिज़ॉल्व होता है, तो प्रोसेस को एक बार सुरक्षित किया जाता है. हर पैकेज (processName == packageName) की सिर्फ़ मुख्य प्रोसेस को सुरक्षा की सुविधा मिलती है. इसलिए, सहायक सबप्रोसेस (जैसे कि :screenshot) सुरक्षा बजट का इस्तेमाल नहीं करती हैं.
सेल्फ़-ट्यूनिंग नीति और तीन लेवल का सीजीग्रुप डेलिगेशन
इंटरैक्टिव डीमन का वर्किंग सेट, डिवाइस के साइज़ और रैम की क्षमता के हिसाब से काफ़ी अलग होता है. उदाहरण के लिए, SystemUI स्मार्टवॉच पर करीब 45 एमबी, 6 जीबी रैम वाले फ़ोन पर 60 एमबी, और 16 जीबी रैम वाले फ़ोन पर 180 एमबी मेमोरी का इस्तेमाल करता है. इसलिए, हर डिवाइस के लिए स्टैटिक लुकअप टेबल का इस्तेमाल करना सही नहीं है. इसके बजाय, SystemMemoryBudgetManager हर प्रोसेस के अपने रेज़िडेंट फ़ुटप्रिंट से सीधे तौर पर फ़्लोर की जानकारी लेता है. इसके लिए, वह तीन कॉन्स्टेंट का इस्तेमाल करता है:
| नीति पैरामीटर | डिफ़ॉल्ट वैल्यू | व्यवहार |
|---|---|---|
| हर प्रोसेस के लिए फ़्लोर | सेटल किए गए memory.current का 90% हिस्सा, जिसमें अनमैप की गई फ़ाइल का कैश मेमोरी शामिल नहीं है |
यह एनॉनिमस हीप, स्लैब, और हॉट मैप किए गए कोड को सुरक्षित रखता है. साथ ही, सबसे कम इस्तेमाल होने वाले 10% कोड को फिर से इस्तेमाल करने के लिए छोड़ देता है, ताकि वाकई में कम इस्तेमाल होने वाले पेजों को अब भी हटाया जा सके. 90% का अनुपात लागू करने से पहले, अनमैप की गई फ़ाइल कैश (memory.stat में से max(0, file - shmem - file_mapped)) को घटाया जाता है. इससे बूट पैकेज-स्कैन कैश या एक बार पढ़ी गई ऐसेट, फ़्लोर को नहीं बढ़ाती हैं. |
| ग्लोबल रैम कैप | कुल रैम का 10% (config_systemMemoryBudgetLowKb) |
यह PinnerService config_pinnerMaxPinnedMemoryPercentage गार्डरेल से मेल खाता है. अगर 90% फ़्लोर का योग MemTotal के 10% से ज़्यादा है, तो हर फ़्लोर को एक ही फ़ैक्टर के हिसाब से कम किया जाता है. |
| रीफ़्रेश करने की फ़्रीक्वेंसी | शुरू होने के 1, 4, 16, और 64 सेकंड बाद. इसके बाद, हर 30 मिनट में | ज्यामितीय सेटल सीरीज़, हर डीमन के पोस्ट-स्टार्टअप वर्किंग सेट पर कन्वर्ज होती है. इसके लिए, हर डिवाइस के वॉर्म-अप में होने वाली देरी को हार्डकोड नहीं किया जाता. साथ ही, 30 मिनट का स्टेडी-स्टेट रीफ़्रेश, डिवाइस के लाइफ़टाइम के दौरान वर्किंग-सेट की धीरे-धीरे होने वाली बढ़ोतरी और कमी को ट्रैक करता है. |
Linux cgroup v2 मेमोरी कंट्रोलर (mm/memcontrol.c:effective_protection) में, लीफ़ cgroup की असरदार memory.min सुरक्षा, उसके पैरंट और ऐंसेस्टर cgroup पर कॉन्फ़िगर किए गए memory.min से सीमित होती है. memory.min को सिर्फ़ लीफ़ pid_<pid> डायरेक्ट्री पर सेट करने से, कोई सुरक्षा नहीं मिलती. ऐसा तब होता है, जब uid_<uid>/memory.min को 0 पर सेट किया गया हो.
इसके उलट, सिर्फ़ टॉप /sys/fs/cgroup/system स्लाइस पर फ़्लैट memory.min सेट करने से, दावा न की गई सुरक्षा सभी चाइल्ड यूआईडी और प्रोसेस में बराबर (memory_recursiveprot) बांट दी जाती है. इससे, uid_1000 (android.uid.system) को शेयर करने वाली डाइग्नोस्टिक या सेकंडरी प्रोसेस, surfaceflinger और audioserver से सुरक्षा को हटा सकती हैं.
हर डीमन को अलग-अलग आइसोलेट करने के लिए, SystemMemoryBudgetManager हर बार रीफ़्रेश होने पर, cgroup v2 हैरारकी के तीनों लेवल पर सुरक्षा की सुविधा देता है. इसे इमेज 1 में दिखाया गया है:
- लीफ प्रोसेस नोड (
pid_<pid>/memory.min): इसे प्रोसेस के (स्केल किए गए) 90% वर्किंग-सेट फ़्लोर पर सेट करें. - यूआईडी नोड (
uid_<uid>/memory.min): इसे मैनेज किए जा रहेpid_*लीफ़ फ़्लोर के कुल योग पर सेट किया जाता है. इससे, उस यूआईडी को शेयर करने वाली मैनेज न की जा रही प्रोसेस (जैसे, अन्यAID_SYSTEMडीमन याsharedUserId="android.uid.system"पैकेज) के पासmemory.min = 0होता है और वे सुरक्षा का दावा नहीं कर सकतीं. - टॉप-लेवल स्लाइस (
/sys/fs/cgroup/system/memory.minऔर/sys/fs/cgroup/apps/memory.min): इसे इसकेuid_*चाइल्ड स्लाइस के कुल योग पर सेट करें. मैनेज किए जा रहे नोड पर मौजूदmemory.lowकी पुरानी वैल्यू को मिटाकर0कर दिया जाता है. साथ ही, पिछली बार रीफ़्रेश किए जाने पर मैनेज की गईuid_*डायरेक्ट्री को रीसेट करके0कर दिया जाता है. जैसे, उपयोगकर्ता के लॉन्चर स्विच करने के बाद, पिछला होम लॉन्चर.
पहली इमेज. cgroup स्लाइस में, तीन लेवल की सुरक्षा के लिए फ़्लोर डेलिगेशन.
एमजीएलआरयू कर्नेल पर, memory.low के बजाय memory.min का इस्तेमाल क्यों किया जाता है
मल्टी-जनरेशनल एलआरयू (एमजीएलआरयू, Android 6.6 और इसके बाद के वर्शन वाले कर्नेल पर डिफ़ॉल्ट पेज रिक्लेम इंजन) के तहत, memory.low और memory.min, mm/vmscan.c:shrink_one में अलग-अलग तरह से काम करते हैं:
memory.low(सिंगल-पास डिफ़रल): ऐसा cgroup जिसका इस्तेमालmemory.lowसे कम है, उसे memcg LRU (MEMCG_LRU_TAIL) की टेल पर घुमाया जाता है और एक रिक्लेम पास के लिए छोड़ दिया जाता है. मेमोरी पर लगातार दबाव पड़ने पर, अगले पास में कर्नेल, cgroup को पूरी तरह से वापस ले लेता है औरMEMCG_LOWइवेंट को लॉग करता है. फ़िज़िकल डिवाइस के स्ट्रेस टेस्ट में, मेमोरी का इस्तेमाल करने वाले किसी अज्ञात ऐप्लिकेशन ने फ़िज़िकल रैम का 85% हिस्सा इस्तेमाल किया. इस दौरान,memory.lowने स्मार्टवॉच परSystemUIको ~45 एमबी से ~5 से 10 एमबी तक कम करने की अनुमति दी. साथ ही, 16 जीबी वाले फ़ोल्ड किए जा सकने वाले डिवाइस पर,audioserverको ~14 एमबी के फ़्लोर के मुकाबले 15 एमबी से 2 एमबी तक कम करने की अनुमति दी.memory.min(हार्ड प्रोटेक्शन फ़्लोर): ऐसा cgroup जिसका इस्तेमालmemory.minसे कम है, उसे ग्लोबल रिक्लेम से स्किप कर दिया जाता है. जैसा कि इमेज 2 में दिखाया गया है, 85% रैम प्रेशर वाले वर्कलोड के तहत,memory.minहर डीमन के सबसे कम इस्तेमाल होने वाले 10% हिस्से को हटा देता है. साथ ही,SystemUI,surfaceflinger, औरaudioserverको उनके 90% फ़्लोर पर रखता है. इसमें, बिना नाम वाले पेज के लिए कोई रीफ़ॉल्ट नहीं होता औरlmkdप्रोसेस को बंद करने की संख्या में कोई बढ़ोतरी नहीं होती.
memory.min, PinnerService mlock की सुरक्षा से मैच करने वाला हार्ड फ़िज़िकल रिज़र्वेशन उपलब्ध कराता है. यह रिज़र्वेशन, पिन किए गए की जगह लेता है. इसका फ़ायदा यह है कि कर्नल एलआरयू (स्टैटिक फ़ाइल लिस्ट के बजाय) यह चुनता है कि कौनसे हॉट कोड, हीप, और ग्राफ़िक पेज मेमोरी में बने रहें.
दूसरी इमेज. मेमोरी का दबाव बढ़ने पर, डीमन वर्किंग-सेट को बनाए रखना.
बूट प्रीवॉर्मिंग और पोस्ट-बूट अनमैप्ड फ़ाइल कैश मेमोरी को फिर से हासिल करना
config_defaultPinnerServiceFiles के PinnerService स्थायी mlock को बदलने के लिए, बूट-टाइम के दो व्यवहारों के बीच तालमेल बनाना ज़रूरी है:
- बैकग्राउंड में बूट होने के दौरान, एक बार में प्रीवॉर्मिंग (
PinnerService): पेज कैश मेमोरी को वॉर्म किए बिनाPinnerServicemlockको स्किप करने से,SystemUIके शुरू होने (OnBootPhase_550) पर, सिंक्रोनस बूट पाथ मेंSystemUIAPK, ODEX, और VDEX डिस्क की करीब 95 एमबी मेमोरी को रीड किया जाता है. इससे बूट होने में 300 से 450 मिलीसेकंड ज़्यादा लगते हैं.madvise(MADV_WILLNEED)को कॉल करना काफ़ी नहीं है, क्योंकि कर्नेल मेंforce_page_cache_ra, एकMADV_WILLNEEDकॉल को एक रीडअहेड विंडो (आम तौर पर 128 केबी से 2 एमबी) तक सीमित कर देता है. इसके बजाय, जबSystemMemoryBudgetManager.shouldSkipDefaultSystemPinningचालू होता है, तबPinnerService,onStartके दौरान बैकग्राउंड थ्रेड परconfig_defaultPinnerServiceFilesमें मौजूद हर फ़ाइल को मैप करता है. साथ ही,Os.mlockकी मदद से फ़ाइल को पेज कैश में सिंक्रोनस तरीके से पॉप्युलेट करता है. इसके बाद,Os.munlock,munmap, औरcloseको तुरंत कॉल करता है. इससे तेज़ी से चालू होने की सुविधा बनी रहती है. साथ ही, हमेशा के लिए लॉक किए गए बाइट की संख्या शून्य रहती है, ताकि कोल्ड स्टार्टअप पेजों को बाद में हटाया जा सके. - अनमैप की गई फ़ाइल कैश मेमोरी को हटाना और बूट पैकेज-स्कैन कैश मेमोरी को फिर से हासिल करना:
बूट के दौरान,
PackageManagerServiceइंस्टॉल किए गए APKs को स्कैन करता है. इससेsystem_servercgroup में 1.5 से 2.5 जीबी की कोल्ड अनमैप की गई फ़ाइल पेज कैश मेमोरी बच जाती है. साथ ही, अन्य सुरक्षित प्रोसेस (जैसे, एक्सआर डिवाइसों पर 3D ऐसेट फ़ाइलों को पढ़ने वालाSystemUI) भी एक बार पढ़ने से अनमैप की गई फ़ाइल कैश मेमोरी को बनाए रख सकती हैं. अगरmemory.minके कैलकुलेशन में कोल्ड कैश को शामिल किया जाता है, तो वह 10% ग्लोबल रैम कैप को भर सकता है. साथ ही,surfaceflinger,SystemUI, औरaudioserverके प्रोटेक्शन फ़्लोर को आनुपातिक रूप से कम कर सकता है. कैप स्टार्वेशन को रोकने के लिए,SystemMemoryBudgetManagerहर सुरक्षित प्रोसेस के लिएmemory.statको पढ़ता है. साथ ही, अनमैप की गई फ़ाइल कैश कोmax(0, file - shmem - file_mapped)के तौर पर कंप्यूट करता है. इसके बाद, 90% फ़्लोर को कंप्यूट करने से पहले, अनमैप की गई कैश मेमोरी कोmemory.currentसे घटाता है. जैसा कि इमेज 3 में दिखाया गया है. इसके अलावा,PHASE_BOOT_COMPLETEDके 10 सेकंड बाद, मैनेजर Linux 6.2 और नए कर्नेल परsystem_serverकेmemory.reclaimनोड में<unmapped_file> swappiness=0को एक बार में लिखता है. इससे, बिना नाम वाले हीप को स्वैप किए बिना या मैप किए गए DEX और कोड पेजों को हटाए बिना, कोल्ड पैकेज-स्कैन कैश को हटाया जा सकता है.android14-6.1जैसे पुराने कर्नेल पर,EINVALके साथswappiness=0को अस्वीकार कर दिया जाता है. ऐसे में, मैनेजरmemory.reclaimराइट को स्किप कर देता है. इसके बजाय, वह बिना अनुमति वाले रिक्लेम राइट पर वापस नहीं जाता, जो बूट के दौरान अज्ञात हीप को स्वैप कर देता है.
तीसरी इमेज. बूट होने के बाद, सुरक्षा के लिए तय की गई कम से कम मेमोरी को कन्वर्ज करना और कैश मेमोरी को फिर से हासिल करना.
कर्नेल से जुड़ी ज़रूरी शर्तें और डिवाइस कॉन्फ़िगरेशन ओवरले
SystemMemoryBudgetManager, Linux कर्नेल में mem_cgroup_calculate_protection पर निर्भर करता है, ताकि नेस्ट किए गए cgroups में memory.min को लागू किया जा सके. Android के कॉमन कर्नेल android15-6.6 और android16-6.12 में, एमजीएलआरयू नेस्टेड प्रोटेक्शन की सुविधा पहले से मौजूद होती है. एमजीएलआरयू की सुविधा वाले android14-6.1 पर चलने वाले डिवाइसों के लिए, mm/vmscan.c और mm/memcontrol.c में तीन अपस्ट्रीम बैकपोर्ट की ज़रूरत होती है. इससे खाली इंटरमीडिएट स्लाइस और यूआईडी सीजीग्रुप, लीफ़ प्रोसेस सीजीग्रुप को सुरक्षा देते हैं:
30d77b7eef01(mm/mglru: fix ineffective protection calculation)8aa420617918(mm/mglru: respect min_ttl_ms with memcgs)adb8213014b2(mm: memcg: fix stale protection of reclaim target memcg)
ओईएम, नीचे दिए गए फ़्रेमवर्क रिसॉर्स ओवरले का इस्तेमाल करके, SystemMemoryBudgetManager को पसंद के मुताबिक बना सकते हैं या बंद कर सकते हैं:
config_systemMemoryBudgetLowKb(इंटीजर, केबी):0(डिफ़ॉल्ट) सभीmemory.minफ़्लोर के योग को कुल फ़िज़िकल रैम के 10% पर सीमित करता है. पॉज़िटिव वैल्यू, केबी में एक तय सीमा सेट करती है. वहीं, नेगेटिव वैल्यू, डिवाइस परSystemMemoryBudgetManagerको बंद कर देती है. इससे लेगसीPinnerServiceस्टैटिकmlockपिनिंग बनी रहती है.config_systemMemoryBudgetHighKb(integer, KB):0(default) leaves/sys/fs/cgroup/system/memory.highatmax. पॉज़िटिव वैल्यू, टॉप स्लाइसmemory.highकी सीलिंग सेट करती है. यह वैल्यू, फ़्लोर कैप से ज़्यादा या उसके बराबर होनी चाहिए.config_systemMemoryBudgetAdditionalSystemProcesses(string-array):/sys/fs/cgroup/systemमें, ज़्यादा इंतज़ार के समय वाले नेटिव सिस्टम या वेंडर डीमन प्रोसेस के अतिरिक्त नामों की सूची (10000के तहत सिस्टम और वेंडर यूआईडी के लिए,/proc/<pid>/cmdlineमें/proc/<pid>/commयाargv[0]के बेसनेम से मैच किया गया) ताकि डिफ़ॉल्ट छह सिस्टम डीमन के साथ-साथ 90%memory.minफ़्लोर से सुरक्षित रखा जा सके.init.rcमेंmemory.minसेट करने के बजाय, इस ओवरले का इस्तेमाल करें. ऐसा इसलिए, क्योंकिSystemMemoryBudgetManager,uid_<uid>/memory.minको मैनेज की गई लीफ़ प्रोसेस के योग के तौर पर फिर से कैलकुलेट करता है. साथ ही, हर बार रीफ़्रेश करने पर, मैनेज नहीं किए गएuid_*नोड को हटा देता है. उदाहरण के लिए, एक्सआर डिवाइस अपने स्पेशल ट्रैकिंग और कैमरा एचएएल डीमन (android.hardware.perceptionhostऔरauracamerahal) को सुरक्षित रख सकता है. साथ ही, Android डेस्कटॉप डिवाइस अपने ऑडियो और यूएसबी कैमरा एचएएल डीमन (dras.core.audioऔरandroid.hardware.camera.provider-usb-service.android-desktop) को सुरक्षित रख सकता है:<!-- XR device overlay --> <string-array translatable="false" name="config_systemMemoryBudgetAdditionalSystemProcesses"> <item>android.hardware.perceptionhost</item> <item>auracamerahal</item> </string-array> <!-- Android Desktop device overlay --> <string-array translatable="false" name="config_systemMemoryBudgetAdditionalSystemProcesses"> <item>dras.core.audio</item> <item>android.hardware.camera.provider-usb-service.android-desktop</item> </string-array>config_systemUi(स्ट्रिंग): प्लैटफ़ॉर्म के SystemUI ऐप्लिकेशन का पैकेज नेम, जिसेMATCH_SYSTEM_ONLYकी मदद से रिज़ॉल्व किया गया है.
किसी डिवाइस पर चालू SystemMemoryBudgetManager फ़्लोर और cgroup नोड की जांच करने के लिए, यह कमांड चलाएं:
# Inspect policy state, resolved PIDs, and applied floors adb shell dumpsys system_server_dumper --name SystemMemoryBudgetManager adb shell dumpsys meminfo | sed -n '/System Memory Budgets/,$p'# Inspect raw cgroup v2 memory.min nodes across the system and apps slices adb shell head -n 1 \ /sys/fs/cgroup/system/memory.min \ /sys/fs/cgroup/system/uid_*/memory.min \ /sys/fs/cgroup/system/uid_*/pid_*/memory.min \ /sys/fs/cgroup/apps/memory.min \ /sys/fs/cgroup/apps/uid_*/memory.min \ /sys/fs/cgroup/apps/uid_*/pid_*/memory.min
बैकग्राउंड में लगातार चलने वाले सिस्टम ऐप्लिकेशन के लिए, मेमोरी बजट तय करना
SystemMemoryBudgetManager, memory.min फ़्लोर का इस्तेमाल करके, इंटरैक्टिव डीमन को रीक्लेम होने से बचाता है. हालांकि, कई अन्य सिस्टम ऐप्लिकेशन और खास अधिकार वाली प्लैटफ़ॉर्म सेवाएं, बैकग्राउंड में लंबे समय तक PERSISTENT प्रोसेस, बाउंड फ़ोरग्राउंड सेवाओं या अक्सर क्वेरी किए जाने वाले कॉन्टेंट देने वाले के तौर पर चलती हैं.
मेमोरी की साफ़ तौर पर तय की गई सीमा के बिना, इन प्रोसेस पर तब तक कोई पाबंदी नहीं लगाई जाती, जब तक कि वे कई गीगाबाइट की मेमोरी लिमिटर की सीमाओं तक नहीं पहुंच जातीं. जैसे, स्क्रीन पर दिखने वाले ऐप्लिकेशन के लिए 4 जीबी से 10 जीबी और बैकग्राउंड में चलने वाले ऐप्लिकेशन के लिए 2 जीबी से 5 जीबी. इसके अलावा, ऐसा तब भी होता है, जब ग्लोबल मेमोरी प्रेशर की वजह से, पूरे सिस्टम में kswapd और कम मेमोरी वाले किलर (lmkd) की गतिविधि ट्रिगर होती है.
अगर बैकग्राउंड में चल रही सिस्टम प्रोसेस पर कोई पाबंदी न लगाई जाए, तो अक्सर उनमें बड़ी मात्रा में कोल्ड मेमोरी जमा हो जाती है. यह मेमोरी, उनके ऐक्टिव वर्किंग सेट का हिस्सा नहीं होती:
- अनबाउंडेड फ़ाइल पेज कैश: मीडिया को इंडेक्स करने वाली, डेटाबेस खोजने वाली या कैलेंडर और प्रोवाइडर टेबल को सिंक करने वाली सेवाएं (जैसे,
AppSearch,MediaProvider, औरCalendarProvider), डिस्क पर मौजूद बड़ी फ़ाइलों को मैप या स्ट्रीम करती हैं. cgroupmemory.highकी सीमा के बिना, एक बार पढ़े गए क्लीन फ़ाइल-बैक्ड पेज, प्रोसेस cgroup से हमेशा के लिए चार्ज रहते हैं. इससे सैकड़ों मेगाबाइट की फ़िज़िकल रैम खर्च होती है. - बर्स्ट के बाद, पहचान छिपाकर हीप को बनाए रखना: ऐसी सेवाएं जिनमें कुछ समय के लिए गतिविधि में बढ़ोतरी होती है, जैसे कि
Bluetoothऑडियो और BLE डिस्कवरी बर्स्ट,NetworkStackकैप्टिव-पोर्टल टीएलएस की पुष्टि या यूज़र इंटरफ़ेस (यूआई) हेल्पर का बैकग्राउंड में ट्रांज़िशन, बर्स्ट पूरा होने के बाद भी, पहचान छिपाकर हीप पेजों को बनाए रख सकती हैं.
सिस्टम ऐप्लिकेशन पर, कैलिब्रेट किए गए <memory-budget> एलान (memory.high सॉफ़्ट लिमिट, आम तौर पर 30 एमबी से 190 एमबी) लागू करने से दो मुख्य फ़ायदे मिलते हैं:
- प्रोऐक्टिव और लोकलाइज़्ड पेज रिक्लेम: जब कोई सिस्टम प्रोसेस, कॉन्फ़िगर किए गए
memory.highबजट को पार कर जाती है, तो Linux कर्नेल, पेज रिक्लेम को खास तौर पर उस cgroup पर भेजता है. इससे, फ़ाइल-बैक्ड पेजों को पहले हटाया जाता है और इनऐक्टिव एनॉनिमस पेजों को ZRAM में कंप्रेस किया जाता है. इसके लिए, डिवाइस की मेमोरी पर ग्लोबल प्रेशर का इंतज़ार नहीं करना पड़ता. - फ़ोरग्राउंड ऐप्लिकेशन और कैश मेमोरी में सेव किए गए ऐप्लिकेशन पूल के लिए ज़्यादा रैम उपलब्ध होना: हमेशा चालू रहने वाली सिस्टम सेवाओं में, कोल्ड फ़ाइल कैश मेमोरी को सीमित करने से, डिवाइस में मौजूद फ़िज़िकल रैम में से कुछ मेगाबाइट से लेकर सैकड़ों मेगाबाइट तक की मेमोरी खाली हो जाती है. इससे यूज़र इंटरफ़ेस (यूआई) में रुकावटें कम होती हैं, कैमरा लॉन्च करने में कम समय लगता है, और कैश मेमोरी में सेव किए गए उपयोगकर्ता के ज़्यादा ऐप्लिकेशन चालू रहते हैं.
सिस्टम ऐप्लिकेशन के लिए मेमोरी बजट कॉन्फ़िगर करना
सिस्टम ऐप्लिकेशन, सामान्य ऐप्लिकेशन की तरह ही <memory-budget> मेनिफ़ेस्ट सिंटैक्स, प्रोसेस-स्टेट कैस्केडिंग, डिसप्ले-डेंसिटी स्केलिंग, और लास्ट-मैचिंग-क्लॉज़ रिज़ॉल्यूशन रूल का इस्तेमाल करते हैं. एट्रिब्यूट की पूरी सूची देखने के लिए, एक्सएमएल एट्रिब्यूट का रेफ़रंस देखें.
ओईएम, सिस्टम ऐप्लिकेशन के AndroidManifest.xml में सीधे तौर पर <memory-budget> एलिमेंट का एलान कर सकते हैं. इसके अलावा, वे Android.bp में additional_manifests प्रॉपर्टी का इस्तेमाल करके, उन्हें किसी अलग एक्सएमएल फ़ाइल से मर्ज कर सकते हैं. आम तौर पर, AOSP रेफ़रंस सिस्टम ऐप्लिकेशन के बजट को अलग-अलग *-budget.xml फ़ाइलों में सेव करता है. ये फ़ाइलें, कोर प्लैटफ़ॉर्म पैकेज के लिए frameworks/base/core/memory_budgets/ में या packages/modules/NetworkStack/memory_budgets/, packages/modules/AppSearch/apk/, और packages/services/Telephony/ जैसे अलग-अलग मॉड्यूल के साथ मौजूद होती हैं. साथ ही, इन्हें additional_manifests के साथ अटैच करता है:
android_app {
name: "TeleService",
manifest: "AndroidManifest.xml",
additional_manifests: ["Telephony-budget.xml"],
// ...
}
पैकेज-लेवल (यूआईडी) बनाम प्रोसेस-लेवल (पीआईडी) स्कोपिंग
पैकेज-लेवल का बेसलाइन बजट (<application>) या मल्टी-प्रोसेस बजट (<processes><process>) तय करने से यह तय होता है कि कर्नेल, यूआईडी सीजीग्रुप लेवल (/sys/fs/cgroup/uid_<uid>/memory.high) पर या हर पीआईडी सीजीग्रुप लेवल (/sys/fs/cgroup/uid_<uid>/pid_<pid>/memory.high) पर memory.high को लागू करता है या नहीं. जैसा कि इमेज 4 में दिखाया गया है:
- पैकेज-लेवल (
<application>) बजट: इसका इस्तेमाल तब करें, जब APK अपने यूआईडी के तहत एक ही प्रोसेस चलाता हो. उदाहरण के लिए,Bluetooth,Nfc,NetworkStack,CalendarProvider,TraceurयाAppSearch. - प्रोसेस-लेवल (
<processes><process>) बजट: इसका इस्तेमाल तब करें, जब APK, अन्य सिस्टम पैकेज के साथandroid:sharedUserId(जैसे, यूआईडी1001वालाandroid.uid.phoneया यूआईडी1000वालाandroid.uid.system) शेयर करता हो, ताकि उस यूआईडी को शेयर करने वाली अन्य प्रोसेस को एक साथ थ्रॉटल न किया जाए. इसके अलावा, इसका इस्तेमाल तब करें, जब कोई APK, अलग-अलग मेमोरी रोल वाली कई प्रोसेस चलाता हो. उदाहरण के लिए, बैकग्राउंडMediaProviderडीमन और:PhotoPickerयूआई सबप्रोसेस.
चौथी इमेज. यूआईडी-लेवल और पीआईडी-लेवल की मेमोरी सीलिंग.
यहां दिए गए उदाहरण में MediaProvider-budget.xml को दिखाया गया है. यह रैम के हिसाब से तय किए गए बजट को डिफ़ॉल्ट MediaProvider प्रोसेस (<process>) और डिसप्ले के हिसाब से तय किए गए बजट को :PhotoPicker यूज़र इंटरफ़ेस (यूआई) प्रोसेस के दायरे में लाता है. हर android:maxDeviceRamMb एट्रिब्यूट, उन डिवाइसों से मैच करता है जिनकी कुल फ़िज़िकल रैम (MemTotal), एमबी में तय किए गए थ्रेशोल्ड के बराबर या उससे कम होती है. अगर यह एट्रिब्यूट शामिल नहीं किया जाता है, तो यह किसी भी रैम क्षमता वाले डिवाइसों पर लागू होता है. क्लॉज़ को बिना किसी पाबंदी वाले डिफ़ॉल्ट से लेकर सबसे छोटे maxDeviceRamMb थ्रेशोल्ड के क्रम में लगाया जाता है, ताकि आखिरी मैचिंग क्लॉज़ रिज़ॉल्यूशन नियम, लागू होने वाले सबसे सख्त टियर को चुन सके:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.providers.media.module">
<uses-sdk android:targetSdkVersion="10000" />
<application>
<processes>
<process>
<memory-budget
android:maxMb="85" />
<memory-budget
android:maxMb="75"
android:maxDeviceRamMb="12288" />
<memory-budget
android:maxMb="60"
android:maxDeviceRamMb="8192" />
</process>
<process android:process=":PhotoPicker">
<memory-budget
android:maxMb="85"
android:additionalBytesPerDisplayPixel="25" />
</process>
</processes>
</application>
</manifest>
बजट मेनिफ़ेस्ट में <processes> का एलान करते समय, <process> एंट्री सिर्फ़ उन प्रोसेस के लिए लिस्ट करें जो <memory-budget> का एलान करती हैं. अगर डिफ़ॉल्ट ऐप्लिकेशन प्रोसेस, <application> पर कस्टम android:process नाम का एलान करती है, तो बिना नाम वाले <process /> टैग का इस्तेमाल करने के बजाय, उसके <process android:process="..."> एलिमेंट पर वह नाम बताएं. एपीके कंपाइल करने के दौरान, aapt2 आपस में मिले हुए मेनिफ़ेस्ट में कॉम्पोनेंट की ओर से एलान की गई ऐसी प्रोसेस के लिए, <process> एंट्री अपने-आप जोड़ देता है जिनके लिए बजट तय नहीं किया गया है. साथ ही, Android 17 के साथ काम करने के लिए, ज़रूरत पड़ने पर <application> के अंदर <memory-budget android:maxMb="1000000" /> को शामिल करता है, ताकि हर प्रोसेस के लिए बजट, उनकी टारगेट प्रोसेस से अलग रहें.
Google Pixel डिवाइसों पर, एओएसपी के रेफ़रंस बजट को कैसे कैलिब्रेट किया गया
AOSP में सिस्टम ऐप्लिकेशन के लिए तय की गई मेमोरी की सीमा को, Google Pixel डिवाइसों के हिसाब से कैलिब्रेट किया गया था. इनमें 6 जीबी से लेकर 16 जीबी तक की फ़िज़िकल रैम वाले डिवाइस शामिल थे. जैसे, 6 जीबी, 8 जीबी, 12 जीबी, और 16 जीबी रैम वाले फ़ोन, फ़ोल्ड किए जा सकने वाले डिवाइस, और टैबलेट. साथ ही, इनमें ~1.2 एमपी (720×1600) से लेकर ~4.5 एमपी (2076×2152) तक के डिसप्ले रिज़ॉल्यूशन वाले डिवाइस शामिल थे.
कैलिब्रेशन में, एक-दूसरे के पूरक दो डेटा सोर्स को जोड़ा गया: फ़्लीट-वाइड cgroup v2 फ़ील्ड टेलीमेट्री और कंट्रोल किए गए फ़िज़िकल-डिवाइस memory.high की मदद से, क्रिटिकल यूज़र जर्नी (सीयूजे) के दौरान की गई जांच.
सभी फ़्लीट के लिए cgroup v2 टेलीमेट्री का विश्लेषण
सभी डिवाइसों से समय-समय पर cgroup v2 के स्नैपशॉट इकट्ठा किए गए. इसके बाद, उन्हें फ़िज़िकल रैम टियर (≤8 जीबी, 12 जीबी, और ≥16 जीबी) और प्रोसेस स्टेट बकेट (foreground, perceptible, background, और cached) के हिसाब से बांटा गया. आंकड़ों के विश्लेषण के लिए, छह सिद्धांतों का पालन किया गया:
memory.currentको वर्किंग सेट और फिर से इस्तेमाल की जा सकने वाली फ़ाइल कैश मेमोरी में बांटना:memory.high, cgroup के रेज़िडेंट चार्ज (memory.current) को कंट्रोल करता है. इसलिए, हर स्नैपशॉट कोmemory.statका इस्तेमाल करके, एनॉनिमस हीप (anon), स्वैप किए गए एनॉनिमस पेज (swap), और फ़ाइल-बैक्ड पेज कैश मेमोरी (file) में बांटा गया. इसे इमेज 5 में दिखाया गया है. बिना सोर्स फ़ाइल वाली ऐसी मेमोरी जिसे कंप्रेस नहीं किया जा सकता, उसकी कुल मांग (P99 परanon + swap) से, बजट के लिए कम से कम वर्किंग-सेट फ़्लोर तय होता है. इससे प्रोसेस के दौरान, ZRAM के खत्म होने का खतरा नहीं रहता. वहीं,memory.currentP99 औरanon + swapP99 के बीच का बड़ा अंतर, फ़ाइल पेज कैश को दिखाता है.memory.highइसे फिर से हासिल कर सकता है. हालांकि, इसके लिए ज़रूरी है कि कैश मेमोरी अनमैप हो और उसका इस्तेमाल न किया जा रहा हो.- ऐसी मेमोरी का हिसाब लगाएं जिसे
memory.highफिर से इस्तेमाल नहीं कर सकता: सभी फ़ाइल और शेयर की गई मेमोरी, कोल्ड कैश नहीं होती. लॉक किए गए पेज (memory.statमेंunevictable, जैसे किmlockके साथ लॉक की गई शेयर की गई मेमोरी या किसी वर्चुअल मशीन की लॉक की गई गेस्ट रैम, जिसके होस्ट प्रोसेस को ऐप्लिकेशन के cgroup से चार्ज किया जाता है) बजट के तहत एक हार्ड फ़्लोर सेट करते हैं. साथ ही, मैप किए गए पेज (file_mapped) अक्सर ऐक्टिव वर्किंग सेट का हिस्सा होते हैं. फ़ाइल मेमोरी को फिर से इस्तेमाल करने लायक मानने से पहले,unevictable,shmem, औरfile_mappedको देखें. उदाहरण के लिए,AppSearchकी करीब 100 एमबी मेमोरी लॉक होती है और उसे खाली नहीं किया जा सकता. इसलिए, इसके बजट में वह फ़्लोर और उसका हॉट होस्ट वर्किंग सेट शामिल होता है. साथ ही, लॉक किए गए हिस्से को बढ़ाने के लिए हेडरूम भी होता है. - आइडल-स्टेट डाइल्यूशन को फ़िल्टर करना: कॉन्टेंट देने वाले (
CalendarProvider) और मांग पर उपलब्ध डेवलपर टूल (Traceur), फ़ील्ड स्नैपशॉट का 70% से 99.9% हिस्सा, करीब 1 एमबी से 3 एमबी तक इस्तेमाल नहीं करते. सभी स्नैपशॉट में रॉ पर्सेंटाइल की गिनती करने से, P95 और P99 के अनुमानों पर काफ़ी असर पड़ता है. इसके बजाय, पर्सेंटाइल और कॉन्फ़िडेंस इंटरवल का हिसाब, बिना किसी बदलाव के ऐक्टिव स्नैपशॉट के आधार पर लगाया गया. इसमेंCACHEDस्नैपशॉट और आइडल बेसलाइन स्नैपशॉट को फ़िल्टर करके हटा दिया गया. - डिवाइस के हिसाब से क्लस्टर किए गए कॉन्फ़िडेंस इंटरवल का इस्तेमाल करें: एक ही डिवाइस समय के साथ कई समय-समय पर स्नैपशॉट देता है. इसलिए, स्नैपशॉट को अलग-अलग सैंपल के तौर पर मानने से, टेल अनसर्टेनिटी कम हो जाती है. P95 और P99 के सभी वर्किंग सेट के अनुमानों का आकलन, डिवाइस के क्लस्टर के हिसाब से 95% कॉन्फ़िडेंस इंटरवल का इस्तेमाल करके किया गया. इसके लिए, अलग-अलग डिवाइस की संख्या
N_devको सैंपल साइज़ के तौर पर इस्तेमाल किया गया. memory.peakकी मदद से, कुछ समय के लिए होने वाले बर्स्ट को कैप्चर करें: समय-समय पर सैंपल लेने से, कम समय के लिए होने वाले और ज़्यादा मेमोरी का इस्तेमाल करने वाले बर्स्ट छूट सकते हैं. जैसे,NetworkStackकैप्टिव-पोर्टल टीएलएस की पुष्टि और एक साथ होने वाली डीएनएस जांच याBluetoothA2DP और बीएलई को शुरू करना. बर्स्टी सेवाओं के लिए, बजट इस तरह से तय किए गए थे कि वे रैम के अलग-अलग टियर में, लाइफ़टाइम कर्नेलmemory.peakके हाई-वॉटर मार्क के 90वें से 95वें पर्सेंटाइल को कवर कर सकें.- पुष्टि करें कि रैम टियर, रैम को दिखाता है, न कि डिवाइस की जनरेशन को: नए डिवाइसों में ज़्यादा रैम और ज़्यादा सुविधाएं होती हैं. इसलिए, रैम टियर के साथ बढ़ने वाला वर्किंग सेट, असल में सुविधाओं के साथ बढ़ सकता है.
maxDeviceRamMbटियर जोड़ने से पहले, डेटा को डिवाइस मॉडल के हिसाब से स्लाइस करें. उदाहरण के लिए, एक ही जनरेशन के 12 जीबी और 16 जीबी वाले फ़ोन पर,com.android.phoneउसी P99anon + swap(करीब 85 से 90 एमबी) तक पहुंचता है. वहीं, फ़ोल्ड होने वाले पुराने 12 जीबी फ़ोन पर, यह 40 एमबी का इस्तेमाल करता है. इसलिए, इसके बजट में रैम टियर के बिना एक ही वैल्यू का इस्तेमाल किया जाता है. इससे, कम रैम वाले डिवाइस में नई टेलीफ़ोनी सुविधाएं उपलब्ध कराने के लिए, बजट कम नहीं पड़ता.
पांचवीं इमेज. वर्किंग सेट बनाम फिर से इस्तेमाल की जा सकने वाली फ़ाइल कैश मेमोरी.
फ़िज़िकल-डिवाइस सीयूजे और डिसप्ले-स्केलिंग स्वीप
टेलीमेट्री से मिले बजट की पुष्टि करने और डिसप्ले के हिसाब से बजट (जैसे, :PhotoPicker) और स्थिति के हिसाब से बैकग्राउंड बजट (जैसे, Traceur) को कैलिब्रेट करने के लिए, 6 जीबी से 16 जीबी रैम वाले फ़िज़िकल डिवाइसों पर लाइव memory.high स्वीप किए गए:
- ज़ीरो-रीफ़ॉल्ट नी का पता लगाना: एंड-टू-एंड सीयूजे (जैसे, फ़ोटो ग्रिड को तेज़ी से फ़्लिंग करना, एल्बम ब्राउज़ करना, फ़ुल-स्क्रीन हाई-रिज़ॉल्यूशन वाली फ़ोटो और वीडियो की झलक को स्वाइप करना, और ट्रेस रिकॉर्ड करना और सेव करना) को चलाते समय, cgroup
memory.statकाउंटर (workingset_refault_anon,workingset_refault_file,pgscan, औरpgsteal) औरmemory.events(high) को मेज़र करते समय,memory.highको कम किया गया. जैसा कि इमेज 6 में दिखाया गया है, ऑप्टिमाइज़ किया गया बजट, ज़ीरो-रीफ़ॉल्ट नी से थोड़ा ज़्यादा है. ज़ीरो-रीफ़ॉल्ट नी वह थ्रेशोल्ड है जहां कर्नेल, कोल्ड वन-टाइम फ़ाइल कैश (pgsteal > 0) को फिर से हासिल करता है. इसके लिए, उसे ऐक्टिव वर्किंग-सेट थ्रैशिंग (workingset_refault == 0) को ट्रिगर करने की ज़रूरत नहीं पड़ती. - अलग-अलग रिज़ॉल्यूशन पर डिसप्ले-पिक्सल स्केलिंग की पुष्टि करना: हमने
:PhotoPickerको चार फ़िज़िकल और एम्युलेट किए गए डिसप्ले रिज़ॉल्यूशन पर टेस्ट किया. ये रिज़ॉल्यूशन, ~1.2 एमपी (720×1600) से लेकर ~4.5 एमपी (2076×2152 अनफ़ोल्ड किया गया इनर डिसप्ले) तक थे. इससे यह पुष्टि हुई कि इसका ऐक्टिव Glide और ViewPager2 बिटमैप वर्किंग सेट, डिसप्ले पिक्सल की संख्या के हिसाब से लीनियर तरीके से स्केल होता है. बिना डिसप्ले वाली बेसलाइन भी डिवाइस के हिसाब से अलग-अलग होती है: करीब-करीब एक जैसी पिक्सल संख्या पर, 16 जीबी वाले फ़ोल्ड किए जा सकने वाले डिवाइस के बाहरी डिसप्ले पर ज़ीरो-रीफ़ॉल्ट नी करीब 140 एमबी था. वहीं, 6 जीबी वाले फ़ोन पर यह 110 से 125 एमबी था. टेस्ट किए गए हर डिसप्ले पर, 85 एमबी की बेसलाइन और हर डिसप्ले पिक्सल के लिए 25 बाइट (android:maxMb="85"औरandroid:additionalBytesPerDisplayPixel="25"), मेज़र किए गए नी से ज़्यादा रहती है. एचडी+ पर ~110 एमबी, एफ़एचडी+ पर ~145 एमबी, और अनफ़ोल्ड किए गए डिसप्ले पर ~190 एमबी. - बैकग्राउंड में ART गार्बेज कलेक्शन की पुष्टि करना: cgroup v2 में, Zygote-शेयर किए गए
boot.artऔर फ़्रेमवर्क इमेज पेज, Zygote के cgroup से चार्ज होते रहते हैं. साथ ही, ART के साथ-साथ मार्क-कॉम्पैक्ट (सीएमसी) गार्बेज कलेक्शन के दौरान, इन्हें इम्यून स्पेस के तौर पर माना जाता है. स्ट्रेस टेस्टिंग से यह पुष्टि हुई कि जब कोई सिस्टम यूज़र इंटरफ़ेस (यूआई) ऐप्लिकेशनbackgroundपर ट्रांज़िशन करता है, तोmemory.highको टाइट करने से (उदाहरण के लिए,Traceurपर 30 एमबी तक) निजी हीप और पेज कैश को बिना किसी जीसी थ्रैशिंग या स्वैप गतिविधि के साफ़ तौर पर बाउंड किया जाता है.
छठी इमेज. सीयूजे के दौरान, ज़ीरो-रीफ़ॉल्ट नी का पता लगाना.
AOSP के लिए रेफ़रंस सिस्टम ऐप्लिकेशन के बजट की खास जानकारी
नीचे दी गई टेबल में, रैम टीयर और प्रोसेस की स्थितियों के हिसाब से, एओएसपी में कैलिब्रेट किए गए रेफ़रंस बजट की खास जानकारी दी गई है:
| सिस्टम पैकेज या प्रोसेस | दायरा | ≤8 जीबी रैम | 12 जीबी रैम | ≥16 जीबी रैम | प्राइमरी कैलिब्रेशन ड्राइवर |
|---|---|---|---|---|---|
com.android.bluetooth |
यूआईडी (<application>) |
80 एमबी | 95 एमबी | 110 एमबी | इसमें P90 लाइफ़टाइम memory.peak बर्स्ट (~75 से 110 एमबी) और >2x P99 ऐक्टिव memory.current शामिल हैं. |
com.android.nfc |
यूआईडी (<application>) |
50 एमबी | 60 एमबी | 60 एमबी | यह कोल्ड फ़ाइल कैश मेमोरी को ट्रिम करते समय, चालू होस्ट कार्ड एम्युलेशन P99 (ज़्यादा से ज़्यादा ~50 एमबी) और P90 से P95 memory.peak को कवर करता है. |
com.android.providers.calendar |
यूआईडी (<application>) |
डिफ़ॉल्ट रूप से 70 एमबी (फ़ोरग्राउंड) 50 एमबी perceptible और background |
ऐक्टिव वर्किंग सेट, रैम के अलग-अलग टियर के हिसाब से नहीं बदलता. बैकग्राउंड बजट, रिमाइंडर अलार्म के लिए हेडस्पेस को बनाए रखता है. साथ ही, सिंक करने के दौरान SQLite पेज कैश को ट्रिम करता है. | ||
com.android.traceur |
यूआईडी (<application>) |
डिफ़ॉल्ट तौर पर 85 एमबी (फ़ोरग्राउंड और परसेप्टिबल) 30 एमबी background |
ट्रेस रिकॉर्डिंग और एक्सपोर्ट (TraceService) के दौरान, 85 एमबी का पूरा हेडरूम सुरक्षित रखता है. साथ ही, इस्तेमाल न होने और ब्रॉडकास्ट की स्थिति को 30 एमबी पर सीमित करता है. |
||
com.android.providers.media.module (मुख्य) |
पीआईडी (<process>) |
60 एमबी | 75 एमबी | 85 एमबी | कोल्ड SQLite और थंबनेल फ़ाइल कैश मेमोरी को फिर से हासिल करते समय, P99 anon + swap पर ~10 से 30 एमबी हेडरूम उपलब्ध कराता है. |
com.android.providers.media.module:PhotoPicker |
पीआईडी (<process>) |
85 एमबी + 25 बाइट प्रति पिक्सल (एचडी+ पर ~110 एमबी, फ़ुल एचडी+ पर ~145 एमबी, ~4.5 एमपी फ़ोल्ड पर ~190 एमबी) |
Glide बिटमैप के वर्किंग-सेट नी से मैच करने के लिए, डिसप्ले पिक्सल की संख्या (additionalBytesPerDisplayPixel="25") के हिसाब से, अनुपात में स्केल किया जाता है. |
||
com.android.networkstack |
यूआईडी (<application>) |
65 एमबी | 70 एमबी | 85 एमबी | ज़्यादातर ऐसी मेमोरी जो पहचान ज़ाहिर नहीं करती. इसका साइज़, P95 लाइफ़टाइम memory.peak के हिसाब से तय किया जाता है, ताकि कैप्टिव-पोर्टल टीएलएस, डीएनएस, और डीएचसीपी बर्स्ट को कवर किया जा सके. |
com.android.appsearch.apk |
यूआईडी (<application>) |
130 एमबी | इसमें लॉक की गई और खाली न की जा सकने वाली करीब 100 एमबी मेमोरी के साथ-साथ, करीब 5 एमबी का हॉट होस्ट वर्किंग सेट शामिल होता है. साथ ही, लॉक किए गए हिस्से को बढ़ाने के लिए हेडरूम भी होता है. कोल्ड पेज कैश मेमोरी (P99 पर ~330 एमबी तक) को फिर से हासिल करने के दौरान, ≥125 एमबी पर शून्य रीफ़ॉल्ट मेज़र किए गए. | ||
com.android.phone (TeleService) |
पीआईडी (<process>) |
120 एमबी | शेयर किए गए यूआईडी 1001 पर, हर पीआईडी के लिए स्कोप किया गया. वर्किंग सेट, रैम के बजाय डिवाइस जनरेशन को ट्रैक करता है. इसलिए, एक बजट, हर मॉडल के लिए सबसे ज़्यादा P99 anon + swap से ~30 एमबी ज़्यादा होता है. |
||
ओईएम अपने डिवाइसों के लिए, सिस्टम ऐप्लिकेशन के बजट को फिर से कैसे कैलिब्रेट कर सकते हैं
सिस्टम ऐप्लिकेशन को पसंद के मुताबिक बनाने वाली OEM (उदाहरण के लिए, वेंडर की ब्लूटूथ प्रोफ़ाइलें, पसंद के मुताबिक बनाए गए टेलीफ़ोनी एक्सटेंशन या OEM मीडिया इंडेक्सर जोड़ना) या पहले से इंस्टॉल की गई अतिरिक्त सिस्टम सेवाएं शिप करने वाली OEM, मौजूदा बजट को फिर से तय कर सकती हैं. इसके अलावा, वे अपने हार्डवेयर पोर्टफ़ोलियो के लिए नई *-budget.xml फ़ाइलें भी बना सकती हैं.
ऐक्टिव cgroup v2 मेमोरी प्रोफ़ाइलें इकट्ठा करें
हर टारगेट सिस्टम प्रोसेस के लिए, /sys/fs/cgroup/uid_<uid>/pid_<pid>/ में मौजूद इसके cgroup v2 मेमोरी नोड पढ़ें. ऐसा, अलग-अलग वर्कलोड और रैम टियर के लिए करें:
memory.current: cgroup के लिए चार्ज की गई मौजूदा रेज़िडेंट मेमोरी (Zygote-शेयर किए गए पेजों को छोड़कर)memory.peak: प्रोसेस शुरू होने के बाद से, जीवनकाल पीकmemory.currentहाई-वॉटर मार्कmemory.swap.current: ZRAM में कंप्रेस किए गए स्वैप का मौजूदा इस्तेमालmemory.stat:anon,file,pgscan,pgsteal,workingset_refault_anon, औरworkingset_refault_fileका ब्रेकडाउनmemory.events:highके उल्लंघन की कुल संख्या (memory.highथ्रॉटलिंग और रिक्लेम इवेंट)
डॉगफ़ूड या फ़ील्ड डिवाइसों से टेलीमेट्री इकट्ठा करते समय, प्रोसेस की चालू स्थितियों (TOP, FOREGROUND_SERVICE, चालू बाइंडिंग, और चालू सिंक) को, इस्तेमाल में न होने वाली CACHED या इस्तेमाल में न होने वाली PERSISTENT स्थितियों से अलग करें. इससे, इस्तेमाल में न होने वाले स्नैपशॉट, P95 और P99 वर्किंग-सेट के हिसाब को कम नहीं करते.
कंप्रेस न किए जा सकने वाले हीप को, फिर से इस्तेमाल किए जा सकने वाले फ़ाइल कैश से अलग करना
anon + swap के 99वें पर्सेंटाइल की तुलना, memory.current के 99वें पर्सेंटाइल से करें:
- फ़ाइल-कैश मेमोरी पर निर्भर सेवाएं (
file≫anon, जैसे कि डेटाबेस प्रोवाइडर, Search इंडेक्स करने वाले टूल, और लॉग डीमन):android:maxMbको सेट करें, ताकि P99anon + swapके मुकाबले ज़्यादा हेडरूम (आम तौर पर 1.5 गुना से 4 गुना) मिल सके. साथ ही, हॉट फ़ाइल पेजों के लिए एक वर्किंग विंडो मिल सके. इस कॉन्फ़िगरेशन की मदद से, कर्नेल लगातार कोल्ड अनमैप किए गए फ़ाइल पेजों को हटाता रहता है. इसके लिए, वह अनाम हीप को नहीं छूता. अगरunevictableयाfile_mappedबड़ा है (जैसा कि लॉक की गई मेमोरी या मेमोरी-मैप किए गए डेटाबेस के साथ होता है), तो उस फ़ुटप्रिंट को वर्किंग सेट के तौर पर भी गिनें. - बिना सोर्स फ़ाइल वाली हीप मेमोरी का ज़्यादा इस्तेमाल करने वाली या अचानक से ज़्यादा मेमोरी इस्तेमाल करने वाली सेवाएं (
anon,memory.currentका ज़्यादातर हिस्सा बनाती है, जैसे कि नेटवर्किंग या कनेक्टिविटी स्टैक):memory.peakके P90 से P95 को कवर करने के लिए, साइज़android:maxMbहोना चाहिए, ताकि अचानक से होने वाले बर्स्ट, इंतज़ार के समय के हिसाब से संवेदनशील थ्रेड पर सिंक्रोनस ZRAM स्वैप-आउट को ट्रिगर न करें. - डिसप्ले-इंटेंसिव यूज़र इंटरफ़ेस (यूआई) प्रोसेस (जैसे, पिकर, गैलरी या सिस्टम यूज़र इंटरफ़ेस (यूआई) हेल्पर): सबसे कम और सबसे ज़्यादा रिज़ॉल्यूशन वाले डिसप्ले पर, बेसलाइन नॉन-यूज़र इंटरफ़ेस (यूआई) फ़ुटप्रिंट और हर मेगापिक्सल के हिसाब से बढ़ते हुए बिटमैप फ़ुटप्रिंट को मेज़र करें. साथ ही,
android:maxMbऔरandroid:additionalBytesPerDisplayPixelका इस्तेमाल करके बजट को दिखाएं.
फ़िज़िकल डिवाइसों पर memory.high को स्वीप करना
बिल्ड के लिए नया बजट तय करने से पहले, am memory-limiter manual का इस्तेमाल करें (या
userdebug बिल्ड पर प्रोसेस के memory.high cgroup नोड पर सीधे लिखें)
अपने ऑटोमेटेड सीयूजे टेस्ट चलाते समय, कैंडिडेट की सीमाओं की जांच करने के लिए:
# Override memory.high for a specific PID to 60 MB during a CUJ test
adb shell am memory-limiter manual <PID> 60MBसीयूजे से पहले और बाद में, memory.stat और memory.events को मॉनिटर करें:
- बजट बहुत कम है: सीयूजे के दौरान,
workingset_refault_anonयाworkingset_refault_fileमें अचानक बढ़ोतरी होती है, फ़ोरग्राउंड में चल रहे काम के दौरानmemory.swap.currentलगातार बढ़ता है या सीयूजे फ़्रेम या बाइंडर लेटेंसी कम हो जाती है. बजट को डिफ़ॉल्ट नी से ज़्यादा बढ़ाएं. - बजट बहुत ज़्यादा है: फ़ाइल-स्ट्रीमिंग या इंडेक्स करने के भारी वर्कलोड के बाद भी,
memory.events:high0ही रहता है. साथ ही,memory.statमेंfile, कोल्ड पेजों के साथ तेज़ी से बढ़ता है. बजट को कम करके, ऐक्टिव वर्किंग सेट के हिसाब से सेट करें. - बजट को सही तरीके से कैलिब्रेट किया गया है: सामान्य कार्रवाई के दौरान, स्टेडी-स्टेट
memory.current,memory.highसे कम रहता है. ज़्यादा फ़ाइल या कैश मेमोरी के बर्स्ट के दौरान,pgstealकोल्ड फ़ाइल पेजों को फिर से हासिल करता है. वहीं,workingset_refault_anonशून्य के करीब रहता है और सीयूजे लेटेंसी में कोई बदलाव नहीं होता.