बिटमैप और मेमोरी

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

बिटमैप कॉन्फ़िगरेशन और पिक्सल डेटा

बिटमैप की मेमोरी का इस्तेमाल, मुख्य रूप से इसके डाइमेंशन (चौड़ाई × ऊंचाई) और कॉन्फ़िगरेशन (Bitmap.Config) से तय होता है.

कॉन्फ़िगरेशन से पता चलता है कि हर पिक्सल को दिखाने के लिए कितने बाइट इस्तेमाल किए जाते हैं:

कॉन्फ़िगरेशन बाइट प्रति पिक्सल ब्यौरा
ALPHA_8 1 सिर्फ़ ऐल्फ़ा (पारदर्शिता) चैनल. मास्क बनाने के लिए इस्तेमाल किया जाता है.
RGB_565 2 लाल (5 बिट), हरा (6 बिट), नीला (5 बिट). कोई ऐल्फ़ा वर्शन नहीं है. यह ऐसी अपारदर्शी इमेज के लिए अच्छा है जिनमें रंग की फ़िडेलिटी ज़्यादा ज़रूरी नहीं होती.
ARGB_8888 4 ऐल्फ़ा, लाल, हरा, नीला (हर एक के लिए 8 बिट). डिफ़ॉल्ट और सबसे सामान्य विकल्प.
RGBA_F16 8 हाफ़-प्रिसिज़न फ़्लोटिंग पॉइंट. इसका इस्तेमाल वाइड-गैमट और एचडीआर कॉन्टेंट के लिए किया जाता है.
HARDWARE लागू नहीं ग्राफ़िक्स मेमोरी (gralloc/DMABuf) में सेव किया जाता है. हार्डवेयर बिटमैप देखें.

मेमोरी फ़ॉर्मूला: Memory (Bytes) = Width × Height × Bytes Per Pixel

उदाहरण के लिए, 1080 पिक्सल वाले डिवाइस (1920x1080) पर फ़ुल-स्क्रीन इमेज ARGB_8888 का साइज़: 1920 × 1080 × 4 बाइट ≈ 8.3 एमबी होता है.

हीप बिटमैप बनाम शेयर किए गए बिटमैप

हीप बिटमैप (नेटिव हीप)

Android 8.0 और इसके बाद के वर्शन में, बिटमैप पिक्सल डेटा को नेटिव हीप में सेव किया जाता है. वहीं, Java हीप में सिर्फ़ एक छोटा रैपर ऑब्जेक्ट मौजूद होता है.

जब किसी ऐप्लिकेशन को इमेज दिखानी होती है, तो आम तौर पर कंप्रेस की गई इमेज फ़ाइल को बिटमैप में डिकोड किया जाता है. इसके बाद, इसे हीप में सेव किया जाता है.

शेयर किए गए बिटमैप (ashmem/memfd)

जब किसी बिटमैप को एक प्रोसेस से दूसरी प्रोसेस में ट्रांसफ़र किया जाता है (जैसे, सूचना के लिए Binder के ज़रिए SystemUI में), तो Android, पिक्सल डेटा को कॉपी करने से बचता है. इसके लिए, वह शेयर्ड मेमोरी (ashmem या memfd) का इस्तेमाल करता है.

Bitmap इंस्टेंस को शेयर की गई मेमोरी में कॉपी किया जा सकता है. इसके लिए, Bitmap.asShared() को कॉल करना होगा. इसके अलावा, अगर Bitmap को Parcel में रखा जाता है, तो इसे इंप्लिसिट तौर पर कॉपी किया जा सकता है. आम तौर पर, Bitmap को Parcelable (जैसे कि Bundle) में जोड़कर और Binder IPC पर भेजकर ऐसा किया जाता है.

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

बदले जा सकने वाले बनाम बदले न जा सकने वाले बिटमैप

  • बदले जा सकने वाले बिटमैप: इन्हें बनाने के बाद बदला जा सकता है. उदाहरण के लिए, Canvas के ज़रिए. इनके लिए, हमेशा अपनी निजी मेमोरी का इस्तेमाल करना ज़रूरी होता है. अगर किसी Bitmap को बदला जा सकता है, तो उसकी डीप कॉपी (सभी पिक्सल डेटा की दूसरी कॉपी) बनानी होगी.
  • बदलाव न किए जा सकने वाले बिटमैप: इनमें बदलाव नहीं किया जा सकता. इससे, अलग-अलग Bitmap इंस्टेंस के बीच एक ही मेमोरी बफ़र शेयर करने जैसे ऑप्टिमाइज़ेशन किए जा सकते हैं. APK रिसॉर्स (BitmapFactory) से लोड किए गए बिटमैप आम तौर पर बदले नहीं जा सकते.

बिटमैप को बेहतर तरीके से मैनेज करना

बिटमैप को पूल करना और उनका फिर से इस्तेमाल करना

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

Google का सुझाव है कि Java पर आधारित ऐप्लिकेशन के लिए, Glide का इस्तेमाल करें. साथ ही, Kotlin पर आधारित ऐप्लिकेशन के लिए, Coil का इस्तेमाल करें. खास तौर पर, जब Jetpack Compose का इस्तेमाल किया जा रहा हो.

जब किसी बिटमैप की ज़रूरत नहीं होती है, तो ऐप्लिकेशन उसे GC'd होने देने के बजाय, bitmap.recycle() को कॉल करता है या उसे पूल में वापस भेज देता है. जब एक ही डाइमेंशन और कॉन्फ़िगरेशन वाले बिटमैप की ज़रूरत होती है, तो पूल मौजूदा बफ़र उपलब्ध कराता है. इससे नए बफ़र को मेमोरी असाइन करने की ज़रूरत नहीं पड़ती.

हार्डवेयर बिटमैप

Bitmap.Config.HARDWARE की मदद से, पिक्सल डेटा को सीधे ग्राफ़िक्स मेमोरी (डीएमएबफ़) में सेव किया जा सकता है.

  • फ़ायदे:
    • मेमोरी की बचत: ऐप्लिकेशन या नेटिव हीप का इस्तेमाल नहीं करता; जीपीयू मेमोरी का इस्तेमाल करता है. अक्सर ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में दिखाए गए बिटमैप को GPU मेमोरी में कॉपी करना पड़ता है. इसलिए, इस सुविधा से कॉपी करने की कार्रवाई और मेमोरी की अतिरिक्त लागत बच जाती है.
    • परफ़ॉर्मेंस: डेटा पहले से ही जीपीयू पर मौजूद होने की वजह से, इसे बहुत तेज़ी से बनाया जा सकता है.
  • नुकसान:
    • बदलाव नहीं किया जा सकता: हार्डवेयर बिटमैप में बदलाव नहीं किया जा सकता.
    • रीड-बैक की प्रोसेस धीमी है: सीपीयू से पिक्सल ऐक्सेस करना (जैसे, getPixel()) बहुत महंगा है.
    • एट्रिब्यूशन: एएचएटी जैसे स्टैंडर्ड टूल में इसे ट्रैक करना मुश्किल होता है (नीचे देखें).

बिटमैप की मेमोरी से जुड़ी आम समस्याएं

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

बहुत बड़े बिटमैप डिकोड किए जा रहे हैं

फ़ुल रिज़ॉल्यूशन वाली 4000 × 3000 पिक्सल की फ़ोटो, ARGB_8888 में 48 एमबी की जगह लेती है. पूरी इमेज को डिकोड करके, उसे सिर्फ़ 200 × 150 पिक्सल के थंबनेल में रेंडर करने से, पिक्सल बफ़र का 99% से ज़्यादा हिस्सा बर्बाद हो जाता है.

ImageDecoder या BitmapFactory का इस्तेमाल करके इमेज को सीधे तौर पर डिकोड करते समय, डिकोड पास के दौरान डाउनसैंपल करें. ऐसा ImageDecoder.setTargetSize() या BitmapFactory.Options.inSampleSize का इस्तेमाल करके, टारगेट व्यू डाइमेंशन से मैच करने के लिए करें. Glide और Coil जैसी इमेज लोड करने वाली लाइब्रेरी, टारगेट व्यू का साइज़ तय करने पर, डाउनसैंपलिंग की प्रोसेस अपने-आप करती हैं.

उदाहरण के लिए, ImageDecoder का इस्तेमाल करके बिट मैप को डिकोड करते समय, OnHeaderDecodedListener पास करें. इससे आउटपुट डाइमेंशन को आपके टारगेट व्यू साइज़ के हिसाब से छोटा किया जा सकेगा:

val source = ImageDecoder.createSource(resources, R.drawable.high_res_photo)
val bitmap = ImageDecoder.decodeBitmap(source) { decoder, info, _ ->
    if (info.size.width > targetWidth || info.size.height > targetHeight) {
        decoder.setTargetSize(targetWidth, targetHeight)
    }
}

पैरलल डिकोडिंग की वजह से, स्ट्रीम पर बने रहने वाले कॉनकरंट व्यूअर की संख्या ज़्यादा होती है

भले ही, हर बिटमैप का साइज़ सही हो और वह कम समय के लिए हो, लेकिन एक साथ कई इमेज डिकोड करने से मेमोरी का इस्तेमाल बहुत ज़्यादा बढ़ सकता है. उदाहरण के लिए, अगर कोई आयोजक या गैलरी स्क्रीन, एक साथ आइकॉन या थंबनेल डिकोड करने के लिए, अनबाउंडेड थ्रेड पूल पर 30 टास्क भेजती है, तो सभी 30 अनकंप्रेस किए गए पिक्सल बफ़र और डिकोडर स्क्रैच बफ़र, एक ही समय में रैम का इस्तेमाल करते हैं.

एक साथ कई ऐप्लिकेशन इस्तेमाल करने की वजह से, मेमोरी का इस्तेमाल करने वाले ऐप्लिकेशन की संख्या बढ़ जाती है. इससे नेटिव हीप फ़ुटप्रिंट बढ़ जाता है. साथ ही, बैच पूरा होने से पहले ही lmkd प्रोसेस बंद हो सकती हैं. थ्रेड पूल, सेमाफ़ोर या कोरूटीन डिस्पैचर जैसे Dispatchers.IO.limitedParallelism(2) का इस्तेमाल करके, डिकोड करने की प्रोसेस को सीमित करें. इससे एक बार में सिर्फ़ कुछ बिटमैप डिकोड होंगे.

फ़्रेम-प्रोसेसिंग लूप में, रीसाइकल नहीं किए गए ट्रांज़िएंट बिटमैप

Android 8.0 और इसके बाद के वर्शन में, Java Bitmap रैपर ऑब्जेक्ट, Java हीप पर सिर्फ़ 56 बाइट लेता है. वहीं, इसका पिक्सल बफ़र नेटिव हीप में रहता है और कई मेगाबाइट ले सकता है. इस स्प्लिट की पुष्टि, Android Studio Memory Profiler या AHAT में की जा सकती है. यहां हर Bitmap इंस्टेंस, अपने मल्टी-मेगाबाइट नेटिव साइज़ के साथ-साथ ~56 बाइट का शैलो Java साइज़ दिखाता है. साथ ही, dumpsys meminfo में Native Allocations (Bitmap (malloced)) में भी इसकी पुष्टि की जा सकती है.

कैमरे के फ़्रेम का विश्लेषण, ओसीआर या एमएल इन्फ़्रेंस लूप जैसी हाई-फ़्रीक्वेंसी पाइपलाइन, अक्सर हर फ़्रेम पर एक नया बिटमैप असाइन करती हैं. इसके लिए, रोटेशन या क्रॉपिंग के लिए ImageProxy.toBitmap() और Bitmap.createBitmap() को कॉल किया जाता है. बदले गए फ़्रेम के रेफ़रंस को रीसाइकल किए बिना हटाने से, नेटिव मेमोरी बढ़ सकती है. छोटे Java रैपर, Java हीप ऑक्यूपेंसी को मुश्किल से बढ़ाते हैं. इसलिए, वे गार्बेज कलेक्शन को इतनी तेज़ी से ट्रिगर नहीं करते कि सैकड़ों मेगाबाइट के नेटिव पिक्सल बफ़र को इकट्ठा होने से रोका जा सके. ऐसा तब तक होता है, जब तक NativeAllocationRegistry उन्हें वापस नहीं ले लेता.

जब किसी लूप में फ़्रेम प्रोसेस किए जाते हैं, तो हो सके, तो पहले से असाइन किए गए बफ़र का फिर से इस्तेमाल करें. इसके अलावा, हर फ़्रेम के प्रोसेस होने के तुरंत बाद, ट्रांज़िएंट इंटरमीडिएट बिटमैप पर bitmap.recycle() को साफ़ तौर पर कॉल करें.

खुद से की जाने वाली गतिविधि: बिटमैप एक्सप्लोरेशन

हम इन सिद्धांतों को समझने के लिए, BitmapLab सैंपल के तौर पर मिले ऐप्लिकेशन का इस्तेमाल करेंगे.

1. dumpsys meminfo की मदद से मेज़रमेंट करना

BitmapLab लॉन्च करें और ALLOCATE 10MB ARGB_8888 पर टैप करें. इसके बाद, यह कमांड चलाएं:

adb shell dumpsys meminfo -s com.android.bitmaplab

Android के नए वर्शन में, नेटिव ऐलोकेशन सेक्शन ढूंढें. ये सामान्य ऐप्लिकेशन की खास जानकारी की तुलना में, बिटमैप के लिए बेहतर एट्रिब्यूशन देते हैं:

 Native Allocations
                         Count                       Total(kB)
                        ------                         ------
   Bitmap (malloced):        1                          10240  # <--- 10MB Bitmap data!
Bitmap (nonmalloced):        0                              0
  • बिटमैप (malloced): प्रोसेस के नेटिव हीप में असाइन किए गए बिटमैप. Android 8.0 और इसके बाद के वर्शन में, ज़्यादातर स्टैंडर्ड बिटमैप यहीं मौजूद होते हैं.
  • बिटमैप (nonmalloced): ऐसे बिटमैप जो खास मेमोरी का इस्तेमाल करते हैं. जैसे, हार्डवेयर बिटमैप या शेयर किए गए बिटमैप (ashmem या memfd के ज़रिए).

BitmapLab में Shared Bitmap असाइन करने पर, आपको यह Bitmap (nonmalloced) में दिखेगा:

 Native Allocations
                         Count                       Total(kB)
                        ------                         ------
   Bitmap (malloced):        1                          10240
Bitmap (nonmalloced):        1                          10240  # <--- Shared Bitmap!

शेयर किए गए बिटमैप को ट्रैक करना

Android के कुछ वर्शन और कर्नल कॉन्फ़िगरेशन पर, dumpsys meminfo फ़ाइल डिस्क्रिप्टर के ज़रिए प्रोसेस के पता स्पेस में मैप किए गए बिटमैप के लिए, हाई-रिज़ॉल्यूशन ट्रैकिंग भी उपलब्ध कराता है.

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

adb shell setprop debug.hwui.bitmap_ashmem_long_name true

इस सुविधा को चालू करने पर, /proc/<pid>/smaps में मौजूद ashmem क्षेत्रों के नाम ज़्यादा जानकारी देने वाले होंगे. meminfo इसका फ़ायदा उठाएगा और नतीजे इस तरह दिखेंगे:

 Shared Bitmaps
                         Count                       Size(KB)
                        ------                         ------
              Mapped:        1                          10240
              Unique:        1                          10240
  • मैप की गई: बिट मैप से जुड़ी मेमोरी मैपिंग का कुल साइज़.
  • यूनीक: बिटमैप का साइज़ सिर्फ़ यूनीक वैल्यू के हिसाब से तय किया जाता है. इसका मतलब है कि एक ही शेयर किए गए बिटमैप पिक्सल डेटा की दो या इससे ज़्यादा मैपिंग को सिर्फ़ एक बार गिना जाता है.

2. AHAT में बिटमैप

AHAT, बिटमैप के लिए बेहतरीन विज़ुअलाइज़ेशन उपलब्ध कराता है.

  1. BitmapLab में, कुछ बिटमैप असाइन करें.
  2. नेटिव बिटमैप डेटा को शामिल करने के लिए, -b फ़्लैग का इस्तेमाल करके हीप डंप कैप्चर करें:

    adb shell am dumpheap -b png com.android.bitmaplab /data/local/tmp/bitmaps.hprof
    adb pull /data/local/tmp/bitmaps.hprof .
    ahat bitmaps.hprof
    
  3. localhost:7100 खोलें और साइडबार में Bitmaps लिंक ढूंढें या Bitmap क्लास खोजें.

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

रेंडर किए गए बिटमैप दिखाने वाला AHAT

3. Perfetto में बिटमैप ट्रैक

Perfetto, समय के साथ बिटमैप के लिए मेमोरी के बंटवारे और उनकी संख्या को ट्रैक कर सकता है. ये काउंटर, Android फ़्रेमवर्क से तब जनरेट होते हैं, जब किसी ऐप्लिकेशन के लिए gfx atrace कैटगरी चालू होती है.

  1. ट्रेस शुरू करें. आपको gfx कैटगरी शामिल करनी होगी. साथ ही, -a फ़्लैग का इस्तेमाल करके, किसी खास ऐप्लिकेशन पैकेज को टारगेट करना होगा:

    external/perfetto/tools/record_android_trace -o bitmaps.perfetto-trace \
        -t 15s -b 64mb view gfx dalvik am res memory -a com.android.bitmaplab
    
  2. BitmapLab में, Allocate और Clear बटन पर बार-बार टैप करें.

  3. इसके अलावा, पार्सल/अनपार्सल बिटमैप पर भी टैप करें.

  4. ui.perfetto.dev में ट्रेस का विश्लेषण करें.

com.android.bitmaplab के प्रोसेस सेक्शन में, आपको यह दिखेगा: * बिटमैप की संख्या: यह काउंटर, चालू बिटमैप की संख्या दिखाता है. * बिटमैप मेमोरी: यह काउंटर, बिटमैप के लिए इस्तेमाल किए गए कुल बाइट दिखाता है.

ज़्यादा जानकारी वाले स्लाइस (Perfetto SDK)

BitmapLab, बिटमैप ऑपरेशन के लिए हाई-लेवल स्लाइस जनरेट करने के लिए Perfetto SDK का भी इस्तेमाल करता है. ट्रेस में BitmapLab_ खोजकर, ये चीज़ें ढूंढें: * BitmapLab_parcelUnparcel: पार्सल करने और पार्सल खोलने के लॉजिक को कवर करने वाले स्लाइस. * BitmapLab_postNotification: सूचना पोस्ट करने के फ़्लो को कवर करने वाले स्लाइस.

सूचनाओं के फ़्लो को ट्रैक करना

सूचना पोस्ट करें पर टैप करने पर, ऐप्लिकेशन मौजूदा बिटमैप वाली सूचना बनाता है और उसे सिस्टम को भेजता है. इसकी ज़िम्मेदारी फ़्रेमवर्क कोड की होती है. यह कोड, Perfetto स्लाइस को फ़्लो इवेंट के साथ जोड़ता है. ये इवेंट, पार्सलिंग (बिटमैप को पार्सल में लिखना, ताकि इसे Binder IPC पर भेजा जा सके) और अनपार्सलिंग (बिटमैप को पार्सल से पढ़ना) के लिए होते हैं.

नीचे दिए गए स्क्रीनशॉट में, ऐप्लिकेशन को सूचना पोस्ट करने के लिए, Binder लेन-देन में इस्तेमाल किए जाने वाले बड़े बिटमैप को पार्सल करते हुए दिखाया गया है. साथ ही, system_server प्रोसेस में, उससे जुड़े अनपार्सल को दिखाया गया है.

इस इमेज में, सूचना के ज़रिए BitmapLab से system_server तक का फ़्लो दिखाया गया है

Perfetto का इस्तेमाल करके, उसी सूचना बिटमैप को फ़ॉलो किया जा सकता है, क्योंकि यह थ्रेड और प्रोसेस में आगे बढ़ता है. उदाहरण के लिए, system_server में मौजूद बाइंडर थ्रेड (जो INotificationManager बाइंडर सर्वर को लागू करता है) से लेकर system_server वर्कर थ्रेड तक. इसके बाद, ये थ्रेड उसी बिटमैप को com.android.systemui को फ़ॉरवर्ड कर सकती हैं, ताकि उसे सूचना शेड में दिखाया जा सके.

सिस्टम ऐप्लिकेशन से जुड़ी समस्याएं

SystemUI (सूचनाएं) और Launcher जैसे सिस्टम ऐप्लिकेशन को इन खास चुनौतियों का सामना करना पड़ता है:

  1. अनबाउंड कॉन्टेंट: सूचनाएं और विजेट कई हो सकते हैं. अगर हर एक में बड़ा बिटमैप होता है, तो सिस्टम में मेमोरी बहुत तेज़ी से खत्म हो सकती है.
  2. डुप्लीकेट होना: ऐसा हो सकता है कि एक ही ऐप्लिकेशन का आइकॉन, Launcher की कैश मेमोरी, SystemUI की सूचना वाले हिस्से, और Settings ऐप्लिकेशन में मौजूद हो.
  3. हार्डवेयर बफ़र के ज़रिए शेयर करना: इस समस्या को कम करने के लिए, सिस्टम कॉम्पोनेंट एक सेंट्रलाइज़्ड "इमेज ऑफ़लोड" सेवा की ओर बढ़ रहे हैं. यह सेवा, प्रोसेस के बीच HardwareBuffer इंस्टेंस शेयर करती है.
  4. DMABuf एट्रिब्यूशन: हार्डवेयर बिटमैप, हीप स्पेस को सेव करते हैं. हालांकि, ये DMABuf मेमोरी का इस्तेमाल करते हैं. इस मेमोरी को स्टैंडर्ड मेमोरी टूल में किसी खास प्रोसेस के लिए एट्रिब्यूट करना मुश्किल होता है.

    सिस्टम-वाइड डीएमएबफ़ एलोकेशन देखने के लिए, adb shell dmabuf_dump का इस्तेमाल करें. यह टूल, हर प्रोसेस के लिए बफ़र की जानकारी देता है:

     droid.bitmaplab:19562
                      Name              Rss              Pss         nr_procs            Inode               Exporter
                 <unknown>          3840 kB          1280 kB                3             3397              virtio_gpu
                    system            12 kB             4 kB                3             3398                  system
                 <unknown>          3840 kB          1920 kB                2             3399              virtio_gpu
                    system            12 kB             6 kB                2             3400                  system
             PROCESS TOTAL         11556 kB          5136 kB
    
    • आरएसएस: अगर प्रोसेस में बफ़र मैप किया गया है, तो उसका कुल साइज़.
    • Pss: यह बफ़र शेयर करने वाली प्रोसेस की संख्या से विभाजित आरएसएस का आनुपातिक साइज़ होता है. यह हिसाब रखने के लिए सबसे अच्छी मेट्रिक है.
    • nr_procs: उन प्रोसेस की संख्या जो फ़िलहाल इस बफ़र का रेफ़रंस रखती हैं.
    • एक्सपोर्टर: वह ड्राइवर जिसने बफ़र को असाइन किया है. उदाहरण के लिए, virtio_gpu Cuttlefish पर या हार्डवेयर पर वेंडर के हिसाब से Ion/DMA-BUF हीप.

    सभी बफ़र और पूरे सिस्टम में डीएमए-बीयूएफ़ के इस्तेमाल की खास जानकारी के लिए, adb shell dmabuf_dump -b का इस्तेमाल भी किया जा सकता है.


← Java | ↑ Up | Native →