تحسينات أندرويد 8.0 آرت

تم تحسين وقت تشغيل Android (ART) بشكل ملحوظ في إصدار Android 8.0. تلخص القائمة أدناه التحسينات التي يمكن أن تتوقعها الشركات المصنعة للأجهزة في ART.

جامع القمامة المضغوط المتزامن

كما تم الإعلان عنه في Google I/O، يتميز ART بأداة تجميع البيانات المهملة المضغوطة المتزامنة (GC) الجديدة في Android 8.0. يقوم هذا المجمع بضغط الكومة في كل مرة يتم فيها تشغيل GC وأثناء تشغيل التطبيق، مع توقف قصير واحد فقط لمعالجة جذور الخيط. وهنا فوائده:

  • يقوم GC دائمًا بضغط الكومة: أحجام كومة أصغر بنسبة 32% في المتوسط ​​مقارنة بنظام Android 7.0.
  • يتيح الضغط تخصيص كائن مؤشر الترابط المحلي: عمليات التخصيص أسرع بنسبة 70% من Android 7.0.
  • يوفر أوقات إيقاف مؤقت أقل بنسبة 85% لمعيار H2 مقارنة بنظام Android 7.0 GC.
  • لم تعد أوقات الإيقاف المؤقت تتناسب مع حجم الكومة؛ يجب أن تكون التطبيقات قادرة على استخدام أكوام كبيرة دون القلق بشأن النفايات.
  • تفاصيل تنفيذ GC - عوائق القراءة:
    • حواجز القراءة هي مقدار صغير من العمل المنجز لكل حقل كائن يتم قراءته.
    • تم تحسينها في المترجم، ولكنها قد تؤدي إلى إبطاء بعض حالات الاستخدام.

تحسينات الحلقة

يتم استخدام مجموعة واسعة من تحسينات الحلقة بواسطة ART في إصدار Android 8.0:

  • حدود التحقق من عمليات الإزالة
    • ثابت: ثبت أن النطاقات ضمن الحدود في وقت الترجمة
    • ديناميكي: تضمن اختبارات وقت التشغيل بقاء الحلقات ضمن الحدود (يتم حذفها بخلاف ذلك)
  • الاستقراء المتغير الحذف
    • إزالة الحث الميت
    • استبدل الاستقراء الذي يتم استخدامه فقط بعد الحلقة بتعبيرات مغلقة الشكل
  • إزالة الكود الميت داخل جسم الحلقة، وإزالة الحلقات الكاملة التي أصبحت ميتة
  • تخفيض القوة
  • تحويلات الحلقة: الانعكاس، التبادل، الانقسام، البسط، الوحدة النمطية، إلخ.
  • SIMDization (وتسمى أيضًا المتجهات)

يوجد مُحسِّن الحلقة في ممر التحسين الخاص به في مترجم ART. تتشابه معظم تحسينات الحلقة مع التحسينات والتبسيط في أي مكان آخر. تظهر التحديات مع بعض التحسينات التي تعيد كتابة CFG بطريقة معقدة أكثر من المعتاد، لأن معظم أدوات CFG المساعدة (انظر العقد.h) تركز على بناء CFG، وليس إعادة كتابته.

تحليل التسلسل الهرمي للفئة

يستخدم ART في Android 8.0 تحليل التسلسل الهرمي للفئة (CHA)، وهو عبارة عن تحسين للمترجم يعمل على تحويل المكالمات الافتراضية إلى مكالمات مباشرة بناءً على المعلومات التي تم إنشاؤها عن طريق تحليل التسلسلات الهرمية للفئة. تعد المكالمات الافتراضية باهظة الثمن نظرًا لأنه يتم تنفيذها حول بحث vtable، كما أنها تتطلب بعض الأحمال التابعة. كما لا يمكن تضمين المكالمات الافتراضية.

فيما يلي ملخص للتحسينات ذات الصلة:

  • تحديث حالة طريقة التنفيذ الفردي الديناميكي - في نهاية وقت ربط الفئة، عندما يتم ملء vtable، تجري ART مقارنة إدخال بإدخال مع vtable الخاص بالفئة الفائقة.
  • تحسين المترجم - سيستفيد المترجم من معلومات التنفيذ الفردي للطريقة. إذا كانت الطريقة A.foo تحتوي على مجموعة علامات تنفيذ فردي، فسيقوم المترجم بتحويل المكالمة الافتراضية إلى مكالمة مباشرة، وسيحاول أيضًا تضمين المكالمة المباشرة نتيجة لذلك.
  • إبطال التعليمات البرمجية المترجمة - أيضًا في نهاية وقت ربط الفصل الدراسي عندما يتم تحديث معلومات التنفيذ الفردي، إذا كانت الطريقة A.foo تحتوي سابقًا على تطبيق فردي ولكن تم إبطال هذه الحالة الآن، فإن جميع التعليمات البرمجية المترجمة تعتمد على افتراض أن الطريقة A. يحتاج foo إلى تنفيذ فردي لإبطال التعليمات البرمجية المترجمة الخاصة به.
  • إلغاء التحسين - بالنسبة للتعليمات البرمجية المترجمة المباشرة والموجودة على المكدس، سيتم بدء عملية إلغاء التحسين لإجبار التعليمات البرمجية المترجمة غير الصالحة على وضع المترجم الفوري لضمان صحتها. سيتم استخدام آلية جديدة لإلغاء التحسين وهي عبارة عن مزيج من التحسين المتزامن وغير المتزامن.

ذاكرة التخزين المؤقت المضمنة في ملفات .oat

تستخدم ART الآن ذاكرة التخزين المؤقت المضمنة وتقوم بتحسين مواقع الاتصال التي توجد بها بيانات كافية. تسجل ميزة ذاكرة التخزين المؤقت المضمنة معلومات إضافية عن وقت التشغيل في ملفات التعريف وتستخدمها لإضافة تحسينات ديناميكية للتجميع المسبق.

Dexlayout

Dexlayout هي مكتبة تم تقديمها في Android 8.0 لتحليل ملفات dex وإعادة ترتيبها وفقًا للملف الشخصي. يهدف Dexlayout إلى استخدام معلومات ملفات تعريف وقت التشغيل لإعادة ترتيب أقسام ملف dex أثناء تجميع الصيانة الخاملة على الجهاز. من خلال تجميع أجزاء ملف dex التي غالبًا ما يتم الوصول إليها معًا، يمكن أن يكون للبرامج أنماط وصول أفضل للذاكرة من المنطقة المحسنة، مما يوفر ذاكرة الوصول العشوائي (RAM) ويقلل وقت بدء التشغيل.

نظرًا لأن معلومات الملف الشخصي متاحة حاليًا فقط بعد تشغيل التطبيقات، فقد تم دمج dexlayout في تجميع dex2oat على الجهاز أثناء الصيانة الخاملة.

إزالة ذاكرة التخزين المؤقت Dex

حتى Android 7.0، كان كائن DexCache يمتلك أربع مصفوفات كبيرة، تتناسب مع عدد عناصر معينة في DexFile، وهي:

  • سلاسل (مرجع واحد لكل DexFile::StringId)،
  • الأنواع (مرجع واحد لكل DexFile::TypeId)،
  • الأساليب (مؤشر أصلي واحد لكل DexFile::MethodId)،
  • الحقول (مؤشر أصلي واحد لكل DexFile::FieldId).

تم استخدام هذه المصفوفات للاسترجاع السريع للكائنات التي قمنا بحلها مسبقًا. في Android 8.0، تمت إزالة جميع المصفوفات باستثناء مصفوفة الأساليب.

أداء المترجم

تحسن أداء المترجم بشكل ملحوظ في إصدار Android 7.0 مع تقديم "mterp" - وهو مترجم يتميز بآلية جلب/فك تشفير/ترجمة أساسية مكتوبة بلغة التجميع. تم تصميم Mterp على غرار مترجم Dalvik السريع، ويدعم الذراع، وarm64، وx86، وx86_64، وmips، وmips64. بالنسبة للكود الحسابي، فإن mterp الخاص بـ Art يمكن مقارنته تقريبًا بالمترجم السريع الخاص بـ Dalvik. ومع ذلك، في بعض المواقف يمكن أن يكون أبطأ بشكل ملحوظ - وحتى بشكل كبير:

  1. استدعاء الأداء.
  2. التلاعب بالسلسلة، وغيرهم من المستخدمين الثقيلين للطرق المعترف بها على أنها جوهرية في Dalvik.
  3. استخدام أعلى للذاكرة المكدسة.

يعالج Android 8.0 هذه المشكلات.

المزيد من البطانة

منذ Android 6.0، يمكن لـ ART تضمين أي استدعاء داخل نفس ملفات dex، ولكن يمكنه فقط تضمين الأساليب الطرفية من ملفات dex المختلفة. وكان هناك سببان لهذا القيد:

  1. يتطلب التضمين من ملف dex آخر استخدام ذاكرة التخزين المؤقت لـ dex لملف dex الآخر، على عكس تضمين ملف dex نفسه، والذي يمكنه فقط إعادة استخدام ذاكرة التخزين المؤقت لـ dex للمتصل. هناك حاجة إلى ذاكرة التخزين المؤقت dex في التعليمات البرمجية المترجمة لبضعة تعليمات مثل الاستدعاءات الثابتة أو تحميل السلسلة أو تحميل الفئة.
  2. تقوم خرائط المكدس فقط بتشفير فهرس الطريقة داخل ملف dex الحالي.

لمعالجة هذه القيود، أندرويد 8.0:

  1. إزالة الوصول إلى ذاكرة التخزين المؤقت لـ dex من التعليمات البرمجية المترجمة (راجع أيضًا القسم "إزالة ذاكرة التخزين المؤقت لـ Dex")
  2. يمتد ترميز خريطة المكدس.

تحسينات المزامنة

قام فريق ART بضبط مسارات كود MonitorEnter/MonitorExit، وقلل من اعتمادنا على حواجز الذاكرة التقليدية في ARMv8، واستبدالها بتعليمات (اكتساب/تحرير) أحدث حيثما أمكن ذلك.

أساليب محلية أسرع

تتوفر مكالمات أصلية أسرع إلى Java Native Interface (JNI) باستخدام التعليقات التوضيحية @FastNative و @CriticalNative . تعمل تحسينات وقت تشغيل ART المضمنة هذه على تسريع انتقالات JNI واستبدال تدوين !bang JNI المهمل الآن. ليس للتعليقات التوضيحية أي تأثير على الطرق غير الأصلية وهي متاحة فقط لمنصة كود لغة Java على bootclasspath (لا توجد تحديثات لمتجر Play).

يدعم التعليق التوضيحي @FastNative الأساليب غير الثابتة. استخدم هذا إذا كانت إحدى الطرق تصل إلى jobject كمعلمة أو قيمة إرجاع.

يوفر التعليق @CriticalNative طريقة أسرع لتشغيل الأساليب الأصلية، مع القيود التالية:

  • يجب أن تكون الأساليب ثابتة - لا توجد كائنات للمعلمات أو القيم المرجعة أو this ضمنيًا.
  • يتم تمرير الأنواع البدائية فقط إلى الطريقة الأصلية.
  • لا تستخدم الطريقة الأصلية معلمات JNIEnv و jclass في تعريف وظيفتها.
  • يجب تسجيل الطريقة في RegisterNatives بدلاً من الاعتماد على ربط JNI الديناميكي.

بإمكان @FastNative تحسين أداء الطريقة الأصلية بما يصل إلى 3x، و @CriticalNative حتى 5x. على سبيل المثال، تم قياس انتقال JNI على جهاز Nexus 6P:

استدعاء واجهة جافا الأصلية (JNI). وقت التنفيذ (بالنانوثانية)
JNI العادية 115
!بانغ جيني 60
@FastNative 35
@CriticalNative 25