پیاده سازی حسابداری حافظه DMABUF و GPU در اندروید 12

این صفحه بهبودهای مختلف حسابداری حافظه معرفی شده در اندروید 12 را شرح می دهد.

آمار DMA-BUF در sysfs

در اندروید 11 و اندروید 12، debugfs نمی‌توان در ساخت‌های کاربری نصب کرد. بنابراین آمار DMA-BUF به sysfs در فهرست /sys/kernel/dmabuf/buffers در اندروید 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 API آمار DMA-BUF sysfs را تجزیه می‌کند تا آمار هر صادرکننده و هر بافر را نشان دهد.

لطفاً توجه داشته باشید که درایورهای هسته که DMA-BUF ها را صادر می کنند، باید قبل از فراخوانی API dma_buf_export() برای ایجاد یک DMA-BUF، فیلد exp_name struct dma_buf_export_info را روی نام صادرکننده تنظیم کنند. این برای libdmabufinfo و ابزار dmabuf_dump برای استخراج آمار هر صادرکننده مورد نیاز است که سپس در گزارش اشکال نمایش داده می‌شود.

ابزار dmabuf_dump برای خروجی این اطلاعات با آرگومان جدید، -b اصلاح شده است.

آمار برای چارچوب پشته های DMA-BUF

ION در GKI 2.0 به نفع چارچوب پشته‌های DMA-BUF ، که بخشی از هسته بالادستی لینوکس است، منسوخ شده است.

آمار جهانی ION زیر در اندروید 11 ردیابی می شود:

  • اندازه کل DMA-BUFهای صادر شده توسط هر پشته ION
  • اندازه کل حافظه از پیش تخصیص داده نشده ذخیره شده توسط هر پشته ION

هیچ رابطی برای نمایش آمار هیپ هر یون در اندروید 11 در دسترس نیست.

جدول زیر رابط های آماری ION را با همتایان خود برای دستگاه هایی که از چارچوب هیپ DMA-BUF در اندروید 12 استفاده می کنند، مقایسه می کند.

Android 11 یا دستگاه هایی که با پشتیبانی ION در اندروید 12 راه اندازی می شوند دستگاه‌هایی که با پشته‌های DMA-BUF در Android 12 راه‌اندازی می‌شوند
آمار یون هر هیپ هیچ یک تجزیه از آمار DMA-BUF sysfs
اندازه کل DMA-BUFهای صادر شده /sys/kernel/ion/total_heap_size_kb
(اندازه DMA-BUF های صادر شده توسط صادرکنندگان غیریون را شامل نمی شود)
تجزیه از آمار DMA-BUF sysfs
(شامل اندازه تمام DMA-BUFهای صادر شده است).
کل حافظه جمع آوری شده توسط پشته ها /sys/kernel/ion/total_pool_size_kb /sys/kernel/dma_heap/total_pool_size_kb

دقت محاسبه RAM از دست رفته را بهبود بخشید

قبلاً محاسبه RAM از دست رفته به صورت زیر انجام می شد:

آخرین Long lostRAM = memInfo.getTotalSizeKb( ) - ( totalPss - totalSwapPss )

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

- kernelUsed - memInfo.getZramTotalSizeKb() ;

جزء totalPss شامل استفاده از حافظه GPU بود (که توسط رابط getMemory() Memtrack HAL برگردانده شد. مؤلفه kernelUsed شامل کل مصرف حافظه DMA-BUF بود. با این حال، برای دستگاه های اندرویدی، حافظه GPU از موارد زیر است:

  • تخصیص مستقیم توسط درایور GPU با استفاده از تخصیص دهنده صفحه فیزیکی
  • DMA-BUF ها در فضای آدرس GPU نگاشت شده اند

بنابراین، DMA-BUFهایی که با حافظه در فضای آدرس GPU نگاشت شده بودند، با محاسبه RAM از دست رفته دو بار کم شدند. اندروید 12 راه حلی را برای محاسبه اندازه DMA-BUF های نگاشت شده در فضای آدرس GPU پیاده سازی می کند، به این معنی که تنها یک بار در محاسبه رم گم شده به حساب می آید.

جزئیات راه حل به شرح زیر است:

  • Memtrack HAL API getMemory() هنگامی که با PID 0 فراخوانی می شود باید کل حافظه GPU خصوصی را برای MemtrackType::GL و MemtrackRecord::FLAG_SMAPS_UNACCOUNTED گزارش کند.
  • getMemory () هنگامی که با PID 0 برای MemtrackType غیر از GL فراخوانی می شود، نباید شکست بخورد. در عوض باید 0 برگرداند.
  • راه حل ردیابی/eBPF حافظه GPU اضافه شده در Android 12 کل حافظه GPU را به خود اختصاص می دهد. با کم کردن کل حافظه خصوصی GPU از کل حافظه GPU، اندازه DMA-BUF های نگاشت شده در فضای آدرس GPU فراهم می شود. سپس می‌توان از این مقدار برای بهبود دقت محاسبات رم از دست رفته با محاسبه صحیح مصرف حافظه GPU استفاده کرد.
  • حافظه GPU خصوصی در totalPss در اکثر پیاده سازی های Memtrack HAL گنجانده شده است و بنابراین باید قبل از حذف آن از lostRAM حذف شود.

راه حل اجرا شده در بخش بعدی به تفصیل توضیح داده شده است.

تغییرپذیری Memtrack را از RAM از دست رفته حذف کنید

از آنجایی که پیاده سازی Memtrack HAL می تواند در شرکای مختلف متفاوت باشد، حافظه GPU موجود در totalPSS از HAL همیشه سازگار نیست. برای حذف تغییرپذیری از lostRAM ، حافظه در نظر گرفته شده در MemtrackType::GRAPHICS و MemtrackType::GL در طول محاسبه lostRAM از totalPss حذف می‌شود.

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;

محاسبه RAM از دست رفته به روز شد

هم کل حافظه GPU خصوصی و هم کل حافظه بافر DMA صادر شده در kernelUsed + totalPss موجود است که از lostRAM حذف شده است. این امر هم دوبار شمارش و هم تغییرپذیری Memtrack را از محاسبه RAM از دست رفته حذف می کند.

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

اعتبار سنجی

تست‌های VTS این قانون را اجرا می‌کنند که دستگاه‌هایی که در اندروید 12 با هسته لینوکس نسخه 5.4 یا بالاتر راه‌اندازی می‌شوند، از API ()getGpuDeviceInfo پشتیبانی می‌کنند.

یک Memtrack HAL API getGpuDeviceInfo() جدید باید اطلاعات مربوط به دستگاه GPU در حال استفاده را برگرداند.

این حسابداری حافظه و دید بهتری را در بافر DMA و استفاده از حافظه GPU فراهم می کند. پیاده سازی memtrack AIDL HAL برای از دست دادن بهتر RAM و حسابداری حافظه. این ویژگی به خدمات Google وابسته نیست.

پیاده سازی

این ویژگی به AIDL Memtrack HAL بستگی دارد و دستورالعمل‌های پیاده‌سازی آن در اندروید 12 به‌عنوان نظر در کد موجود است.

تمام HIDL HAL ها برنامه ریزی شده است که در نسخه های بعدی به AIDL تبدیل شوند.

API های زیر به 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 خود ادغام کنید و API AIDL memtrack HAL getMemory() را پیاده سازی کنید تا به درستی کل حافظه خصوصی GPU-GPU را هنگامی که با PID 0 برای MemtrackType::GL و MemtrackRecord فراخوانی می شود، بازگردانید: FLAG_SMAPS_UNACCOUNTED.