بیتمپها اغلب بزرگترین اشیاء مصرفکننده حافظه در یک برنامه هستند. عملیات رمزگشایی و مقیاسبندی اغلب در مسیر بحرانی رندر فریم قرار دارند. بهینهسازی استفاده از حافظه بیتمپ با کاهش jank، ANR و توقفهای فرآیند مربوط به OOM، پیشرفتهای قابل توجهی در پاسخگویی رابط کاربری، عمر باتری و پایداری کلی ایجاد میکند.
شناسایی میزان بالای استفاده از حافظه بیتمپ
Android Vitals با جمعآوری دادهها از دستگاههای اندروید، معیارهایی را در مورد میزان مصرف حافظه بیتمپ یک برنامه ارائه میدهد. این معیارها شامل درصدهای مبتنی بر دوره (به عنوان مثال، ۲۸ روزه) در هر بسته و فرآیند هستند. این دادهها به شناسایی روندها و رگرسیونهای بالقوه در کارایی حافظه در انواع و نسخههای مختلف دستگاه کمک میکند.
Android Vitals میزان استفاده از حافظه بیتمپ برنامه شما را که توسط حالتهای فرآیند زیر تفکیک شده است، به اشتراک میگذارد:
- پیشزمینه : فرآیند برنامه قابل مشاهده است. انتظار میرود که P99 در پیشزمینه به طور قابل توجهی بالاتر از سایر حالتهای فرآیند باشد، اما توسعهدهندگان باید بررسی کنند که آیا نسبت P99/P50 قابل توجه است یا خیر (مثلاً بالاتر از 3.5x)، زیرا این اغلب به نشت حافظه بیتمپ اشاره دارد. میتوانید این را با جستجوی واگرایی بین استفاده معمول (P50) و استفاده پرت (P99) شناسایی کنید. در حالی که نفخ کلی دارایی، حافظه را به طور یکنواخت در تمام صدکها افزایش میدهد، نشت حافظه با گذشت زمان ترکیب میشود و دادههای انتهایی (P99) را به شدت منحرف میکند. اطمینان حاصل کنید که تخصیصهای بیتمپ پیشزمینه پس از انتقال برنامه به حالتهای دیگر، بیجهت ادامه نمییابند.
- سرویسهای درکشده توسط کاربر : فرآیند برنامه در یک وضعیت قابل درک اجرا میشود. این شامل سرویسهای پیشزمینه ، کارهای تسریعشده و کارهای انتقال داده آغازشده توسط کاربر میشود . برنامهها نباید هنگام انتقال به این وضعیتها، تخصیصهای سنگین نقشه بیتی پیشزمینه را حفظ کنند. از آنجا که این سرویسها برای وظایف طولانیمدت طراحی شدهاند، نگهداشتن داراییهای بزرگ، تجربه کلی کاربر را خراب میکند و سرویس قاتل حافظه کم (LMKD) را مجبور میکند با خاتمه دادن به فرآیندهای با اولویت پایینتر، حافظه را بازیابی کند.
- پسزمینه : برنامه در حال اجرای یک سرویس پسزمینه است، یا اخیراً در پسزمینه قرار گرفته است، اما هنوز در حافظه پنهان (cache) ذخیره نشده است. از آنجا که این وضعیت فرآیند اهمیت کمتری نسبت به فرآیندهای پیشزمینه یا قابل درک دارد، برنامهها باید صریحاً دادههای بیتمپ بزرگ را در اینجا منتشر کنند تا فشار بر حافظه کاهش یابد.
- ذخیره شده (Cached ): برنامه در حالت ذخیره شده (cache) قرار دارد. این حالت به فشار حافظه سیستم مانند LMKها بسیار حساس است. برنامهها باید در این حالت به طور فعال استفاده از حافظه بیتمپ را کاهش دهند تا از حذف شدن توسط سیستم عامل جلوگیری شود.
عوامل مؤثر در استفاده زیاد از حافظه بیتمپ
حافظه مجازی که هرگز استفاده نشده است نیز ممکن است در محاسبه لحاظ شود. اگر به طور غیرمنتظرهای شاهد استفاده زیاد از حافظه بیتمپ بودید، بررسی کنید که حافظهای را که استفاده نشده است، اختصاص نمیدهید.
منابع
تحلیل بیتمپها در اندروید استودیو
پروفایلینگ اندروید استودیو برای بیتمپها
از Memory Profiler برای بررسی تخصیص حافظه به صورت بلادرنگ، ثبت دادههای هیپ و تجزیه و تحلیل اشیاء برای یافتن نشتی حافظه استفاده کنید؛ علاوه بر این، از Heap Analyzer برای تشخیص نشتی حافظه، شناسایی تخصیصهای بیتمپ تکراری و تجسم حفظ اشیاء استفاده کنید.
تشخیص خودکار نشت با LeakCanary
کتابخانه LeakCanary را برای خودکارسازی تشخیص نشت حافظه در برنامه خود ادغام کنید. LeakCanary تجزیه و تحلیل خودکار پشته را ارائه میدهد و اشیایی را که باید جمعآوری زباله میشدند اما هنوز در حافظه نگهداری میشوند، مانند بیتمپهایی که توسط فعالیتها یا قطعات تخریبشده حفظ شدهاند، شناسایی میکند.
مستندات عملکرد بیتمپ
این منابع راهنمایی جامعی در مورد بهترین شیوهها برای مدیریت کارآمد بیتمپ در اجزای مختلف اندروید ارائه میدهند.
چک لیست توسعهدهندگان برای بهینهسازی استفاده از حافظه بیتمپ
برای بهینهسازی کارایی حافظه بیتمپ، سه اصل اساسی را دنبال کنید: کاهش، استفاده مجدد و بازیافت.
- کاهش : هنگام بارگذاری یا نمایش بیتمپها، میزان حافظه اولیه را به حداقل میرساند.
- استفاده مجدد : پیادهسازی مکانیزمهای ذخیرهسازی موقت برای جلوگیری از تخصیصهای تکراری بیتمپ.
- بازیافت : منابع را به صورت پیشگیرانه آزاد میکند تا امکان تخصیص مجدد حافظه برای فرآیندهای فعال فراهم شود.
چک لیست توسعهدهندگان زیر میتواند به شما در بهینهسازی استفاده از حافظه بیتمپ کمک کند.
| اصل اساسی | مساحت | توضیحات |
|---|---|---|
| کاهش | حذف بیتمپهای تکراری | با استفاده از Memory Profiler، دادههای هیپ دامپ را تجزیه و تحلیل کنید تا تخصیصهای بیتمپ اضافی را شناسایی کنید. به راهنمای مدیریت حافظه بیتمپ مراجعه کنید. |
| استفاده از کتابخانههای بارگذاری تصویر | از کتابخانههایی مانند Glide و Coil برای خودکارسازی threading، caching و decoding کارآمد استفاده کنید. | |
| پیادهسازی نمونهبرداری کاهشی | به جای بارگذاری فایلهای با وضوح کامل، تصاویر را طوری رمزگشایی کنید که با ابعاد کانتینر رابط کاربری هدف مطابقت داشته باشند. | |
| برای تصاویر مات از RGB_565 استفاده کنید | با تغییر از ARGB_8888 به پیکربندی ۱۶ بیتی برای تصاویر بدون شفافیت، میزان مصرف حافظه را تا ۵۰٪ کاهش دهید. | |
| اولویتبندی VectorDrawableها | برای آیکونها و گرافیکهای پایه از بردارها استفاده کنید تا مقیاسبندی دقیق با حداقل سربار حافظه تضمین شود. | |
| بهینهسازی تحویل تصویر سمت سرور | APIهای بکاند را طوری پیکربندی کنید که تصاویر متناسب با تراکم دستگاه و ابعاد ImageView ارائه شوند . | |
| حاشیههای شفاف را حذف کنید | با استفاده از InsetDrawable یا layout padding به جای حاشیههای از پیش تعیینشده، از تخصیص حافظه برای پیکسلهای «نامرئی» جلوگیری کنید. به بخش مهندسی برنامههای اندروید با عملکرد حافظه بالا مراجعه کنید. | |
| استفاده مجدد | پیکربندی اندازههای بهینه حافظه پنهان | محدودیتهای حافظه و حافظه پنهان دیسک را بر اساس رم دستگاه و وضوح صفحه نمایش تنظیم کنید. به ذخیرهسازی بیتمپها مراجعه کنید. |
| بازیافت | پاکسازی منابع در پسزمینه | برای پاک کردن حافظههای پنهان و بهبود بقای فرآیند در هنگام فشار بر حافظه سیستم TRIM_MEMORY_BACKGROUND را پیادهسازی کنید . |
| انتشار داراییها زمانی که رابط کاربری پنهان است | از TRIM_MEMORY_UI_HIDDEN برای آزادسازی حافظههای نهان بیتمپ زمانی که برنامه دیگر برای کاربر قابل مشاهده نیست، استفاده کنید . | |
| نظارت بر نشت حافظه | از LeakCanary و Memory Profiler برای یافتن بیتمپهایی که پس از از بین رفتن LifecycleOwner آنها باقی ماندهاند، استفاده کنید. به مدیریت حافظه برنامه خود مراجعه کنید. |