مروری بر مدیریت حافظه

Android Runtime (ART) و ماشین مجازی Dalvik از صفحه‌بندی و نقشه‌برداری حافظه (mmapping) برای مدیریت حافظه استفاده می‌کنند. این بدان معنی است که هر حافظه ای که برنامه تغییر می دهد - چه با تخصیص اشیاء جدید یا لمس صفحات نقشه برداری شده - در RAM باقی می ماند و نمی توان آن را صفحه بندی کرد. تنها راه برای آزاد کردن حافظه از یک برنامه، آزاد کردن ارجاعات اشیایی است که برنامه نگهداری می‌کند و حافظه را در دسترس جمع‌آورنده زباله قرار می‌دهد. این با یک استثنا است: اگر سیستم بخواهد از آن حافظه در جای دیگری استفاده کند، هر فایلی که بدون هیچ تغییری در آن نگاشت شده است، مانند کد، می‌تواند از RAM خارج شود.

این صفحه نحوه مدیریت فرآیندهای برنامه و تخصیص حافظه را توضیح می دهد. برای اطلاعات بیشتر درباره نحوه مدیریت کارآمدتر حافظه در برنامه، به مدیریت حافظه برنامه خود مراجعه کنید.

جمع آوری زباله

یک محیط حافظه مدیریت شده، مانند ماشین مجازی ART یا Dalvik، هر تخصیص حافظه را پیگیری می کند. هنگامی که مشخص می کند که یک قطعه از حافظه دیگر توسط برنامه استفاده نمی شود، آن را بدون هیچ گونه مداخله ای از سوی برنامه نویس به پشته باز می کند. مکانیسم بازیابی حافظه استفاده نشده در محیط حافظه مدیریت شده به عنوان جمع آوری زباله شناخته می شود. جمع آوری زباله دو هدف دارد: یافتن اشیاء داده در یک برنامه که در آینده قابل دسترسی نیست. و منابع مورد استفاده توسط آن اشیاء را بازیابی کنید.

پشته حافظه اندروید یک نسل است، به این معنی که سطل های مختلفی از تخصیص ها وجود دارد که براساس طول عمر و اندازه مورد انتظار یک شی که تخصیص داده می شود، آنها را ردیابی می کند. به عنوان مثال، اشیاء اخیراً به نسل جوان تعلق دارند. هنگامی که یک شی به مدت کافی فعال بماند، می توان آن را به نسل قدیمی تر ارتقا داد و به دنبال آن یک نسل دائمی.

هر نسل هیپ محدودیت بالایی اختصاصی خود را در میزان حافظه ای دارد که اشیاء در آنجا می توانند اشغال کنند. هر زمان که یک نسل شروع به پر شدن می کند، سیستم یک رویداد جمع آوری زباله را در تلاش برای آزاد کردن حافظه اجرا می کند. مدت زمان جمع‌آوری زباله بستگی به این دارد که کدام نسل از اشیاء را جمع‌آوری می‌کند و در هر نسل چند شیء فعال وجود دارد.

اگرچه جمع آوری زباله می تواند بسیار سریع باشد، اما همچنان می تواند بر عملکرد برنامه شما تأثیر بگذارد. شما معمولاً کنترل نمی‌کنید که یک رویداد جمع‌آوری زباله از داخل کد شما رخ دهد. این سیستم دارای مجموعه ای از معیارهای در حال اجرا برای تعیین زمان جمع آوری زباله است. هنگامی که معیارها برآورده شدند، سیستم اجرای فرآیند را متوقف می کند و جمع آوری زباله را آغاز می کند. اگر جمع آوری زباله در وسط یک حلقه پردازش فشرده مانند یک انیمیشن یا در حین پخش موسیقی اتفاق بیفتد، می تواند زمان پردازش را افزایش دهد. این افزایش به طور بالقوه می‌تواند اجرای کد در برنامه شما را از آستانه ۱۶ میلی‌ثانیه توصیه‌شده برای رندر فریم کارآمد و صاف عبور دهد.

علاوه بر این، جریان کد شما ممکن است انواعی از کارها را انجام دهد که رویدادهای جمع‌آوری زباله را مجبور می‌کند بیشتر اتفاق بیفتند یا طولانی‌تر از حد معمول طول بکشند. به عنوان مثال، اگر در طول هر فریم از یک انیمیشن ترکیبی آلفا، چندین شی را در درونی ترین قسمت حلقه for اختصاص دهید، ممکن است حافظه خود را با اشیاء زیادی آلوده کنید. در این شرایط، جمع‌آورنده زباله چندین رویداد جمع‌آوری زباله را اجرا می‌کند و می‌تواند عملکرد برنامه شما را کاهش دهد.

برای اطلاعات عمومی بیشتر در مورد جمع آوری زباله، به جمع آوری زباله مراجعه کنید.

حافظه را به اشتراک بگذارید

اندروید برای اینکه همه چیز مورد نیاز خود را در رم جا دهد، سعی می کند صفحات رم را در بین فرآیندها به اشتراک بگذارد. می تواند به روش های زیر این کار را انجام دهد:

  • هر فرآیند برنامه از یک فرآیند موجود به نام Zygote منشعب می شود. فرآیند Zygote زمانی شروع می‌شود که سیستم بوت می‌شود و کدها و منابع رایج چارچوب (مانند موضوعات فعالیت) را بارگیری می‌کند. برای شروع یک فرآیند برنامه جدید، سیستم فرآیند Zygote را منقطع می کند و سپس کد برنامه را در فرآیند جدید بارگیری و اجرا می کند. این رویکرد به اکثر صفحات RAM اختصاص داده شده برای کد فریمورک و منابع اجازه می دهد تا در تمام فرآیندهای برنامه به اشتراک گذاشته شوند.
  • بیشتر داده های استاتیک در یک فرآیند mmapped می شوند. این تکنیک اجازه می دهد تا داده ها بین فرآیندها به اشتراک گذاشته شوند، و همچنین اجازه می دهد تا در صورت نیاز صفحه بندی شوند. نمونه‌ای از داده‌های استاتیک عبارتند از: کد Dalvik (با قرار دادن آن در یک فایل .odex از پیش پیوند شده برای mmapping مستقیم)، منابع برنامه (با طراحی جدول منبع به عنوان ساختاری که می‌تواند mmmap شود و با تراز کردن ورودی‌های فشرده APK) و عناصر پروژه سنتی مانند کد بومی در فایل‌های .so .
  • در بسیاری از مکان‌ها، اندروید رم پویا یکسانی را در بین فرآیندها با استفاده از مناطق حافظه مشترک اختصاص داده شده (با ashmem یا gralloc) به اشتراک می‌گذارد. به عنوان مثال، سطوح پنجره از حافظه مشترک بین برنامه و سازنده صفحه استفاده می کنند و بافرهای مکان نما از حافظه مشترک بین ارائه دهنده محتوا و مشتری استفاده می کنند.

با توجه به استفاده گسترده از حافظه مشترک، تعیین میزان استفاده از حافظه برنامه شما نیاز به دقت دارد. تکنیک‌هایی برای تعیین درست میزان استفاده از حافظه برنامه‌تان در بررسی استفاده از RAM شما بحث شده است.

تخصیص و بازیابی حافظه برنامه

پشته Dalvik به یک محدوده حافظه مجازی برای هر فرآیند برنامه محدود می شود. این اندازه منطقی هیپ را مشخص می‌کند، که می‌تواند در صورت نیاز رشد کند، اما فقط تا حدی که سیستم برای هر برنامه تعریف می‌کند.

اندازه منطقی هیپ با مقدار حافظه فیزیکی استفاده شده توسط هیپ یکسان نیست. هنگام بررسی هیپ برنامه شما، اندروید مقداری به نام اندازه تنظیم متناسب (PSS) را محاسبه می‌کند، که هم صفحات کثیف و هم تمیزی را که با سایر فرآیندها به اشتراک گذاشته می‌شوند، محاسبه می‌کند - اما فقط به مقداری که متناسب با تعداد برنامه‌هایی است که آن RAM را به اشتراک می‌گذارند. این کل (PSS) چیزی است که سیستم به عنوان ردپای حافظه فیزیکی شما در نظر می گیرد. برای اطلاعات بیشتر در مورد PSS، راهنمای استفاده از RAM را بررسی کنید.

پشته Dalvik اندازه منطقی هیپ را فشرده نمی کند، به این معنی که اندروید برای بستن فضا، هیپ را یکپارچه نمی کند. اندروید تنها زمانی می‌تواند اندازه منطقی پشته را کوچک کند که فضای بلااستفاده در انتهای پشته وجود داشته باشد. با این حال، این سیستم همچنان می‌تواند حافظه فیزیکی استفاده شده توسط هیپ را کاهش دهد. پس از جمع‌آوری زباله، دالویک روی پشته راه می‌رود و صفحات استفاده نشده را پیدا می‌کند، سپس آن صفحات را با استفاده از madvise به هسته برمی‌گرداند. بنابراین، تخصیص های جفتی و تخصیص تکه های بزرگ باید منجر به بازیابی تمام (یا تقریباً همه) حافظه فیزیکی استفاده شده شود. با این حال، بازیابی حافظه از تخصیص‌های کوچک می‌تواند بسیار کمتر کارآمد باشد، زیرا صفحه مورد استفاده برای تخصیص کوچک ممکن است همچنان با چیز دیگری که هنوز آزاد نشده است به اشتراک گذاشته شود.

حافظه برنامه را محدود کنید

برای حفظ یک محیط چند وظیفه ای کاربردی، اندروید برای هر برنامه محدودیت سختی را برای اندازه پشته تعیین می کند. محدودیت اندازه دقیق پشته بین دستگاه‌ها بر اساس میزان رم کلی دستگاه متفاوت است. اگر برنامه شما به ظرفیت پشته رسیده باشد و سعی کند حافظه بیشتری را اختصاص دهد، می تواند OutOfMemoryError دریافت کند.

در برخی موارد، ممکن است بخواهید از سیستم پرس و جو کنید تا دقیقاً چه مقدار فضای پشته ای در دستگاه فعلی در دسترس دارید - به عنوان مثال، تعیین کنید که چه مقدار داده برای نگهداری در حافظه پنهان امن است. شما می توانید با فراخوانی getMemoryClass() از سیستم برای این شکل پرس و جو کنید. این روش یک عدد صحیح نشان می دهد که تعداد مگابایت های موجود برای پشته برنامه شما را نشان می دهد.

برنامه ها را تغییر دهید

وقتی کاربران بین برنامه‌ها جابه‌جا می‌شوند، Android برنامه‌هایی را که پیش‌زمینه نیستند (یعنی برای کاربر قابل مشاهده نیستند یا سرویس‌های پیش‌زمینه مانند پخش موسیقی اجرا می‌کنند) را در حافظه پنهان نگه می‌دارد. به عنوان مثال، هنگامی که کاربر برای اولین بار یک برنامه را راه اندازی می کند، یک فرآیند برای آن ایجاد می شود. اما هنگامی که کاربر برنامه را ترک می کند، این روند متوقف نمی شود. سیستم فرآیند را در حافظه پنهان نگه می دارد. اگر کاربر بعداً به برنامه بازگردد، سیستم از فرآیند استفاده مجدد می‌کند و در نتیجه سرعت تعویض برنامه را افزایش می‌دهد.

اگر برنامه شما دارای یک فرآیند کش است و منابعی را که در حال حاضر به آنها نیاز ندارد حفظ می کند، برنامه شما - حتی زمانی که کاربر از آن استفاده نمی کند - بر عملکرد کلی سیستم تأثیر می گذارد. از آنجایی که سیستم منابعی مانند حافظه کم دارد، فرآیندهای موجود در حافظه پنهان را از بین می برد. این سیستم همچنین فرآیندهایی را در نظر می گیرد که بیشترین حافظه را در خود نگه می دارند و می توانند آنها را برای آزادسازی رم خاتمه دهند.

توجه: هرچه برنامه شما در حافظه نهان حافظه کمتری مصرف کند، شانس بیشتری برای از بین رفتن و از سرگیری سریع آن خواهد داشت. با این حال، بسته به نیازهای سیستم آنی، این امکان وجود دارد که فرآیندهای ذخیره شده در حافظه پنهان در هر زمانی بدون توجه به استفاده از منابع آنها خاتمه یابد.

برای اطلاعات بیشتر در مورد نحوه ذخیره‌سازی پردازش‌ها در حالی که در پیش‌زمینه اجرا نمی‌شوند و اینکه چگونه Android تصمیم می‌گیرد کدام یک از آنها حذف شوند، به راهنمای Processes and Threads مراجعه کنید.

تست استرس حافظه

اگرچه مشکلات مربوط به استرس حافظه در دستگاه‌های رده بالاتر کمتر رایج است، اما همچنان می‌توانند مشکلاتی را برای کاربران دستگاه‌های با رم پایین، مانند دستگاه‌هایی که Android (نسخه Go) دارند، ایجاد کنند. مهم است که سعی کنید این محیط پر از حافظه را بازتولید کنید تا بتوانید تست‌های ابزار دقیق برای تأیید رفتار برنامه و بهبود تجربه کاربران خود در دستگاه‌های با حافظه کم بنویسید.

تست کاربرد استرس زا

تست برنامه استرس زا ( stressapptest ) یک تست رابط حافظه است که به ایجاد موقعیت های واقعی و پر بار برای آزمایش محدودیت های حافظه و سخت افزار مختلف برای برنامه شما کمک می کند. با توانایی تعریف محدودیت‌های زمان و حافظه، این امکان را به شما می‌دهد تا ابزار دقیق بنویسید تا برخوردهای دنیای واقعی با موقعیت‌های با حافظه بالا را تأیید کنید. به عنوان مثال، از مجموعه دستورات زیر برای فشار دادن کتابخانه ایستا در سیستم فایل داده خود، قابل اجرا کردن آن و اجرای یک تست استرس به مدت 20 ثانیه با حجم 990 مگابایت استفاده کنید:
    adb push stressapptest /data/local/tmp/
    adb shell chmod 777 /data/local/tmp/stressapptest
    adb shell /data/local/tmp/stressapptest -s 20 -M 990

  

برای اطلاعات بیشتر در مورد نصب ابزار، آرگومان های رایج و اطلاعات رسیدگی به خطا به مستندات stressapptest مراجعه کنید.

مشاهدات در آزمون استرس

ابزارهایی مانند stressapptest را می توان برای درخواست تخصیص حافظه بزرگتر از مقدار آزاد استفاده کرد. این نوع درخواست می تواند هشدارهای مختلفی را ایجاد کند که باید از سمت توسعه از آنها آگاه باشید. سه هشدار اصلی که به دلیل در دسترس بودن حافظه کم می توانند مطرح شوند عبارتند از:
  • SIGABRT: این یک خرابی مرگبار و بومی برای فرآیند شما به دلیل درخواست تخصیص اندازه بزرگتر از حافظه آزاد است، در حالی که سیستم از قبل تحت فشار حافظه است.
  • SIGQUIT : یک حافظه هسته خالی تولید می کند و هنگامی که توسط تست ابزار دقیق شما شناسایی شد، فرآیند را خاتمه می دهد.
  • TRIM_MEMORY_EVENTS : این تماس‌ها در Android نسخه 4.1 (سطح API 16) و بالاتر در دسترس هستند و هشدارهای حافظه دقیقی را برای فرآیند شما ارائه می‌دهند.