تنفيذ محاسبة ذاكرة DMABUF وGPU في Android 12

توضح هذه الصفحة التحسينات المتنوعة لحساب الذاكرة التي تم تقديمها في Android 12.

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

في Android 11 وAndroid 12، لا يمكن تثبيت 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 الفريد <inode_number> .
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name يحتوي هذا الملف للقراءة فقط على اسم مصدر DMA-BUF.
/sys/kernel/dmabuf/buffers/<inode_number>/size يحدد هذا الملف للقراءة فقط حجم DMA-BUF بالبايت.

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

يرجى ملاحظة أن برامج تشغيل kernel التي تقوم بتصدير DMA-BUFs يجب أن تقوم بتعيين حقل 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 heaps ، والذي يعد جزءًا من نواة Linux الأولية.

يتم تتبع إحصائيات ION العالمية التالية في Android 11:

  • الحجم الإجمالي لـ DMA-BUFs المصدرة بواسطة كل كومة ION
  • الحجم الإجمالي للذاكرة المخصصة مسبقًا غير المستخدمة والمخزنة بواسطة كل كومة ION

لا توجد واجهة متاحة لعرض إحصائيات الكومة لكل ION في Android 11.

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

Android 11 أو الأجهزة التي يتم تشغيلها بدعم ION في Android 12 الأجهزة التي يتم تشغيلها باستخدام أكوام DMA-BUF في Android 12
إحصائيات أيون لكل كومة لا أحد تم تحليلها من إحصائيات DMA-BUF sysfs
الحجم الإجمالي لوحدات DMA-BUF المصدرة /sys/kernel/ion/total_heap_size_kb
(لا يشمل حجم DMA-BUFs المصدرة من قبل المصدرين غير الأيونيين)
تم تحليلها من إحصائيات DMA-BUF sysfs
(يتضمن حجم كافة وحدات 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، فقد جاءت ذاكرة GPU مما يلي:

  • التخصيصات المباشرة التي يتم إجراؤها بواسطة برنامج تشغيل GPU باستخدام مخصص الصفحة الفعلي
  • تم تعيين DMA-BUFs في مساحة عنوان GPU

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

وتفاصيل الحل كالتالي:

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

الحل المطبق مفصل في القسم التالي.

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

نظرًا لأن تطبيقات Memtrack HAL يمكن أن تختلف عبر الشركاء، فإن ذاكرة GPU المضمنة في 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 واستبدالها بذاكرة GPU الخاصة ( 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;

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

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

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

تصديق

تفرض اختبارات VTS القاعدة التي تنص على أن الأجهزة التي تعمل بنظام التشغيل Android 12 بإصدار Linux kernel 5.4 أو أعلى تدعم واجهة برمجة تطبيقات getGpuDeviceInfo() .

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

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

تطبيق

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

تم التخطيط لتحويل جميع HIDL HALs إلى 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() API لإرجاع إجمالي الذاكرة العامة لوحدة معالجة الرسومات بشكل صحيح عند استدعائها باستخدام PID 0 لـ MemtrackType::GL وMemtrackRecord:: FLAG_SMAPS_UNACCOUNTED.