توضّح هذه الصفحة التحسينات المختلفة التي تم إدخالها على نظام احتساب الذاكرة في 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 لعرض إحصاءات لكل مصدر ولكل مخزن مؤقت.
يجب أن تضبط برامج تشغيل النواة التي تصدّر 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.
| Android 11 أو الأجهزة التي تتوافق مع ION في Android 12 | الأجهزة التي يتم إطلاقها مع مساحات 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) المفقودة
في السابق، كان يتم حساب مقدار ذاكرة الوصول العشوائي المفقودة على النحو التالي:
final long 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 المؤقتة التي تم ربطها بمساحة عناوين وحدة معالجة الرسومات، ما يعني أنّه يتم احتسابها مرة واحدة فقط في عملية احتساب ذاكرة الوصول العشوائي المفقودة.
في ما يلي تفاصيل الحل:
- يجب أن تعرض واجهة برمجة التطبيقات Memtrack HAL 
getMemory()عند استدعائها باستخدام معرّف العملية 0 إجمالي الذاكرة الخاصة بوحدة معالجة الرسومات على مستوى النظام، وذلك لكل منMemtrackType::GLوMemtrackRecord::FLAG_SMAPS_UNACCOUNTED. getMemory()عند استدعائه معPID 0لقيمةMemtrackTypeغيرGLيجب ألا يتعذّر. يجب أن تعرض القيمة 0 بدلاً من ذلك.- يقدّم حل نقطة تتبُّع ذاكرة وحدة معالجة الرسومات/eBPF الذي تمت إضافته في Android 12 إجمالي ذاكرة وحدة معالجة الرسومات. يؤدي طرح إجمالي ذاكرة وحدة معالجة الرسومات الخاصة من إجمالي ذاكرة وحدة معالجة الرسومات إلى توفير حجم DMA-BUFs التي تم ربطها بمساحة عناوين وحدة معالجة الرسومات. يمكن بعد ذلك استخدام القيمة لتحسين دقة عمليات احتساب ذاكرة الوصول العشوائي المفقودة من خلال احتساب استخدام ذاكرة وحدة معالجة الرسومات بشكل صحيح.
 - يتم تضمين ذاكرة وحدة معالجة الرسومات الخاصة في 
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();
للتحقّق من أنّ الإصدار يعمل على النحو المنشود، ادمِج نقاط التتبُّع في برامج تشغيل وحدة معالجة الرسومات، ونفِّذ واجهة برمجة التطبيقات AIDL memtrack HAL getMemory() لعرض إجمالي الذاكرة الخاصة بوحدة معالجة الرسومات بشكل صحيح عند استدعائها باستخدام معرّف العملية 0 لكل من MemtrackType::GL وMemtrackRecord::FLAG_SMAPS_UNACCOUNTED.