في هذا المنشور ، سنتحدث عن وقت تشغيل Android. على وجه الخصوص ، سأحاول أن أوجز بإيجاز ولكن بإيجاز كيف تختلف ART و Dalvik ، وكيف تحسنت أدوات تطوير Android بمرور الوقت. من الواضح أن الموضوع ليس جديدًا ، لكنني آمل أن يكون مفيدًا لأولئك الذين بدأوا للتو في الخوض فيه. من يهتم - مرحبا بكم في القط.
آلة افتراضية
أولاً ، دعنا نرى كيف يختلف JVM عن DVM.
Java Virtual Machine هي آلة افتراضية قادرة على تنفيذ Java bytecode بغض النظر عن النظام الأساسي الأساسي. وهو يقوم على مبدأ "اكتب مرة واحدة ، تشغيل في أي مكان". يمكن تشغيل Java bytecode على أي جهاز قادر على دعم JVM.
يحول مترجم Java ملفات .java إلى ملفات فئة (bytecode). يتم تمرير الرمز الثانوي إلى JVM ، والذي يقوم بترجمته إلى رمز الجهاز للتنفيذ مباشرة على وحدة المعالجة المركزية.
ميزات JVM:
- له بنية مكدس: يتم استخدام المكدس كهيكل بيانات حيث يتم وضع الأساليب وتخزينها. وهو يعمل في مخطط LIFO أو "Last in - First Out" أو "Last in First Out".
- يمكن تشغيل ملفات الفصل فقط.
- يستخدم مترجم JIT.
إن Dalvik Virtual Machine (DVM) عبارة عن آلة Java افتراضية تم تطويرها وكتابتها بواسطة Dan Bornstein وآخرين كجزء من نظام Android للجوال.
يمكننا القول أن Dalvik هي بيئة لتنفيذ مكونات نظام التشغيل Android والتطبيقات المخصصة. يتم تشغيل كل عملية في مساحة العنوان المعزولة الخاصة بها. عندما يقوم المستخدم بتشغيل التطبيق (أو يقوم نظام التشغيل بتشغيل أحد مكوناته) ، فإن جوهر الجهاز الظاهري Dalvik (Zygote Dalvik VM) ينشئ عملية منفصلة ومحمية في الذاكرة المشتركة ، حيث يتم نشر الجهاز الظاهري مباشرةً كبيئة لإطلاق التطبيق. بمعنى آخر ، يبدو Android من الداخل كمجموعة من أجهزة Dalvik الافتراضية ، كل منها يشغل تطبيقًا.
ميزات DVM:
- يستخدم بنية قائمة على السجل: يعتمد هيكل البيانات حيث يتم وضع الأساليب على سجلات المعالج. نظرًا لغياب عمليات POP و PUSH ، يتم تنفيذ التعليمات الموجودة في جهاز افتراضي مسجل بشكل أسرع من التعليمات المماثلة في جهاز افتراضي مكدس.
- ينفذ رمز بايت للتنسيق الأصلي: يقوم Android dexer (سنتحدث عنه أدناه) بتحويل ملفات الفئة إلى تنسيق dex. ، المحسن للتنفيذ على Dalvik VM. على عكس ملف الفصل ، يحتوي ملف dex على عدة فئات في وقت واحد.
يمكنك قراءة المزيد عن هندسة DVM هنا .
Android Dexer
يعرف مطورو Android أن عملية تحويل Java bytecode إلى .dex bytecode لـ Android Runtime هي خطوة أساسية في إنشاء ملف APK. يعمل مترجم dex في الغالب تحت الغطاء في تطوير التطبيقات اليومية ، لكنه يؤثر بشكل مباشر على وقت إنشاء التطبيق وحجم ملف .dex وأداء وقت التشغيل.
كما ذكرنا سابقًا ، يحتوي ملف dex نفسه على عدة فئات في وقت واحد. يتم تضمين الأسطر المكررة والثوابت الأخرى المستخدمة عبر ملفات فئات متعددة فقط لتوفير مساحة. يتم أيضًا تحويل Java bytecode إلى مجموعة تعليمات بديلة يستخدمها DVM. عادةً ما يكون ملف dex غير المضغوط أصغر بنسبة قليلة من أرشيف Java المضغوط (JAR) الذي تم الحصول عليه من نفس ملفات .class.
في البداية ، تم تحويل ملفات الفئة إلى ملفات dex باستخدام مترجم DX المدمج. ولكن بدءًا من Android Studio 3.1 وما بعده ، أصبح D8 هو المترجم الافتراضي . بالمقارنة مع مترجم DX ، فإن D8 يجمع بشكل أسرع ويخرج ملفات dex أصغر ، مع توفير أداء أفضل للتطبيق في وقت التشغيل. يتم تصغير كود dex bytecode الذي تم الحصول عليه بهذه الطريقة باستخدام أداة ProGuard مفتوحة المصدر . نتيجة لذلك ، نحصل على نفس ملف dex ، لكن أصغر. ثم يتم استخدام ملف dex هذا لإنشاء apk وأخيراً للنشر على جهاز Android.
ولكن خلف D8 في عام 2018 جاء R8، وهو في الواقع نفس D8 ، فقط مع الإضافات.
عند العمل مع المكون الإضافي Android Studio 3.4 و Android Gradle 3.4.0 أو أعلى ، لم يعد يستخدم Proguard لتحسين الكود في وقت الترجمة. بدلاً من ذلك ، يعمل المكون الإضافي افتراضيًا مع R8 ، والذي يقوم بتقليص الشفرة والتحسين والتشويش نفسه. على الرغم من أن R8 لا يقدم سوى مجموعة فرعية من الوظائف التي يوفرها Proguard ، إلا أنه يسمح لك بإجراء تحويل Java bytecode إلى dex bytecode مرة واحدة ، مما يقلل من وقت الإنشاء.
R8 وتقليل الكود
عادةً ما تستخدم التطبيقات مكتبات الطرف الثالث مثل Jetpack و Gson و Google Play Services. عندما نستخدم إحدى هذه المكتبات ، غالبًا ما يستخدم التطبيق جزءًا صغيرًا فقط من كل مكتبة فردية. بدون تقلص الكود ، يتم تخزين كل أكواد المكتبة في التطبيق الخاص بك.
يحدث أن يستخدم المطورون تعليمات برمجية مطولة لتحسين إمكانية قراءة التطبيق وإمكانية صيانته. على سبيل المثال ، يمكن استخدام أسماء المتغيرات ذات المعنى ونمط التصميم لمساعدة الآخرين على فهم الكود بسهولة أكبر. لكن القوالب تميل إلى أن تؤدي إلى كود أكثر من اللازم.
هذا هو المكان الذي يأتي فيه R8 لإنقاذ. يسمح لك بتقليل حجم التطبيق بشكل كبير ، وتحسين حجم حتى الشفرة المستخدمة بالفعل من قبل التطبيق.
كمثال ، فيما يلي الأرقام الواردة من تقرير Shrinking Your App with R8 ، الذي تم تقديمه في مؤتمر Android Dev Summit '19:
وهذه هي الطريقة التي بدت بها مقارنة فعالية R8 في مرحلة الإصدار التجريبي (مأخوذة من المصدر مدونة مطوري Android ):
يمكن العثور على مزيد من التفاصيل في وثائق المكتب ، و تقرير .
ART مقابل DVM في Android
تم تصميم DVM خصيصًا للأجهزة المحمولة واستخدم
كآلة افتراضية لتشغيل تطبيقات Android حتى Android 4.4 Kitkat.
بدءًا من هذا الإصدار ، تم تقديم ART كوقت تشغيل ، وفي Android 5.0 (Lollipop) حل ART محل Dalvik تمامًا.
يتمثل الاختلاف الرئيسي الواضح بين ART و DVM في أن ART يستخدم تجميع AOT ، بينما يستخدم DVM تجميع JIT. منذ وقت ليس ببعيد ، بدأت ART في استخدام مزيج من AOT و JIT. دعونا نلقي نظرة فاحصة على هذا.
DVM
- يستخدم تجميع JIT: عندما يبدأ التطبيق ،
- يتم تجميع جزء من الكود المطلوب لتشغيل التطبيق. يتم تجميع باقي الكود ديناميكيًا. يؤدي هذا إلى إبطاء بدء تشغيل التطبيقات وتشغيلها ، ولكنه يقلل من وقت التثبيت.
- , .
- , DVM, , , ART.
- , CPU.
- Dalvik “” 4.4.
ART
- AOT , . , .
- , .
- AOT , DVM.
- , - .
- تحسين جمع القمامة أو جمع القمامة. عند استخدام Dalvik ، كان على جامعي القمامة القيام بتمريرين كومة ، مما أدى إلى ضعف تجربة المستخدم. في حالة ART ، لا يوجد مثل هذا الموقف: فهو ينظف الكومة مرة واحدة لتقوية الذاكرة.
ومخطط صغير لـ Dalvik vs ART:
JIT + AOT في الفن
يتضمن Android Runtime (ART) منذ Android 7 مترجم JIT مع ملف تعريف الكود. يكمل مترجم JIT مترجم AOT ويحسن أداء وقت التشغيل ويوفر مساحة على القرص ويسرع تحديثات التطبيق والنظام.
يحدث هذا بالطريقة التالية:
بدلاً من تشغيل تجميع AOT لكل تطبيق أثناء مرحلة التثبيت ، يقوم بتشغيل التطبيق تحت سيطرة جهاز افتراضي باستخدام مترجم JIT (تقريبًا كما هو الحال في Android <5.0) ، ولكنه يتتبع أي منها يتم تنفيذ أقسام كود التطبيق في أغلب الأحيان. يتم استخدام هذه المعلومات بعد ذلك لتجميع AOT لأقسام الكود هذه. يتم تنفيذ العملية الأخيرة فقط عندما يكون الهاتف الذكي غير نشط أثناء الشحن.
بعبارات بسيطة ، تعمل الآن طريقتان مختلفتان تمامًا معًا ، مما يعطي مزاياها:
- تجميع أكثر كفاءة - عند تشغيل تطبيق ما في الوقت الفعلي ، يكون للمجمع فرصة معرفة المزيد عن عمله أكثر من إجراء تحليل ثابت ، ونتيجة لذلك ، يتم تطبيق طرق تحسين أكثر ملاءمة لكل موقف ؛
- الحفاظ على ذاكرة الوصول العشوائي والذاكرة الدائمة - يكون رمز البايت أكثر إحكاما من رمز الجهاز ، وإذا قمت بإجراء تجميع AOT لأقسام معينة فقط من التطبيق ولم تقم بترجمة التطبيقات التي لا يستخدمها المستخدم ، يمكنك توفير مساحة ذاكرة NAND بشكل كبير ؛
- زيادة كبيرة في التثبيت وسرعة التمهيد الأولى بعد تحديث النظام - لا يوجد تجميع AOT ولا تأخير.
اقرأ المزيد عن تنفيذ مترجم JIT في ART هنا .
خاتمة
في هذه المقالة ، حاولت إلقاء نظرة على الاختلافات الرئيسية بين Dalvik و ART ، وإلقاء نظرة بشكل عام على كيفية قيام Android بتحسين أدوات التطوير الخاصة به بمرور الوقت.
لا يزال ART قيد التطوير مع إضافة ميزات جديدة لتحسين التجربة لكل من المستخدمين والمطورين.
إذا كان ذلك مفيدًا ، فأخبرني بذلك في التعليقات.