توضّح هذه الصفحة التحسينات المختلفة التي تم إدخالها على نظام احتساب الذاكرة في 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
إحصاءات sysfs
DMA-BUF لعرض إحصاءات لكل عملية تصدير ولكل مخزن مؤقت.
يُرجى العِلم أنّ برامج تشغيل النواة التي تصدّر DMA-BUF يجب أن تضبط الحقل exp_name
في struct dma_buf_export_info
بشكل صحيح على اسم المصدر قبل استدعاء واجهة برمجة التطبيقات dma_buf_export()
لإنشاء DMA-BUF.
هذا الإعداد مطلوب لتطبيق libdmabufinfo
وأداة dmabuf_dump
من أجل استخلاص إحصاءات لكل مصدِّر، ثم عرضها في bugreport.
تم تعديل أداة dmabuf_dump
لعرض هذه المعلومات باستخدام وسيطة جديدة، وهي -b
.
إحصاءات إطار عمل أكوام DMA-BUF
سيتم إيقاف ION نهائيًا في الإصدار 2.0 من GKI لصالح إطار عمل أكوام DMA-BUF، وهو جزء من نواة Linux المتوافقة مع أحدث إصدار.
يتم تتبُّع إحصاءات ION العامة التالية في Android 11:
- إجمالي حجم مخازن DMA-BUFs التي تم تصديرها بواسطة كل كومة ION
- الحجم الإجمالي للذاكرة غير المستخدَمة والمخصّصة مسبقًا والمخزَّنة في كل كومة ION
لا تتوفّر واجهة لعرض إحصاءات الذاكرة المؤقتة لكل ION في نظام التشغيل Android 11.
يقارن الجدول التالي بين واجهات إحصاءات ION ونظيراتها للأجهزة التي تستخدم إطار عمل مكدس DMA-BUF في Android 12.
الأجهزة التي تعمل بالإصدار 11 من نظام التشغيل Android أو الأجهزة التي تتوافق مع ION في الإصدار 12 من نظام التشغيل Android | الأجهزة التي تم إطلاقها مع أكوام DMA-BUF في Android 12 | |
---|---|---|
إحصاءات ION لكل كومة | بدون تحديد نمط | تم تحليلها من إحصاءات DMA-BUF sysfs |
إجمالي حجم شرائح الجمهور المحدّدة حسب المنطقة الجغرافية (DMA) وشرائح المستخدمين المحدّدة حسب المنطقة (BUA) التي تم تصديرها | /sys/kernel/ion/total_heap_size_kb
(لا يشمل حجم ملفات DMA-BUF التي يتم تصديرها من خلال أدوات التصدير غير التابعة لـ ION) |
تم تحليلها من إحصاءات sysfs الخاصة بـ DMA-BUF
(تشمل حجم جميع DMA-BUF التي تم تصديرها). |
إجمالي الذاكرة المجمّعة حسب أكوام الذاكرة | /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
استخدام ذاكرة وحدة معالجة الرسومات (التي تعرضها واجهة getMemory() في Memtrack HAL). يتضمّن المكوّن kernelUsed
إجمالي استخدام ذاكرة DMA-BUF.
ومع ذلك، بالنسبة إلى أجهزة Android، كانت ذاكرة وحدة معالجة الرسومات تأتي من المصادر التالية:
- عمليات التخصيص المباشرة التي ينفّذها برنامج تشغيل وحدة معالجة الرسومات باستخدام أداة تخصيص الصفحات الفعلية
- وحدات تخزين مؤقتة DMA مرتبطة بمساحة عناوين وحدة معالجة الرسومات
لذلك، تم طرح DMA-BUFs التي تم ربطها بالذاكرة في مساحة عناوين وحدة معالجة الرسومات مرتين عند احتساب ذاكرة الوصول العشوائي المفقودة. يتضمّن نظام التشغيل Android 12 حلاً لاحتساب حجم DMA-BUF التي تم ربطها بمساحة عناوين وحدة معالجة الرسومات، ما يعني أنّه يتم احتسابها مرة واحدة فقط في عملية احتساب Lost RAM.
في ما يلي تفاصيل الحل:
- يجب أن تعرض واجهة برمجة التطبيقات Memtrack HAL
getMemory()
عند استدعائها باستخدام معرّف العملية 0 إجمالي الذاكرة الخاصة بوحدة معالجة الرسومات على مستوى النظام، وذلك بالنسبة إلى MemtrackType::GL وMemtrackRecord::FLAG_SMAPS_UNACCOUNTED. - يجب ألا يتعذّر تنفيذ getMemory() عند استدعائه مع
PID
0
لعنصرMemtrackType
غيرGL
. يجب أن تعرض القيمة 0 بدلاً من ذلك. - يحتسب حل نقطة تتبُّع/eBPF لذاكرة وحدة معالجة الرسومات الذي تمت إضافته في Android 12 إجمالي ذاكرة وحدة معالجة الرسومات. يؤدي طرح إجمالي ذاكرة وحدة معالجة الرسومات الخاصة من إجمالي ذاكرة وحدة معالجة الرسومات إلى توفير حجم DMA-BUFs التي تم ربطها بمساحة عناوين وحدة معالجة الرسومات. يمكن بعد ذلك استخدام القيمة لتحسين دقة حسابات Lost RAM من خلال احتساب استخدام ذاكرة وحدة معالجة الرسومات بشكل صحيح.
- يتم تضمين ذاكرة وحدة معالجة الرسومات الخاصة في
totalPss
في معظم عمليات تنفيذ Memtrack HAL، وبالتالي يجب إزالة التكرار قبل إزالتها منlostRAM
.
يتم توضيح الحلّ الذي تم تنفيذه في القسم التالي.
إزالة التفاوت في Memtrack من ذاكرة الوصول العشوائي المفقودة
بما أنّ عمليات تنفيذ Memtrack HAL يمكن أن تختلف بين الشركاء، فإنّ ذاكرة وحدة معالجة الرسومات المضمّنة في 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;
تعديل طريقة احتساب ذاكرة الوصول العشوائي المفقودة
يتم تضمين كلّ من إجمالي ذاكرة وحدة معالجة الرسومات الخاصة وإجمالي ذاكرة مخزن DMA التي تم تصديرها في 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()
معلومات عن جهاز وحدة معالجة الرسومات المستخدَم.
يتيح ذلك إمكانية احتساب الذاكرة بشكل أفضل والاطّلاع على استخدام ذاكرة وحدة معالجة الرسومات (GPU) ومخزن DMA المؤقت. نفِّذ واجهة HAL الخاصة بـ memtrack AIDL من أجل تحسين احتساب الذاكرة المفقودة وذاكرة الوصول العشوائي. لا تعتمد هذه الميزة على خدمات Google.
التنفيذ
تعتمد هذه الميزة على AIDL Memtrack HAL، وتتضمّن التعليمات الخاصة بتنفيذها في Android 12 في الرمز البرمجي كتعليقات.
من المخطّط تحويل جميع طبقات HAL لواجهة HIDL إلى 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();
لضمان عمل الإصدار على النحو المطلوب، عليك دمج نقاط التتبُّع في برامج تشغيل وحدة معالجة الرسومات (GPU) وتنفيذ واجهة برمجة التطبيقات AIDL memtrack HAL getMemory()
لعرض إجمالي الذاكرة الخاصة بوحدة معالجة الرسومات بشكل صحيح عند طلبها باستخدام المعرّف 0 لـ MemtrackType::GL وMemtrackRecord::FLAG_SMAPS_UNACCOUNTED.