بهبودهای Android 8.0 ART

زمان اجرا اندروید (ART) در نسخه اندروید 8.0 به طور قابل توجهی بهبود یافته است. لیست زیر به طور خلاصه پیشرفت هایی را که سازندگان دستگاه می توانند در ART انتظار داشته باشند، نشان می دهد.

زباله جمع کن همزمان

همانطور که در Google I/O اعلام شد، ART دارای یک جمع‌کننده زباله (GC) جدید در اندروید 8.0 است. این کلکتور هر بار که GC اجرا می‌شود و در حین اجرای برنامه، پشته را فشرده می‌کند، تنها با یک مکث کوتاه برای پردازش ریشه‌های نخ. در اینجا مزایای آن وجود دارد:

  • GC همیشه پشته را فشرده می کند: به طور متوسط ​​​​32٪ اندازه پشته کوچکتر در مقایسه با Android 7.0.
  • فشردگی تخصیص شی نشانگر ضربه محلی رشته را فعال می کند: تخصیص ها 70 درصد سریعتر از Android 7.0 است.
  • در مقایسه با اندروید 7.0 GC، 85 درصد زمان مکث کمتری را برای معیار H2 ارائه می دهد.
  • زمان مکث دیگر با اندازه پشته مقیاس نمی شود. برنامه ها باید بتوانند از انبوه های بزرگ بدون نگرانی در مورد jank استفاده کنند.
  • جزئیات پیاده سازی GC - خواندن موانع:
    • موانع خواندن مقدار کمی از کار انجام شده برای هر فیلد شی خوانده شده است.
    • اینها در کامپایلر بهینه شده اند، اما ممکن است برخی موارد استفاده را کاهش دهند.

بهینه سازی حلقه

طیف گسترده ای از بهینه سازی های حلقه توسط ART در نسخه اندروید 8.0 استفاده شده است:

  • محدودیت ها حذف شده را بررسی می کند
    • استاتیک: ثابت شده است که محدوده ها در زمان کامپایل در محدوده هستند
    • پویا: تست‌های زمان اجرا تضمین می‌کنند که حلقه‌ها در محدوده باقی می‌مانند (در غیر این صورت)
  • حذف متغیرهای القایی
    • القای مرده را حذف کنید
    • القایی را که فقط بعد از حلقه استفاده می شود با عبارات شکل بسته جایگزین کنید
  • حذف کد مرده در داخل بدنه حلقه، حذف کل حلقه هایی که مرده می شوند
  • کاهش قدرت
  • تبدیل حلقه: معکوس، تبادل، تقسیم، باز کردن، تک مدولار و غیره.
  • SIMDization (همچنین بردارسازی نامیده می شود)

بهینه ساز حلقه در پاس بهینه سازی خودش در کامپایلر ART قرار دارد. اکثر بهینه سازی های حلقه شبیه بهینه سازی و ساده سازی در جاهای دیگر هستند. چالش‌هایی با برخی بهینه‌سازی‌ها ایجاد می‌شوند که CFG را به روشی پیچیده‌تر از معمول بازنویسی می‌کنند، زیرا اکثر ابزارهای CFG (به nodes.h مراجعه کنید) بر ساختن یک CFG تمرکز می‌کنند، نه بازنویسی آن.

تحلیل سلسله مراتب طبقاتی

ART در Android 8.0 از Class Hierarchy Analysis (CHA) استفاده می‌کند، یک بهینه‌سازی کامپایلر که تماس‌های مجازی را به تماس‌های مستقیم بر اساس اطلاعات تولید شده توسط تجزیه و تحلیل سلسله مراتب کلاس‌ها غیر مجازی می‌کند. تماس های مجازی گران هستند، زیرا آنها حول یک جستجوی vtable پیاده سازی می شوند و چندین بار وابسته را می گیرند. همچنین تماس های مجازی نمی توانند به صورت خطی باشند.

در اینجا خلاصه ای از پیشرفت های مرتبط آورده شده است:

  • به روز رسانی وضعیت روش یک پیاده سازی پویا - در پایان زمان پیوند کلاس، زمانی که vtable پر شده است، ART یک مقایسه ورودی به ورودی با vtable کلاس super انجام می دهد.
  • بهینه سازی کامپایلر - کامپایلر از اطلاعات تک پیاده سازی یک روش بهره می برد. اگر متد A.foo دارای مجموعه پرچم تک پیاده‌سازی باشد، کامپایلر تماس مجازی را به یک تماس مستقیم غیر مجازی می‌کند و در نتیجه تلاش می‌کند تا تماس مستقیم را درون خطی کند.
  • عدم اعتبار کد کامپایل شده - همچنین در پایان زمان پیوند کلاس وقتی اطلاعات یک پیاده سازی به روز می شود، اگر متد A.foo که قبلاً یک پیاده سازی داشت اما وضعیت اکنون باطل شده است، همه کد کامپایل می شوند که به فرض آن متد A بستگی دارد. foo یک پیاده‌سازی نیاز دارد تا کد کامپایل‌شده‌اش باطل شود.
  • عدم بهینه سازی - برای کدهای کامپایل شده زنده که روی پشته است، بهینه سازی غیربهینه آغاز می شود تا کد کامپایل شده نامعتبر را به حالت مفسر وادار کند تا صحت را تضمین کند. مکانیزم جدیدی از بهینه سازی که ترکیبی از بهینه سازی همزمان و ناهمزمان است استفاده خواهد شد.

کش های درون خطی در فایل های .oat

ART اکنون از کش های درون خطی استفاده می کند و سایت های تماسی را که اطلاعات کافی برای آنها وجود دارد بهینه می کند. ویژگی کش داخلی اطلاعات زمان اجرا اضافی را در پروفایل ها ثبت می کند و از آن برای افزودن بهینه سازی های پویا به کامپایل قبل از زمان استفاده می کند.

Dexlayout

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

از آنجایی که اطلاعات نمایه در حال حاضر تنها پس از اجرای برنامه‌ها در دسترس است، dexlayout در کامپایل روی دستگاه dex2oat در طول تعمیر و نگهداری بی‌حرکت یکپارچه شده است.

حذف حافظه پنهان Dex

تا آندروید 7.0، شی DexCache دارای چهار آرایه بزرگ بود که متناسب با تعداد عناصر خاص در DexFile بود، یعنی:

  • رشته ها (یک مرجع در هر DexFile::StringId)،
  • انواع (یک مرجع برای هر DexFile::TypeId)،
  • متدها (یک نشانگر بومی برای هر DexFile::MethodId)،
  • فیلدها (یک نشانگر بومی برای هر DexFile::FieldId).

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

عملکرد مترجم

عملکرد مترجم در نسخه اندروید 7.0 با معرفی "mterp" - مفسری که دارای مکانیزم اصلی واکشی/رمزگشایی/تفسیر نوشته شده به زبان اسمبلی است، به طور قابل توجهی بهبود یافت. Mterp از مفسر سریع Dalvik مدل شده است و از arm, arm64, x86, x86_64, mips و mips64 پشتیبانی می کند. برای کد محاسباتی، mterp Art تقریباً با مفسر سریع Dalvik قابل مقایسه است. با این حال، در برخی شرایط می تواند به طور قابل توجهی - و حتی به طور چشمگیری - کندتر باشد:

  1. فراخوانی عملکرد
  2. دستکاری رشته، و سایر کاربران سنگین روش‌هایی که در Dalvik به عنوان ذاتی شناخته شده‌اند.
  3. استفاده از حافظه پشته بالاتر.

اندروید 8.0 این مشکلات را برطرف می کند.

خطی تر

از آندروید 6.0، ART می‌تواند هر تماسی را در همان فایل‌های dex وارد کند، اما فقط می‌تواند روش‌های برگ را از فایل‌های dex مختلف درون‌نویسی کند. دو دلیل برای این محدودیت وجود داشت:

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

برای رفع این محدودیت ها، Android 8.0:

  1. دسترسی حافظه پنهان Dex را از کد کامپایل شده حذف می کند (همچنین به بخش "حذف کش Dex" مراجعه کنید)
  2. رمزگذاری نقشه پشته را گسترش می دهد.

بهبودهای همگام سازی

تیم ART مسیرهای کد MonitorEnter/MonitorExit را تنظیم کرد و اتکای ما به موانع حافظه سنتی در ARMv8 را کاهش داد و در صورت امکان آن‌ها را با دستورالعمل‌های جدیدتر (دریافت/ انتشار) جایگزین کرد.

روشهای بومی سریعتر

تماس‌های بومی سریع‌تر به رابط بومی جاوا (JNI) با استفاده از حاشیه‌نویسی‌های @FastNative و @CriticalNative در دسترس هستند. این بهینه‌سازی‌های داخلی زمان اجرا ART انتقال JNI را سرعت می‌بخشد و جایگزین نماد !bang JNI منسوخ شده می‌شود. حاشیه نویسی ها هیچ تاثیری بر روش های غیر بومی ندارند و فقط برای کد زبان جاوا پلتفرم در bootclasspath در دسترس هستند (بدون به روز رسانی فروشگاه Play).

حاشیه نویسی @FastNative از روش های غیر استاتیک پشتیبانی می کند. اگر یک متد به عنوان پارامتر یا مقدار بازگشتی به یک jobject دسترسی دارد، از این استفاده کنید.

حاشیه نویسی @CriticalNative راه سریع تری را برای اجرای روش های بومی با محدودیت های زیر ارائه می دهد:

  • متدها باید ثابت باشند—هیچ شی برای پارامترها، مقادیر برگردانده یا this ضمنی وجود ندارد.
  • فقط انواع اولیه به روش بومی منتقل می شوند.
  • متد بومی از پارامترهای JNIEnv و jclass در تعریف تابع خود استفاده نمی کند.
  • روش باید به جای اتکا به پیوند پویا JNI در RegisterNatives ثبت شود.

@FastNative می تواند عملکرد روش بومی را تا 3 برابر و @CriticalNative تا 5 برابر بهبود بخشد. برای مثال، یک انتقال JNI که در دستگاه Nexus 6P اندازه‌گیری می‌شود:

فراخوانی رابط بومی جاوا (JNI). زمان اجرا (بر حسب نانوثانیه)
JNI منظم 115
!bang JNI 60
@FastNative 35
@CriticalNative 25