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


مدیریت حافظه android

مدیریت حافظه در اندروید چگونه است؟

مدیریت حافظه در اندروید حین توسعه یک برنامه امری ضروری و حیاتی ست. با استفاده از این مقاله می توانید استفاده از حافظه را حین توسعه برنامه اندرویدی بهبود دهید.

اندروید از سیستم pagging و mmap برای مدیریت حافظه استفاده می کنه. روند کار به این صورت است که تا شما کاملا از برنامه خارج نشوید هیچ کدام از بخش های درگیر حافظه مرتبط با برنامه آزاد نخواهند شد.

اندازه heapی که به برنامه اختصاص داده می شود محدود است. از 2MB شروع می شود و بیشترین مقدار که به largeHeap مرسوم هست به 36MB محدود می شود (البته بنابه تنظیمات هر دیوایس می تواند متغیر باشد). برنامه هایی مثل ادیتورهای عکس و ویدئو، دوربین، گالری و home screen از جمله برنامه هایی با large heap هستند.

اندروید پردازش های پس زمینه هر برنامه را در بخش LRU cache نگه می دارد. استراتژی LRU برای مدیریت حافظه در اندروید به این صورت است که وقتی سیستم با کمبود حافظه رو به رو شود این پردازش ها رو متوفق کند. ولی در این حالت هم اول تشخیص می دهد کدام برنامه بیشتر از بقیه حافظه را درگیر کرده است. در حال حاضر، بیشترین تعداد پروسه ای که می تواند در پس زمینه اجرا شود 20تاست (بسته به تنظیمات دیوایس این عدد متغیر است).

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

Garbage Collection

بخش های مختلف مدیریت حافظه در اندروید مثل ART یا Dalvik virtual machine هر اختصاص حافظه ای که در برنامه صورت گیرد را دنبال خواهند کرد. هر بخشی از حافظه که مشخص شود دیگر مورد نیاز برنامه نیست آزاد می شود و در اختیار heap قرار خواهد گرفت. تمام این پروسه بدون اینکه برنامه نویس در روند آن مداخله ای داشته باشد پیش می رود. پروسه بازگشت حافظه ی بی استفاده در برنامه که به کمک بخش مدیریت حافظه در اندروید صورت میگیرد را به نام garbage collection می شناسند. Garbage collection دو هدف اصلی را دنبال می کند : پیدا کردن objectهایی که در آینده برای برنامه قابل استفاده نباشند و آزاد کردن منابعی که به آنها تخصیص داده شده است.

Heap در حافظه اندروید با دسته بندی نسلی داده ها را دسته بندی می کند. به این معنی که ظرف های متفاوتی برای تخصیص حافظه به متغیرها از نظر اندازه و طول عمر آنها وجود دارد. بطور مثال objectی که به تازگی ساخته شده باشد در رده جوان Young generation قرار می گیرد. وقتی این object به مدت مشخصی فعال باشد  به ظرف دیگری (Older generation) منتقل خواهد شد و به همین ترتیب این روند ادامه دارد.

هر نسل از heap حافظه اختصاصی مربوط به خود را دارد که تا حدی بیش از محدودیت حافظه صرف شده در نظر گرفته شده ست. هر زمانی که نسلی از heap در حال تکمیل باشد، سیستم به سراغ garbage collection میره و سعی می کند تا حافظه درگیر را آزاد کند. زمانی که garbage collection برای عمل به مکانیزم خودش نیاز داره به این بستگی داره که روی کدوم نسل از objectها کار میکنه و چه تعداد object فعال در هر نسل وجود دارند.

با وجود اینکه garbage collection در مدیریت حافظه در اندروید عملکرد بسیار سریعی دارد اما کماکان می تواند روی اجرای برنامه تاثیر گذارد. شما نمی توانید در کد مشخص کنید چه زمانی garbage collection کار خود را آغاز کند. سیستم ضوابطی دارد که بر اساس آنها تعیین می کند چه زمانی garbage collection اجرا شود.

حال اگر garbage collection زمانی وارد عمل شود که خودِ برنامه در حال انجام یک پروسه متناوب مثل اجرای یک انیمیشن یا هنگام پخش یک موسیقی باشد، زمان انجام پروسه کاری garbage collection افزایش پیدا خواهد کرد. این افزایش می تواند باعث شود اجرای کد برنامه بطور پیش فرض 16ms به تعویق بیافتد تا هم چنان برنامه روان اجرا شود و تجربه کاربری خوبی را ایجاد کند.

به علاوه امکان دارد روند برنامه شما طوری نوشته شده باشد که garbage collection مجبور شود تعداد دفعات بیشتری اجرا شود یا حتی هر مرتبه طولانی تر اجرا شود. برای مثال اگر در بدنه یک حلقه for  تعداد زیادی object تعریف کرده باشید برای هر فریم از انیمشین که بخواهد اجرا شود حافظه heap با تعداد زیادی object رو به رو خواهد شد. در این چرخه garbage collection دفعات زیادی مجبور به کار خواهد شد. به همین نسبت روی پرفورمنس برنامه هم تاثیر منفی خواهد گذاشت.

راه کارهایی برای استفاده بهینه از حافظه

در این بخش لیستی از راهکارها و همین طور best practice ها  برای مدیریت حافظه در اندروید جمع آوری شده:

  1. وقتی قصد دارید از abstraction یا کلاس های انتزاعی استفاده کنید، دقت کنید. از این نظر که abstraction باعث می شود معماری کد انعطاف پذیر تر باشد بهینه ست ، اما از طرفی باعث می شود تعداد خط بیشتری کد اجرا شود. خود این عمل هزینه بر خواهد بود. هم از نظر زمانی و هم از نظر میزان حافظه ای که برنامه به خود اختصاص می دهد. پس فقط زمانی از abstraction استفاده کنید که واقعا یک مزیت قابل توجه در اختیار برنامه قرار دهد.
  2. از بکارگیری “enum” ها بپرهیزید. Enum به نسبت ثابت ها دو برابر بیشتر حافظه را درگیر می کنند. پس بهتر است از آنها صرف نظر کنید.
  3. سعی کنید بطور بهینه از ظرف های SparseArray و SparseBooleanArray و LongSparseArray به جای HashMap استفاده کنید. همان طور که می دانید HashMap برای هر بار عمل mapping که انجام می دهد کل object را درگیر می کند که عمل بهینه ای نیست و هم چنین منجر به یک performance ضعیف خواهد شد. اما به خاطر داشته باشید که اگر تعداد داده ها بیشتر از هزارتا باشه SparceArrayها برای عملیاتی مثل حذف و اضافه و جست و جو عملکرد ضعیف و کندتری به نسبت HashMap دارند.
  4. از ایجاد object غیر ضروری بپرهیزید. اگر طول عمر objectی که نیاز به استفاده از آن دارید کوتاه تر از آن است که بعنوان یک object ساخته شود راه دیگری را در نظر بگیرید. به این شکل با تعداد object کمتر وظیفه garbage collection هم کمتر خواهد شد.
  5. میزان heap در دسترس را چک کنید. به واسطه متد ActivityManager::getMemoryClass() یک کوئری ایجاد کنید تا ببینید چند MB از حافظه ی heap در اختیار برنامه شماست. در غیر این صورت با استثنای OutOfMemory رو به رو می شوید. اگر برنامه شما در قسمت xml مشخص کرده باشه که قصد دارد از “largeHeap” استفاده کند می توانید متد getLargeMemoryClass() رو صدا بزنید تا ببینید میزان حافظه در نظر گرفته شده برای large heap چقدر می باشد.
  6. متناسب با برنامه کال بکی از onTrimMemory() را پیاده سازی کنید. این پیاده سازی از متد onTromMemory(int) در اکتیویتی، سرویس یا ContentProvider پیاده سازی می شود تا رفته رفته حافظه درگیر در برنامه آزاد شود و سرعت کلی پاسخ گویی سیستم نیز بهبود پیدا کند.
  7. هنگامی که TIRM_MEMORY_UI_HIDDEN در برنامه اتفاق میافتد به این معنی ست که کل UI در برنامه شما ناپدید شده و ضروری ست منابع UI را آزاد کنید.
  8. تمام کتابخانه های خارج از برنامه که در برنامه به آنها نیاز دارید باید با دقت هرچه تمام استفاده شوند. بیشتر کتابخانه های خارجی برای دیوایس هایی غیر از موبایل نوشته شده اند و به همین خاطر برای اندروید بهینه نشده اند. در صورت نیاز به این دست کتابخانه ها شما باید سعی کنید تا حد امکان کدهای مربوط به کتابخانه را برای اندروید بهینه کنید. مثلا اگر کتابخانه ای با هزاران امکان را فقط برای یک یا دو مورد از امکانات موجود در آن استفاده می کنید بهتر است خودتان موارد مورد نیاز را پیاده سازی کنید.
  9. سرویس ها باید با دقت و وسواس استفاده شوند. اگر شما برای انجام عملیات خاصی نیاز دارید تا از سرویسی در پیش زمینه استفاده کنید. باید به محض اینکه آن کارکرد مشخص تمام شد از اجرای سرویس جلوگیری کنید. سعی کنید از IntentService استفاده کنید که با اتمام کار خود intent را مدیریت می کند. در غیر این صورت اگر در موارد غیر ضروری از سرویس ها استفاده کنید پرفورمنس ضعیف تری خواهید داشت که در نتیجه باعث نارضایتی کاربر خواهد شد و در نهایت برنامه شما را حذف نماید.
  10. اما اگر برنامه شما نیاز دارد که در زمان بیشتری از سرویسی مثل پخش موزیک استفاده کند، شما باید کلیت کار را به دو بخش تقسیم کنید: یکی برای UI و دیگری برای سرویس در پس زمینه (این کار به کمک تنظیم “android:process” در مانیفست انجام میدیم). منابع UI بعد از استفاده ناپدید می شوند و بخش سرویس هم چنان در پس زمینه به عملیات خود ادامه می دهد. به خاطر بسپرید هیچ کدام از عملیات پس زمینه هرگز نباید با UI یک جا انجام بگیرند. وگرنه میزان حافظه درگیر ممکن است دو تا سه برابر افزایش یابد.

 

امیدوارم مقاله مدیریت حافظه در اندروید در ارائخ یک دید کلی نسبت به موضوع  مفید بوده باشد حتما در مقاله(های) دیگری درباره memory leak که البته بحث مفصل و مهمی هست، مطلب خواهیم نوشت.

به این پست امتیاز دهید

روی ستاره های کلیک کنید و امتیاز بدید

میانگین امتیاز / 5. تعداد:

یک دیدگاه در “مدیریت حافظه در اندروید

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *




Enter Captcha Here : *

Reload Image