Android 12 में DMABUF और GPU मेमोरी अकाउंटिंग लागू करें

यह पृष्ठ एंड्रॉइड 12 में पेश किए गए विभिन्न मेमोरी अकाउंटिंग सुधारों का वर्णन करता है।

Sysfs में DMA-BUF आँकड़े

Android 11 और Android 12 में, उपयोगकर्ता बिल्ड में debugfs माउंट नहीं किया जा सकता है। इसलिए Android 12 में /sys/kernel/dmabuf/buffers निर्देशिका में sysfs में DMA-BUF आँकड़े जोड़े गए हैं।

पथ विवरण
/sys/kernel/dmabuf/buffers /sys/kernel/dmabuf/buffers निर्देशिका में प्रत्येक DMA-BUF की आंतरिक स्थिति का एक स्नैपशॉट होता है। /sys/kernel/dmabuf/buffers/<inode_number> अद्वितीय इनोड संख्या <inode_number> के साथ DMA-BUF के आंकड़े शामिल हैं।
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name इस रीड-ओनली फ़ाइल में DMA-BUF निर्यातक का नाम शामिल है।
/sys/kernel/dmabuf/buffers/<inode_number>/size यह केवल पढ़ने योग्य फ़ाइल बाइट्स में DMA-BUF का आकार निर्दिष्ट करती है।

libdmabufinfo एपीआई प्रति-निर्यातक और प्रति-बफर आंकड़ों को उजागर करने के लिए DMA-BUF sysfs आँकड़ों को पार्स करता है।

कृपया ध्यान दें कि डीएमए-बीयूएफ निर्यात करने वाले कर्नेल ड्राइवरों को डीएमए-बीयूएफ बनाने के लिए dma_buf_export() एपीआई को लागू करने से पहले निर्यातक नाम पर struct dma_buf_export_info के exp_name फ़ील्ड को सही ढंग से सेट करना होगा। प्रति-निर्यातक आँकड़े प्राप्त करने के लिए libdmabufinfo और dmabuf_dump टूल के लिए यह आवश्यक है जो बाद में bugreport में प्रदर्शित होते हैं।

इस जानकारी को एक नए तर्क, -b के साथ आउटपुट करने के लिए dmabuf_dump टूल को संशोधित किया गया है।

डीएमए-बीयूएफ हीप्स फ्रेमवर्क के लिए आँकड़े

GKI 2.0 में ION को DMA-BUF हीप्स फ्रेमवर्क के पक्ष में खारिज किया जा रहा है, जो अपस्ट्रीम लिनक्स कर्नेल का हिस्सा है।

निम्नलिखित वैश्विक ION आँकड़े Android 11 में ट्रैक किए गए हैं:

  • प्रत्येक ION ढेर द्वारा निर्यात किए गए DMA-BUFs का कुल आकार
  • प्रत्येक ION ढेर द्वारा संग्रहीत अप्रयुक्त पूर्व-आवंटित मेमोरी का कुल आकार

Android 11 में प्रति-ION हीप आँकड़े प्रदर्शित करने के लिए कोई इंटरफ़ेस उपलब्ध नहीं है।

निम्न तालिका एंड्रॉइड 12 में डीएमए-बीयूएफ हीप फ्रेमवर्क का उपयोग करने वाले उपकरणों के लिए उनके समकक्षों के साथ आईओएन सांख्यिकी इंटरफेस की तुलना करती है।

Android 11 या Android 12 में ION सपोर्ट के साथ लॉन्च होने वाले डिवाइस Android 12 में DMA-BUF हीप्स के साथ लॉन्च होने वाले डिवाइस
प्रति-ढेर ION आँकड़े कोई नहीं DMA-BUF sysfs आँकड़ों से पार्स किया गया
निर्यातित डीएमए-बीयूएफ का कुल आकार /sys/kernel/ion/total_heap_size_kb
(इसमें गैर-आईओएन निर्यातकों द्वारा निर्यात किए गए डीएमए-बीयूएफ का आकार शामिल नहीं है)
DMA-BUF sysfs आँकड़ों से पार्स किया गया
(निर्यात किए गए सभी डीएमए-बीयूएफ का आकार शामिल है)।
ढेरों द्वारा एकत्रित कुल स्मृति /sys/kernel/ion/total_pool_size_kb /sys/kernel/dma_heap/total_pool_size_kb

खोई हुई RAM गणना सटीकता में सुधार करें

पहले खोई हुई रैम की गणना इस प्रकार की जाती थी:

अंतिम लंबी lostRAM = memInfo.getTotalSizeKb( ) - ( totalPss - totalSwapPss )

- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()

- kernelUsed - memInfo.getZramTotalSizeKb() ;

totalPss घटक में GPU मेमोरी उपयोग (मेमट्रैक HAL के getMemory() इंटरफ़ेस द्वारा लौटाया गया) शामिल था। kernelUsed घटक में कुल डीएमए-बीयूएफ मेमोरी उपयोग शामिल था। हालाँकि, Android उपकरणों के लिए, GPU मेमोरी निम्नलिखित से आई:

  • भौतिक पृष्ठ आवंटनकर्ता का उपयोग करके GPU ड्राइवर द्वारा किया गया प्रत्यक्ष आवंटन
  • डीएमए-बीयूएफ को जीपीयू एड्रेस स्पेस में मैप किया गया

इसलिए, डीएमए-बीयूएफ जिन्हें जीपीयू एड्रेस स्पेस में मेमोरी-मैप किया गया था, खोई हुई रैम की गणना करते समय दो बार घटाए गए थे। एंड्रॉइड 12 जीपीयू एड्रेस स्पेस में मैप किए गए डीएमए-बीयूएफ के आकार की गणना करने के लिए एक समाधान लागू करता है, जिसका अर्थ है कि लॉस्ट रैम गणना में इसका केवल एक बार हिसाब लगाया जाता है।

समाधान का विवरण इस प्रकार है:

  • Memtrack HAL API getMemory() जब PID 0 के साथ कॉल किया जाता है, तो उसे MemtrackType::GL और MemtrackRecord::FLAG_SMAPS_UNACCOUNTED के लिए वैश्विक कुल GPU-निजी मेमोरी की रिपोर्ट करनी चाहिए।
  • GL के अलावा किसी अन्य MemtrackType के लिए PID 0 के साथ कॉल करने पर getMemory() विफल नहीं होनी चाहिए। इसके बजाय इसे 0 लौटाना होगा।
  • एंड्रॉइड 12 में जोड़ा गया जीपीयू मेमोरी ट्रेसप्वाइंट/ईबीपीएफ समाधान कुल जीपीयू मेमोरी को दर्शाता है। कुल जीपीयू निजी मेमोरी को कुल जीपीयू मेमोरी से घटाने पर जीपीयू एड्रेस स्पेस में मैप किए गए डीएमए-बीयूएफ का आकार मिलता है। फिर मूल्य का उपयोग GPU मेमोरी उपयोग के लिए सही ढंग से लेखांकन करके खोई हुई रैम गणना की सटीकता में सुधार करने के लिए किया जा सकता है।
  • अधिकांश मेमट्रैक एचएएल कार्यान्वयन में निजी जीपीयू मेमोरी को totalPss में शामिल किया गया है और इसलिए इसे lostRAM से हटाने से पहले इसे डुप्लिकेट किया जाना चाहिए।

कार्यान्वित समाधान अगले भाग में विस्तृत है।

खोई हुई रैम से मेमट्रैक परिवर्तनशीलता हटाएं

चूंकि मेमट्रैक एचएएल कार्यान्वयन भागीदारों के बीच भिन्न हो सकता है, एचएएल से totalPSS में शामिल जीपीयू मेमोरी हमेशा सुसंगत नहीं होती है। lostRAM से परिवर्तनशीलता को दूर करने के लिए, lostRAM गणना के दौरान MemtrackType::GRAPHICS और MemtrackType::GL में मौजूद मेमोरी को totalPss से हटा दिया जाता है।

MemtrackType::GRAPHICS मेमोरी को totalPss से हटा दिया गया है और ActivityManagerService.java में lostRAM गणना में totalExportedDmabuf मेमोरी के साथ बदल दिया गया है जैसा कि नीचे दिखाया गया है:

final long totalExportedDmabuf = Debug.getDmabufTotalExportedKb();

. . .

final long dmabufUnmapped = totalExportedDmabuf - dmabufMapped;

. . .

// Account unmapped dmabufs as part of the kernel memory allocations
kernelUsed += dmabufUnmapped;

// Replace Memtrack HAL reported Graphics category with mapped dmabufs
totalPss -= totalMemtrackGraphics;
totalPss += dmabufMapped;

MemtrackType::GL मेमोरी को totalPss से हटा दिया गया है और ActivityManagerService.java में lostRAM गणना में निजी GPU मेमोरी ( gpuPrivateUsage ) से बदल दिया गया है, जैसा कि नीचे दिखाया गया है:

final long gpuUsage = Debug.getGpuTotalUsageKb();

. . .

final long gpuPrivateUsage = Debug.getGpuPrivateMemoryKb();

. . .

// Replace the Memtrack HAL-reported GL category with private GPU allocations.
// Count it as part of the kernel memory allocations.
totalPss -= totalMemtrackGl;
kernelUsed += gpuPrivateUsage;

खोई हुई रैम गणना को अद्यतन किया गया

कुल निजी जीपीयू मेमोरी और कुल निर्यातित डीएमए बफर मेमोरी kernelUsed + totalPss में समाहित हैं, जिन्हें lostRAM से हटा दिया गया है। यह खोई हुई रैम गणना से डबल-काउंटिंग और मेमट्रैक परिवर्तनशीलता दोनों को समाप्त कर देता है।

final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();

मान्यकरण

वीटीएस परीक्षण इस नियम को लागू करते हैं कि एंड्रॉइड 12 में लिनक्स कर्नेल संस्करण 5.4 या उच्चतर के साथ लॉन्च होने वाले डिवाइस getGpuDeviceInfo() एपीआई का समर्थन करते हैं।

एक नए मेमट्रैक HAL API getGpuDeviceInfo() को उपयोग में आने वाले GPU डिवाइस के बारे में जानकारी लौटानी होगी।

यह डीएमए बफर और जीपीयू मेमोरी उपयोग में बेहतर मेमोरी अकाउंटिंग और दृश्यता प्रदान करता है। खोई हुई रैम और मेमोरी अकाउंटिंग को बेहतर बनाने के लिए मेमट्रैक एआईडीएल एचएएल को लागू करें। यह सुविधा Google सेवाओं पर निर्भर नहीं है.

कार्यान्वयन

यह सुविधा एआईडीएल मेमट्रैक एचएएल पर निर्भर करती है, और इसे एंड्रॉइड 12 में लागू करने के निर्देश कोड में टिप्पणियों के रूप में शामिल किए गए हैं।

सभी एचआईडीएल एचएएल को भविष्य के रिलीज में एआईडीएल में परिवर्तित करने की योजना है।

निम्नलिखित एपीआई को core/java/android/os/Debug.java में जोड़ा गया है:

   /**
     * Return total memory size in kilobytes for exported DMA-BUFs or -1 if
     * the DMA-BUF sysfs stats at /sys/kernel/dmabuf/buffers could not be read.
     *
     * @hide
     */
    public static native long getDmabufTotalExportedKb();

   /**
     * Return memory size in kilobytes allocated for DMA-BUF heap pools or -1 if
     * /sys/kernel/dma_heap/total_pools_kb could not be read.
     *
     * @hide
     */
    public static native long getDmabufHeapPoolsSizeKb();

यह सुनिश्चित करने के लिए कि आपका संस्करण अपेक्षानुसार काम करता है, अपने GPU ड्राइवरों में ट्रेसप्वाइंट को एकीकृत करें, और MemtrackType::GL और MemtrackRecord:: के लिए PID 0 के साथ कॉल करने पर वैश्विक कुल GPU-निजी मेमोरी को सही ढंग से वापस करने के लिए AIDL memtrack HAL getMemory() API को लागू करें। FLAG_SMAPS_UNACCOUNTED.