تجزیه و تحلیل و مدیریت حافظه در اندروید - بخش اول

تجزیه و تحلیل و مدیریت حافظه در اندروید - بخش اول

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

مدیریت حافظه از رشته های پیچیده در علم کامپیوتر به شمار می رود و تکنیک های متعددی در جهت افزایش بهره وری آن توسعه یافته اند. در ادامه چندین مشکل ساده و مقدماتی که برنامه نویسان در مدیریت حافظه با آنها روبه رو می شوند شرح داده شده اند.

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

اندروید یک سیستم عامل مبتنی بر لینوکس است و از کتابخانه های اپن سورس C که برای ماشین های لینوکسی مورد استفاده قرار می گیرند، استفاده می کند. تمامی عملیات ابتدایی سیستم عامل مانند I/O، مدیریت حافظه و غیره توسط کرنل لینوکس مدیریت می شوند. اندروید نیز مشابه جاوا و NET. از ران تایم و ماشین مجازی خود به منظور مدیریت حافظه در اپلیکیشن استفاده می کند، اما بر خلاف این پلتفرم ها ران تیم اندروید فرآیندهای لایف تایم را نیز مدیریت می نماید.

هر اپلیکیشن اندروید در فرآیند مجزایی با نمونه Dalvik خود به اجرا در می آید و مسئولیت مدیریت حافظه و فرآیند را به ران تایم اندروید واگذار می کند و ران تایم نیز اقدام به متوقف کردن و از بین بردن فرآیند ها مطابق با مدیریت منابع می کند. Dalvik یک ماشین مجازی اپن سورس و مبنی بر رجیستر است و قسمتی از سیستم عامل اندروید می باشد. ماشین مجازی Dalvik فایل هایی با فرمت Dalvik Executable یا dex. را به اجرا در می آورد. منابع نیز فایل های ساده با فرمت xml هستند.

Dalvik و ران تایم اندروید در بخش بالایی کرنل اندروید جای گرفته اند، بدین معنا که مسئولیت رسیدگی به تعاملات سخت افزاری سطح پایین شامل درایورها و مدیریت حافظه را بر عهده دارند، در حالی که مجموعه ای از API ها دسترسی به تمامی سرویس های under-lying، امکانات و سخت افزارها را تامین می کنند.

یک بررسی سیستماتیک به همراه ارزیابی داده ها و اطلاعات از اهمیت بالایی برخوردار است، بدین ترتیب می توانید به بهترین نحو به مدیریت حافظه در دسترس اقدام کنید. DDMS نیز برای این منظور در اندروید استودیو تعبیه شده و با استفاده از آن قادر به بررسی حافظه ای که مورد استفاده قرار گرفته می باشید.

DDMS

اندروید استودیو یک ابزار دیباگینگ به نام Dalvik Debug Monitor Service و یا به طور مخفف همان DDMS دارد که تامین کننده سرویس هایی مانند عکس گرفتن از صفحه گوشی، تردینگ، اطلاعات هیپ گوشی، لاگ کت، فرآیندها، تماس های دریافتی، چک کردن پیام های کوتاه، موقعیت قرارگیری، اسپوفینگ داده و چندین مورد دیگر که مرتبط با تست های اندرویدی است می باشد.

blog_15548_1

امکانات DDMS

DDMS در طول اجرای اپلیکیشن، گوشی را به IDE متصل می سازد. در اندروید هر اپلیکیشنی در فرآیند مجزای خود به اجرا در می آید و ماشین مجازی مربوط به خود را دارد و هر فرآیندی به یک دیباگر در یک پورت مختلف گوش می دهد.

هم زمان با شروع، DDMS به ADB یا همان Android Debug Bridge که یک ابزار کامند-لاین است و در اندروید SDK گوگل جای گرفته، متصل می شود. یک دیباگر اندروید برای دیباگ کردن اپلیکیشن اندروید مورد استفاده قرار می گیرد و سرویس نظارت دستگاه بین این دو را راه اندازی می کند و با وصل یا قطع گوشی DDMS را از این موضوع مطلع می سازد. زمانی که گوشی متصل است یک سیستم نظارت VM بین ADB و DDMS بوجود می آید که DDMS را زمانی که VM در گوشی شروع به کار کرده یا خاتمه یافته باخبر می سازد.

حال بیاییدنحوه مصرف حافظه ای که در بالا شرح داده شده را به کمک یک مثال ساده شرح دهیم. اپلیکیشن های اندروید محدود به حافظه heaped شانزده مگابایتی هستند. معمولا گوشی حافظه نسبتا زیادی را مورد استفاده قرار می دهد و حافظه کمی برای استفاده توسعه دهندگان باقی می ماند.

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

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

اکتیویتی و اپلیکیشن

توسعه دهنده اقدام به ارسال یک اکتیویتی به کلاس ها و متدهایی که نیازمند یک Context هستند می کند. یک اکتیویتی نمایش دهنده یک صفحه منفرد با یک رابط کاربری مانند ویندوز یا یک فریم جاوا می باشد.

@Override

protected void onCreate(Bundle state) {

super.onCreate(state);

TextView label = new TextView(this);

label.setText("Leaks are bad");setContentView(label);

}

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

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

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

private static Drawable sBackground;

@Override

protected void onCreate(Bundle state) {

super.onCreate(state);

TextView label = new TextView(this);

label.setText("Leaks are bad");

if (sBackground == null) {

sBackground = getDrawable(R.drawable.large_bitmap);

}

label.setBackgroundDrawable(sBackground);

setContentView(label);

}

 

در قطعه کد بالا، Drawable یک ارجاع به TextView دارد که خود دارای یک ارجاع به اکتیویتی یا Context است که دارای مرجعی به تمامی منابع موردنیاز است. این کد اکتیویتی موجب نشت اکتیویتی با اولین تغییر در جهت صفحه بوجود آمده می شود.

این مثال یک از ساده ترین موارد نشت Context است و شما قادر به مشاهده چگونگی عملکرد آن در صفحه اصلی اپلیکیشن خود می باشید.

مثال بالا ارجاع استاتیک را به نمایش گذاشته است، کلاس های داخلی و ارجاع مطلق به کلاس خارجی خطرناک است، در نتیجه راه حل دیگر برای پیاه سازی این مورد ارائه می دهیم.

راه حل دوم استفاده از Context اپلیکیشن می باشد. این Context تا زمانی که اپلیکیشن زنده است دوام دارد و به چرخه اجرای اکتیویتی ها وابسته نیست. چنانچه قصد دارید آبجکت هایی با عمر طولانی را نگهداری کنید که به یک Context نیاز دارند، از آبجکت اپلیکیشن استفاده کنید. شما با فراخوانی توابع ()Context.getApplicationContext یا ()Activity.getApplication قادر به انجام این کار می شوید.

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

- ارجاع هایی با عمر طولانی را در Context اکتیویتی نگه ندارید(مرجع داده شده به اکتیویتی باید دارای چرخه اجرای مشابه با خود اکتیویتی باشد).

- از context-activity به جای context-application استفاده کنید.

- از استفاده از کلاس های داخلی غیر ثابت در یک اکتیویتی در شرایطی که چرخه اجرای آنها را کنترل نمی کنید، بپرهیزید، از یک کلاس داخلی ثابت استفاده کرده و یک ارجاع ضعیف به اکتیویتی داخل آن بدهید.

- یک garbage collector تضمینی برای نشتی های حافظه در نتیجه کمبود حافظه در دسترس و یا تکه تکه بودن حافظه برای اختصاص یک آبجکت جدید نیست.

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

 

https://acadgild.com برگرفته از

اینها را هم بخوانید