تنفيذ ميزة احتساب ذاكرة وحدة معالجة الرسومات وDMABUF في Android 12

تصف هذه الصفحة التحسينات المختلفة في حساب الذاكرة التي تم تقديمها في الإصدار 12 من نظام التشغيل Android.

إحصائيات DMA-BUF في sysfs

في الإصدارَين 11 و12 من نظام التشغيل Android، لا يمكن تثبيت debugfs في إصدارات المستخدم. لذلك، تمت إضافة إحصاءات DMA-BUF إلى sysfs في دليل /sys/kernel/dmabuf/buffers في Android 12.

المسار الوصف
/sys/kernel/dmabuf/buffers يحتوي الدليل /sys/kernel/dmabuf/buffers على نبذة عن الحالة الداخلية لكل DMA-BUF. يحتوي /sys/kernel/dmabuf/buffers/<inode_number> على إحصاءات عن DMA-BUF التي تحمل رقم ملف البيانات الفريد <inode_number>.
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name يحتوي هذا الملف للقراءة فقط على اسم جهة تصدير DMA-BUF.
/sys/kernel/dmabuf/buffers/<inode_number>/size يحدد هذا الملف للقراءة فقط حجم DMA-BUF بالبايت.

libdmabufinfo تحلّل واجهة برمجة التطبيقات إحصاءات sysfs الخاص بمنطقة DMA-BUF لعرض إحصاءات خاصة بكل مصدِّر وحسب المخزن المؤقت.

يُرجى ملاحظة أنّ برامج تشغيل النواة التي تصدّر ملفات DMA-BUF يجب أن تضبط exp_name. في الحقل struct dma_buf_export_info بشكل صحيح إلى اسم المُصدِّر قبل لاستدعاء واجهة برمجة التطبيقات dma_buf_export() لإنشاء DMA-BUF. هذا الإجراء مطلوب في libdmabufinfo وأداة dmabuf_dump لاستنتاج الإحصاءات لكل مصدِّر: في تقرير الأخطاء.

تم تعديل أداة dmabuf_dump لعرض هذه المعلومات باستخدام وسيطة جديدة، وهي -b.

إحصاءات إطار عمل لقطات لعناصر متعدّدة في DMA-BUF

يتم إيقاف ION في GKI 2.0 نهائيًا لصالح إطار عمل كومدات DMA-BUF، الذي يُعدّ جزءًا من نواة Linux الأساسية.

يتم تتبُّع الإحصاءات العالمية التالية حول ION في Android 11:

  • إجمالي حجم DMA-BUF التي يتم تصديرها من خلال كل كومة ION
  • إجمالي حجم الذاكرة غير المستخدَمة والمخصّصة مسبقًا والتي تخزّنها كلّ كومّة ION

لا تتوفّر واجهة لعرض إحصاءات كل ذاكرة ION في Android 11.

يقارن الجدول التالي بين واجهات إحصاءات ION نظيرها للأجهزة التي تستخدم إطار عمل DMA-BUF لأجزاء من النظام في Android 12.

أجهزة Android 11 أو الأجهزة التي تعمل بنظام التشغيل Android 12 مع إتاحة ION إطلاق الأجهزة التي تتضمّن ذاكرة التخزين المؤقت DMA-BUF في نظام التشغيل Android 12
إحصاءات ION لكل كومّة بدون تحديد نمط تم تحليل البيانات من إحصاءات DMA-BUF sysfs.
إجمالي حجم وحدات DMA-BUF التي تم تصديرها /sys/kernel/ion/total_heap_size_kb
(لا يشمل حجم ملفات DMA-BUF التي تم تصديرها من خلال جهات تصدير غير تابعة لـ ION)
تحليل البيانات من إحصاءات أنظمة DMA-BUF
(يشمل حجم جميع نماذج DMA-BUF التي تم تصديرها).
إجمالي الذاكرة المجمّعة حسب الحِزم /sys/kernel/ion/total_pool_size_kb /sys/kernel/dma_heap/total_pool_size_kb

تحسين دقة احتساب ذاكرة الوصول العشوائي المفقودة

في السابق، كان يتم حساب ذاكرة الوصول العشوائي المفقودة على النحو التالي:

الطول النهائي lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)

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

- kernelUsed - memInfo.getZramTotalSizeKb()

يتضمّن المكوِّن totalPss استخدام ذاكرة وحدة معالجة الرسومات (الذي يعرضه getMemory() من Memtrack HAL ). يتضمّن المكوّن kernelUsed إجمالي استخدام ذاكرة DMA-BUF. ومع ذلك، بالنسبة إلى أجهزة Android، تأتي ذاكرة وحدة معالجة الرسومات من المصادر التالية:

  • عمليات التخصيص المباشرة التي أجراها برنامج تشغيل وحدة معالجة الرسومات باستخدام أداة تخصيص الصفحة الفعلية
  • ربط رموز DMA-BUF في مساحة عنوان وحدة معالجة الرسومات

لذلك، تم طرح وحدات DMA-BUF التي تم ربطها بالذاكرة في مساحة عناوين وحدة معالجة الرسومات مرتين عند احتساب ذاكرة الوصول العشوائي المفقودة. الإصدار 12 من نظام التشغيل Android تنفيذ حل لحساب حجم وحدات DMA-BUF التي تم تعيينها في وحدة معالجة الرسومات مساحة العنوان، ما يعني أنه تم احتسابها مرة واحدة فقط في عمود احتساب ذاكرة الوصول العشوائي (RAM).

تفاصيل الحل هي كما يلي:

  • عند استدعاء واجهة برمجة التطبيقات Memtrack HAL API getMemory() باستخدام PID 0، يجب أن تُبلغ عن إجمالي الذاكرة الخاصة بوحدة معالجة الرسومات على مستوى النظام، وذلك لأجل MemtrackType::GL وMemtrackRecord::FLAG_SMAPS_UNACCOUNTED.
  • يجب ألا يتعذّر تنفيذ getMemory() عند طلبها باستخدام PID 0 لـ MemtrackType بدلاً من GL. وبدلاً من ذلك، يجب أن يكون الناتج 0.
  • حلّ نقطة تتبُّع ذاكرة وحدة معالجة الرسومات/eBPF التي تتم إضافتها في Android 12 لإجمالي ذاكرة وحدة معالجة الرسومات. يؤدي طرح إجمالي الذاكرة الخاصة لوحدة معالجة الرسومات من إجمالي ذاكرة وحدة معالجة الرسومات إلى حجم وحدات DMA-BUF التي تم تعيينها في مساحة عنوان وحدة معالجة الرسومات. يمكن بعد ذلك استخدام القيمة لتحسين دقة حسابات ذاكرة الوصول العشوائي المفقودة من خلال حساب استخدام ذاكرة وحدة معالجة الرسومات.
  • يتم تضمين ذاكرة وحدة معالجة الرسومات الخاصة في totalPss في معظم طبقات Memtrack HAL. عمليات التنفيذ، وبالتالي يجب إزالة تكرارها قبل إزالتها من lostRAM.

يتم شرح الحل الذي تم تنفيذه في القسم التالي.

إزالة التباين في أداة Memtrack من ذاكرة الوصول العشوائي المفقودة

وبما أنّ عمليات تنفيذ طبقة تجريد الأجهزة (HAL) في Memtrack قد تختلف باختلاف الشركاء، تتسع ذاكرة وحدة معالجة الرسومات التي يتم تضمينها في totalPSS من HAL ليست متسقة دائمًا. لإزالة التفاوت من lostRAM، تتم إزالة الذاكرة المُدرَجة في MemtrackType::GRAPHICS وMemtrackType::GL من totalPss أثناء احتساب lostRAM.

تمت إزالة ذكرى واحدة (MemtrackType::GRAPHICS) من "totalPss" واستبدالها بـ استخدام الذاكرة totalExportedDmabuf في العملية الحسابية lostRAM في ActivityManagerService.java كما هو موضح أدناه:

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" واستبدالها بـ ذاكرة وحدة معالجة الرسومات الخاصة (gpuPrivateUsage) في العملية الحسابية lostRAM ActivityManagerService.java كما هو موضح أدناه:

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;

تم تعديل عملية احتساب ذاكرة الوصول العشوائي (RAM) المفقودة.

إنّ كل من إجمالي ذاكرة وحدة معالجة الرسومات الخاصة وإجمالي ذاكرة المخزن المؤقت لمنطقة السوق المحددة التي تم تصديرها تم تضمينها في kernelUsed + totalPss والتي تمت إزالتها من lostRAM. هذا النمط إزالة كل من الحساب المزدوج وتباين Memtrack من ذاكرة الوصول العشوائي المفقودة عملية حسابية.

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

التحقُّق

تفرض اختبارات سلامة النقل (VTS) قاعدة أنّ الأجهزة التي تعمل بالإصدار 12 من Android التي تستخدم الإصدار 5.4 من نواة Linux أو إصدارًا أحدث تكون متوافقة مع واجهة برمجة التطبيقات getGpuDeviceInfo() .

يجب أن تعرض واجهة برمجة تطبيقات Memtrack HAL getGpuDeviceInfo() الجديدة معلومات حول جهاز وحدة معالجة الرسومات المستخدَم.

ويؤدي ذلك إلى توفير معلومات أفضل عن الذاكرة وإمكانية الاطّلاع على استخدام ذاكرة وحدة معالجة الرسومات وذاكرة وحدة التخزين المؤقت لوحدة DMA. تنفيذ memtrack AIDL HAL لتحسين احتساب ذاكرة الوصول العشوائي المفقودة والذاكرة لا تعتمد هذه الميزة على خدمات Google.

التنفيذ

تعتمد هذه الميزة على AIDL Memtrack HAL، وتوجيهات تنفيذها في Android 12 يتم تضمينها في التعليمات البرمجية كتعليقات.

من المخطّط تحويل جميع واجهات HIDL HAL إلى واجهات AIDL في الإصدارات المستقبلية.

تمت إضافة واجهات برمجة التطبيقات التالية إلى 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();

لضمان عمل الإصدار على النحو المطلوب، ادمج نقاط التتبع في وحدة معالجة الرسومات. وبرامج التشغيل، وتنفيذ واجهة برمجة تطبيقات AIDL Memtrack HAL getMemory() لعرض الإجمالي العام للذاكرة الخاصة لوحدة معالجة الرسومات عند استدعائها باستخدام PID 0 لـ MemtrackType::GL وMemtrackRecord:::FLAG_SMAPS_UNACCOUNTED.