توی این پست قراره به اندروید ران تایم بپردازیم. درمورد دالویک و ART و انواع روش هایی که برای اجرای برنامه ها استفاده شده نگاه بندازیم . منبع اصلی اینجاست که این پست از روش ترجمه شده. اگه دوست داشتید میتونید با زبان اصلیش بخونید.
اندروید ران تایم (Android runtime) یکی از اجزای اصلی اندرویده. خیلی از شما ممکنه اسم چیزایی مثل ART ، Dalvik ، JIT یا AOT رو شنیده باشید. اگه شما میخواید بدونید که اینا چی هستن و اندروید ران تایم چجوری کار میکنه جای خوبی اومدید ، توی این پست به این موضوع میپردازیم.
وقتی ما اپلیکیشنی رو میسازیم و ازش خروجی APK میگیریم، قسمتی از این فایل APK فایل هایی با فرمت dex هستن. این فایل ها شامل کل کد های اپلیکیشن ما به همراه کتابخونه (Library) هایی که استفاده کردیم هستن که البته به صورت Bytecode نوشته شدن.
وقتی کاربر اپلیکیشن رو اجرا میکنه ، بایت کد هایی که داخل فایل های dex هستن توسط اندروید ران تایم به زبان ماشین ترجمه میشن تا ماشین این کد ها رو بفهمه و توسط CPU پردازش بشن.
به علاوه کامپایل کردن ، اندروید ران تایم دو تا عمل مهم دیگه یعنی مدیریت حافظه و garbage collection (عملی که باعث میشه پروسه هایی که لازم نیستن بسته بشن) رو انجام میده. چون نمیخوایم این پست طولانی نشه ما به فقط به کامپایل کردن میپردازیم.
عمل کامپایل کردن بایت کد به زبان ماشین میتونه با روش های مختلفی انجام بشه که هر کدوم از این روش های مزایا و معایب خودشونو دارن. برای اینکه ما بفهمیم اندروید ران تایم چجوری کار میکنه باید چند سال به عقب برگردیم و اول بفهمیم دالویک (Dalvik) چیه.
قبلا در آغاز کار اندروید ، گوشی ها به اندازه الان قوی نبودن. بیشتر گوشی های اون موقع RAM خیلی کمی داشتن حتی کمتر از 200 مگابایت. پس عجیب نیست که اینو بدونید اندروید ران تایم اولیه که اسمش دالویک بود ، مهم ترین و اصلی ترین کارش مدیریت و بهبود استفاده از RAM توسط دستگاه بود.
پس بجای اینکه دالویک قبل از اجرای برنامه ها همه رو به زبان ماشین کامپایل کنه، از یه روشی به اسم Just in time (در لحظه) استفاده میکرد که به صورت مخفف بهش میگفتن JIT .
در این روش، کامپایلر یه جورایی شبیه یه واسط عمل میکنه و هنگام اجرای هر برنامه ، تیکه های کوچیکی از کد ها رو کامپایل میکنه. پس با این روش چون دالویک فقط کد هایی رو کامپایل میکنه که نیازن و قراره اجرا بشن ، مقدار زیادی RAM صرفه جویی میشه.
اما این روش یه عیب داره ، به دلیل اینکه عمل کامپایل کردن موقع اجرای برنامه اتفاق میوفته ، مسلما تاثیر بدی روی عملکرد حین اجرا داره.
برای همین یه راه هایی معرفی شدن که باهاشون دالویک بتونه عملکرد بهتری داشته باشه. یکی از راه ها این بود که تیکه کد هایی که زیاد مورد استفاده قرار میگیرن و کامپایل شده هستن ، در حافظه کش (cache) ذخیره میشن تا دیگه دوباره کامپایل نشن. اما یه مشکلی که وجود داشت این بود که RAM در اون زمان خیلی کم بود.
این روش چند سالی جواب داد در حالی که عملکرد گوشیا روز به روز بهتر و مقدار RAM اونا روز به روز بیشتر میشد و همینطور که اپلیکیشن ها هر روز بزرگ تر میشدن ، روش JIT هر روز به مشکل بزرگتری تبدیل میشد.
و اینجوری شد که توی اندروید Lollipop 5 ، یه اندروید ران تایم جدید معرفی شد که جای دالویک رو بگیره . اسم اون ART بود.
مدلی که ART کار میکرد 180 درجه با مدلی که دالویک کار میکرد متفاوت بود. ART بجای روش JIT (کامپایل حین اجرا) که توسط دالویک اجرا میشد ، با یه روشی کار میکرد به اسم Ahead of time compilation (کامپایل قبل اجرا) که به اختصار بهش میگن AOT.
در ART بجای اینکه کامپایلر عین یه واسط ، حین اجرا کد ها رو کامپایل کنه ، از قبل همه رو کامپایل میکرد پس وقتی یه اپلیکیشن اجرا میشد ، کد ها از قبل آماده شده بودن.
این روش تاثیر مثبت بزرگی روی عملکرد حین اجرا داشت و تقریبا 20 برابر سریعتر از JIT بود.
مشکلش چی بود ؟ همون طور که انتظار میره ART توی اندروید 5 RAM خیلی بیشتری نسبت به دالویک اشغال میکرد.
یه ایراد دیگه این بود که توی اندروید 5 خیلی طول میکشید تا یه اپلیکیشن نصب بشه چون بعد دانلود برنامه ، کل کد ها باید به زبان ماشین کامپایل میشد و همیطور بروزرسانی های سیستمی خیلی بیشتر طول میکشید چون همه برنامه ها باید از دوباره کامپایل و بهینه میشدن.
اینجوری شد که توی اندروید nougat 7 روش JIT برگشت اما اینبار با دوست جدیدی به اسم Profile-Guided Compilation.
روش Profile-Guided Compilation باعث میشه که به طور مداوم عملکرد اپلیکیشن ها وقتی اجرا میشن بهتر بشه. به طور پیشفرض ، اپلیکیشنا با روش JIT کامپایل میشن اما وقتی که ART تشخیص بده که بعضی فعالیت ها "Hot" یا پرکاربرد هستن ، اونا رو از قبل کامپایل میکنه و در حافظه کش ذخیره میکنه تا دستگاه بهترین عملکرد رو داشته باشه.
این روش باعث میشه که بهترین عملکرد رو داشته باشیم در حالی که مصرف RAM زیادی هم نداریم. بعدا هم معلوم شد که بیشتر اپلیکیشن ها فقط از 10 تا 20 درصد از کدهاشون پرکاربرد یا همون "Hot" هستن.
بعد این تغییری که توی ART رخ داد ، فرایند نصب اپلیکیشن ها دیگه طولانی نبود و همینطور بروزرسانی های سیستمی هم خیلی طول نمیکشید. فرایند کامپایل کردن کد ها از قبل هم فقط وقتی گوشی در حال شارژ یا در حالت Idle ( وقتی که از گوشی استفاده ای نمیشه و بیکاره) هستش اتفاق میوفته تا کمترین تاثیر منفی رو توی گوشی داشته باشیم.
تنها مشکلی که وجود داشت این بود که برای اینکه یه profile از یه اپلیکیشنی ساخته بشه ، باید اون اپلیکیشن استفاده میشد. یعنی وقتی شما اپلیکیشنی رو تازه نصب کرده باشید و هنوز ازش استفاده نکرده باشید ، چون هنوز profile ساخته نشده ،ART نمیدونه کجای این اپلیکیشن پرکاربرده ، پس شما با کندی سرعت اپلیکیشن مواجه میشید. مسلما با چند بار استفاده از اپلیکیشن این مشکل از بین میره چون اون موقع Profile ساخته میشه.
ایجوری شد که گوگل دست به کار شد و توی اندروید Pie 9 یه چیزی رو معرفی کرد به اسم : Profiles in the cloud به معنی پروفایل ها در ابر ( خداییش نباید این چیزا رو ترجمه کرد به بزرگی خودتون ببخشید :) ).
طرح و فکر اصلی که توی این روش به کار رفت این بود که بیشتر آدما به یک شکل از اپلیکیشن ها استفاده میکنن. خب پس ما میتونیم دقیقا بعد نصب اپلیکیشن روی گوشی یه کاربر ، اطلاعات پروفایل اون اپلیکیشن رو از کاربرایی که قبلا از اون اپلیکیشن استفاده کردن دریافت کنیم. پس دیگه نیازی به پروفایل سازی نیست . این پروفایل ها دریافت میشن و در فایلی ذخیره میشن که اون فایله شامل یه اطلاعات پروفایل اولیه برای یه اپلیکیشن هست.
وقتی که کاربر داره اپ رو نصب میکنه ، در همون موقع پروفایل اپلیکیشن هم دانلود میشه. ART از این اطلاعاتی که دانلود میشن استفاده میکنه تا از قبل بدونه چه کار هایی پرکاربرد هستن تا اونا رو زود تر کامپایل کنه و آماده کنه. با این روش کاربرهایی که اپ جدید نصب میکنن ، در استفاده اولشون از اون اپ ، عملکرد بهتری رو تجربه میکنن.
یادتون باشه این چیزا به این معنی نیست که روش قدیمی دیگه منسوخ شده و استفاده نمیشه! بعد اینکه کاربر اپ رو اجرا کرد ، ART اطلاعات کاربر رو جمع آوری میکنه تا ببینه کدوم تیکه های اپ زیاد دارن استفاده میشن ، بعد که اطلاعات کامل جمع آوری شد موقعی که گوشی استفاده ای ازش نمیشه یا توی شارژه اون تیکه های اپ کامپایل و ذخیره میشن.
نکته خوشحال کننده اش برای برنامه نویسا اینه که لازم نیس اونا کاری بکنن بلکه Android runtime خودش همه کارا رو انجام میده.
اندروید ران تایم وظیفه اش اینه بایت کد های اپلیکیشن ها رو به زبون ماشین کامپایل و ترجمه کنه تا CPU کارشو انجام بده.
اولین اندروید ران تایم اسمش دالویک بود که از روش کامپایل JIT (کامپایل در لحظه) استفاده میکرد تا استفاده از RAM رو بهبود ببخشه .
توی اندروید 5 برای اینکه عملکرد بهتری داشته باشیم ، ART جای دالویک رو گرفت. ART از روش Ahead of time(کامپایل جلو تر از اجرا) یا به اختصار AOT استفاده میکرد. با این روش ما موقع اجرای اپ ها تجربه بهتری داشتیم ولی باید زمان نصب های طولانی و مصرف RAM زیاد رو تحمل میکردیم.
بخاطر همین توی اندروید 7 ، روش JIT به اندروید برگشت اما اینبار به همراه روش Profile-guided compilation . توی این روش جدید بخش های پرکاربرد اپ شناسایی میشدن تا از قبل کامپایل بشن. این باعث شد عملکرد دستگاه خیلی بهتر بشه.
توی اندروید 9 گوگل برای اینکه کاربرا بهترین عملکرد ممکن رو بعد از نصب اپ تجربه کنن ، Profiles in the cloud معرفی شد تا روش قبلی رو تکمیل کنه. توی این روش پروفایل ها همون اول به همراه فایل APK دانلود میشدن تا از ابتدا ما یه پروفایل آماده برای اپ داشته باشیم.