كيف أنشأ مهندسو Instagram Direct بنية واجهة مستخدم متوافقة مع الذكاء الاصطناعي باستخدام Jetpack Compose وخفّضوا تكلفة الرموز المميزة لكل جلسة مع وكيل بنسبة %33
مدّة القراءة: 11 دقيقة
تمت كتابة منشور المدوّنة هذا بالتعاون مع فريق Meta
الرسائل المباشرة على Instagram هي إحدى المساحات الأساسية على Instagram، وهي تتعامل مع مليارات رسائل المستخدمين كل يوم. على مدار سنوات من التكرار، تمكّن الفريق من تحقيق كل تحسين صغير ممكن من نظام Android View القديم. ومع ذلك، يؤدي الحفاظ على مساحة عرض قديمة محسّنة بشكل كبير وتوسيعها إلى تراكم كبير في الديون الفنية وتكاليف هندسية إضافية، خاصةً مع تزايد استخدام الفِرق لواجهات المستخدم التعريفية ومساعدي الترميز المستندين إلى الذكاء الاصطناعي.
لم يقتصر اعتماد Jetpack Compose في Instagram Direct على تحديث واجهة المستخدم بشكل عادي. أنشأ الفريق قاعدة رموز برمجية لواجهة مستخدم متوافقة مع الذكاء الاصطناعي أصغر بنسبة% 50 من عملية التنفيذ الأصلية، مع تحقيق انخفاض بنسبة% 35 في وقت تنفيذ وكيل الذكاء الاصطناعي، وانخفاض بنسبة% 32 في عدد عمليات تبادل المعلومات بين المهندس والوكيل، وانخفاض بنسبة% 33 في تكلفة الرموز المميزة. وبالتعاون الوثيق مع Google، اعتمد الفريق Jetpack Compose مع الحفاظ على مستوى عالٍ من الأداء. من خلال تحسينات الأداء، حسّنت Meta وGoogle أداة Compose ليس فقط لتطبيق Instagram، بل أيضًا لمنظومة Android المتكاملة الأوسع نطاقًا للمطوّرين.
تحديث قاعدة الرموز البرمجية على نطاق واسع
أصبح الذكاء الاصطناعي بسرعة رفيقًا يوميًا للمهندسين في المجال، وقد أدى تطبيقه على قاعدة رموز برمجية واسعة النطاق مثل Instagram إلى تحقيق مكاسب حقيقية في الإنتاجية. وضع فريق Instagram Direct هدفًا أكثر طموحًا. بدلاً من مجرد توجيه أدوات الذكاء الاصطناعي إلى الرمز الحالي، أعاد الفريق تصميم قاعدة الرموز البرمجية وبنيتها لتكون متوافقة مع الذكاء الاصطناعي، ما ضاعف تأثير الذكاء الاصطناعي إلى حدّ كبير مقارنةً بما يمكن أن تحقّقه عملية التعديل وحدها.
اختار فريق Instagram Direct استخدام Jetpack Compose كمكوّن أساسي لإنشاء بنية واجهة مستخدم متوافقة مع الذكاء الاصطناعي. تضمن طبيعته التعريفية أن يكون الرمز البرمجي موجزًا ويمكن توقّعه، كما يسهل على نماذج الذكاء الاصطناعي فهم بنيته، مع آثار جانبية أقل وحالة ضمنية أقل وحدود أوضح للمكوّنات.
تطلّبت عملية نقل البيانات إلى Jetpack Compose تخطيطًا دقيقًا. يرسل مئات الملايين من المستخدمين رسائل على Instagram كل يوم، لذا كان يجب أن تتم عملية نقل البيانات بشكل تدريجي وسلس وبدون أي انقطاع في التجربة أثناء إعادة تصميم الفريق للبنية الأساسية. لتوضيح حجم التحدي، يمكن عرض عناصر واجهة المستخدم الفردية في أكثر من 160 خيارًا مختلفًا للحالة، كما أنّ شاشة محادثة واحدة تتعامل مع أكثر من 200 نوع مختلف من الرسائل.
عند نقل قاعدة الرموز البرمجية بهذا الحجم إلى Compose، قد يكون من المغري اتّخاذ المسار الأسهل وتضمين مكوّنات واجهة مستخدم Compose داخل هيكلية طرق العرض الحالية. وهذا إجراء سليم تمامًا كخطوة متزايدة أثناء عملية نقل تدريجية. ومع ذلك، على المدى الطويل، يمثّل دمج Compose داخل قاعدة رموز تستند إلى View تحديًا. غالبًا ما تسلك أدوات الذكاء الاصطناعي المسار الأسهل. إذا جمعت بين الرمز التعريفي ورمز واجهة المستخدم الإلزامي، من المحتمل أن يدمجهما الذكاء الاصطناعي بشكل غير صحيح، ما يؤدي إلى حدوث أخطاء طفيفة ومشاكل فنية وتراجع في الأداء.
إنشاء بنية لواجهة مستخدم متوافقة مع الذكاء الاصطناعي
في تطبيق بحجم Instagram، لا يمكن تجنُّب درجة من التجريد المعماري، وهي ما يحافظ على إمكانية صيانة التطبيق مع نموه. لنفترض نمطًا شائعًا، حيث يتم تصميم كل نوع من أنواع العناصر RecyclerView كعنصر فرعي من فئة أساسية مخصّصة RecyclerViewItem تعرض عمليات ربط شائعة لدورة الحياة، مثل onBind.
المثال الأول
class ChatItem( val features: FeatureFlagProvider ) : RecyclerViewItem<ComposeViewHolder, ChatUiState> { // Imperative context: // AI could often take the path of least resistance and generate a mutable // state here, dispatched outside the ChatUiState. This class survives // re-bindings and is shared across multiple items, ultimately leading to // unexpected, hard-to-reproduce bugs. var isPinned: Boolean = false override fun onBind(holder: ComposeViewHolder, uiState: ChatUiState) { // Imperative context val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature") // Declarative context holder.composeView.setContent { // Blending imperative and declarative contexts if (isPinnedChatsEnabled) { Button(onClick = { isPinned = !isPinned }) { Text(if (isPinned) "Unpin" else "Pin") } } ... } } }
في المقتطف أعلاه، تظهر مشكلتان. أولاً، تتم قراءة العلامة isPinnedChatsEnabled في التعليمات البرمجية الإجرائية ثم يتم تسجيلها داخل تعبير lambda في Compose، وهو ربط دقيق بين النماذج. ثانيًا، isPinned هو حقل قابل للتغيير في العنصر نفسه وليس في ChatUiState، لذا يظل موجودًا عند إعادة ربط RecyclerView وإعادة استخدامه في الصفوف، ما يؤدي إلى حدوث أخطاء يصعب تكرارها.
حتى عندما يتم تنظيف الرمز من خلال منح العنصر وظيفة @Composable مخصصة، تبقى المشاكل نفسها.
المثال الثاني
class ChatItem( val features: FeatureFlagProvider ) : ComposeRecyclerViewItem<ChatUiState> { // Imperative context val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature") var isPinned: Boolean = false // Declarative context @Composable override fun Content(uiState: ChatUiState) { // Blending imperative and declarative contexts if (isPinnedChatsEnabled) { Button(onClick = { isPinned = !isPinned }) { Text(if (isPinned) "Unpin" else "Pin") } } ... } }
هذا مثال بسيط عن قصد، لكنّه يوضّح مشكلة أوسع نطاقًا، وهي أنّه كلما قلّت الحدود التي يتمّ منحها للذكاء الاصطناعي، انخفضت جودة الرمز الذي ينتجه بمرور الوقت. تساعد ضوابط الأمان والمهارات، ولكنّها لا تكفي وحدها، لأنّه عندما يواجه الذكاء الاصطناعي أي صعوبات، سيتجاوزها غالبًا لإزالة الحظر عن نفسه.
لجعل قاعدة الرموز البرمجية متوافقة مع الذكاء الاصطناعي، يجب اتّباع قاعدتَين عمليتَين:
- الحدّ من الاعتماد على السياق المخصّص: كلّما زادت المعرفة المخصّصة التي يحتاجها وكيل الذكاء الاصطناعي لإجراء تغيير صحيح، انخفضت جودة الناتج. كلّما كانت قاعدة الرموز البرمجية أقرب إلى أفضل الممارسات المعروفة، كانت نتائج الذكاء الاصطناعي أفضل.
- يجب أن تفرض قاعدة الرموز البرمجية المستندة إلى الذكاء الاصطناعي أولاً حدودها الخاصة. لا يمكن توسيع نطاق معالجة الثغرات في التصميم باستخدام مهارات الذكاء الاصطناعي، لأنّ كل مهارة يتم تحميلها في السياق تتطلّب رموزًا مميّزة ويمكن أن تؤدي إلى تدهور أداء الوكيل. بدلاً من ذلك، يجب أن تتحمّل البنية الأساسية هذا العبء. تتّبع وكلاء الذكاء الاصطناعي بشكل طبيعي المسار الأسهل، لذا يجب أن يؤدي التصميم إلى رموز برمجية صحيحة وعالية الجودة، مع صعوبة التعبير عن قرارات التصميم السيئة وارتفاع تكلفتها.
لا يزال من الممكن تمثيل عنصر القائمة من خلال تجريده الخاص، ولكن في هذه الحالة، يكون كل رمز Compose مضمّنًا في الدالة الإنشائية، وبالتالي لا يمكنه الوصول إلى أعضاء الفئة أو حالتها، ومصدر وسيطاته الوحيد هو الدالة الإنشائية. وهذا يجعلها مكافئة لوظيفة @Composable العادية، مع الالتزام بالبنية الحالية.
المثال الثالث
class ChatItem( val features: FeatureFlagProvider, val onPin: (Boolean) -> Unit, ) : ComposeItem<ChatUiState>( // Compose UI content = { uiState: ChatUiState -> val isPinnedChatsEnabled = features.isEnabled("pinned_chats_feature") if (isPinnedChatsEnabled) { Button(onClick = { onPin(!uiState.isPinned) }) { Text(if (uiState.isPinned) "Unpin" else "Pin") } } ... }, )
إنّ نقل قاعدة رموز برمجية بهذا الحجم هو مهمة ضخمة. لفترة طويلة، كان على مئات من عناصر واجهة المستخدم التي تشكّل معظم واجهة المستخدم المباشرة أن تتعايش مع نظيراتها القديمة، مع الحفاظ على كليهما بالتوازي. وقد ساعدت سير عمل الذكاء الاصطناعي في إتاحة عملية النقل المتوازية هذه من خلال تسريع عملية كتابة كميات هائلة من الرموز البرمجية. وقد مكّنت هذه الطريقة فريق Direct من إكمال عملية نقل البيانات في وقت قياسي، وكل ذلك بدون التأثير في بقية الفريق الذي واصل طرح الميزات التي تحسّن تجربة ملايين المستخدمين يوميًا.
استخدم العديد من المهندسين وكلاء الذكاء الاصطناعي الخاصين بهم استنادًا إلى قاعدة معرفة مشتركة تضم مهارات واتفاقيات قابلة لإعادة الاستخدام تم إنشاؤها أثناء عملية نقل البيانات. وقد ساعد ذلك في الحفاظ على تزامن عمليات سير العمل وأفضل الممارسات بين أعضاء الفريق، بدلاً من أن يعيد كل مهندس اكتشافها. ضمن كل مساحة عرض، نفّذ الفريق عملية نقل البيانات على النحو التالي:
- كتابة كل رموز Compose البرمجية باستخدام الذكاء الاصطناعي
- تم تحسينه ومعالجة الحالات الحدّية وسدّ الثغرات في الأداء إلى أن تم طرح واجهة المستخدم للمستخدمين الحقيقيين في اختبار علني.
يسمح تقسيم العمل إلى مرحلتين لكل شاشة لأحد المهندسين بالتنقل بسرعة في جميع الأسطح، وتسوية البنية وحالات الاستخدام الصعبة مسبقًا. وبعد إعداد هذه الأساسيات، يمكن للآخرين التركيز على جعل واجهة المستخدم جاهزة للإنتاج بدون التوقف لاتخاذ هذه القرارات الفنية بأنفسهم، ما يساهم في تسريع عملية النقل بشكل عام.
وقد أثبتت نتائج عملية نقل البيانات صحة هذا النهج. في ما يتعلّق بمساحات عرض Instagram Direct التي تم نقل بياناتها، أتاحت Jetpack Compose للفريق تقليل إجمالي مقدار رمز واجهة المستخدم بنسبة%50. كلّما قلّت كمية الرموز البرمجية التي يطلب من الذكاء الاصطناعي التوليدي إنشاؤها، زادت جودة المخرجات وانخفضت تكلفة الرموز المميزة لكل مهمة.
أجرينا تحليل بيانات داخليًا لقاعدة رموز Android البرمجية في Instagram Direct، وقارنّا بين جلسات الذكاء الاصطناعي الوكيل التي تعمل على واجهة مستخدم Compose والمهام نفسها باستخدام Android Views. كانت التحسينات في الكفاءة واضحة في بُعدَين:
- لكل حرف من الرمز البرمجي الذي تم تنفيذه: تم تسجيل انخفاض بنسبة% 32 في عدد المراسلات بين المهندسين والوكلاء وانخفاض بنسبة% 35 في وقت تنفيذ الوكيل (الوقت المنقضي منذ أن يبدأ الوكيل العمل على طلب أحد المهندسين إلى أن يعرض ردًا).
- لكل جلسة مع وكيل دعم: انخفضت التكلفة الإجمالية للرموز المميزة بنسبة% 33 باستخدام Compose مقارنةً بـ Views.
نقدّم تقارير عن كفاءة الإنتاجية وعدد الجلسات النموذجية لأنّها نتائج مفيدة بشكل مستقل. تقارن أرقام وقت التنفيذ والتبادل بين المهندس والوكيل استخدام الموارد لكل وحدة من المخرجات التي تمّت معالجتها، بينما يقارن رقم الرمز المميز التكلفة الإجمالية لجلسة وكيل نموذجية.
كشفت البيانات أيضًا عن اختلاف ثابت في طريقة تعامل الإطارَين مع الرموز المعقّدة أو الهشة. تتتبّع Meta ذلك باستخدام نتيجة المخاطر لتغييرات الرموز، والتي تقيّم جودة الرموز بشكل عام واحتمالية تسبّب التغيير في وقوع حوادث إنتاج. قاس التحليل كفاءة استخدام الموارد لدى الوكيل باستخدام مجموعة من استهلاك الرموز المميزة ووقت تنفيذ الوكيل وتفاعلات المهندس مع الوكيل. مع تراكم الملفات التي حصلت على تقييم أعلى للمخاطر، تصبح جلسات وكيل الذكاء الاصطناعي أقل كفاءة في استخدام الموارد بشكل طبيعي.
عندما يتضاعف معدّل المخاطر المتراكم لملف، فإنّ واجهة المستخدم التي تم تنفيذها باستخدام Android Views تقلّل من كفاءة موارد الوكيل بنسبة%30 (لكل حرف تم عرضه). في الظروف نفسها، يبلغ الانخفاض في حجم التطبيق باستخدام واجهة مستخدم Jetpack Compose%9 فقط.
من خلال شراكة بين Google وMeta، قدّم فريق Instagram Direct منظورًا جديدًا بشأن استخدام Compose، حيث تمّ التعامل معه من خلال إمكانية قراءة الذكاء الاصطناعي لقاعدة الرموز، وليس مجرد إعادة كتابة لواجهة المستخدم. وقد أظهرت هذه التجربة مدى فعالية Compose في توفير أساس لبناء قواعد رموز وبُنى تستند إلى الذكاء الاصطناعي، خاصةً عند تطبيقها على نطاق واسع في تطبيقات مثل Instagram.
تحسينات الأداء
تُعدّ رسائل Instagram المباشرة إحدى أهم مساحات العرض في التطبيق، ويتوقّع المستخدمون أن تكون سريعة ومتجاوبة في جميع الأوقات. كان استخدام Jetpack Compose يعني بشكل فعّال إعادة كتابة جزء كبير من واجهة المستخدم، وكان الهدف الأساسي هو الحفاظ على تجربة عالية الجودة بدون أي تراجع.
لقد أدّت سنوات من التكرار إلى رفع مستوى الأداء المطلوب من عملية التنفيذ القديمة المستندة إلى المشاهدات على Instagram إلى مستوى عالٍ للغاية، وكان على الفريق استيفاء هذا المعيار نفسه أثناء الانتقال إلى إطار عمل جديد تمامًا لواجهة المستخدم.
يقيس Instagram المئات، إن لم يكن الآلاف، من مقاييس الأداء. بالنسبة إلى استخدام ميزة "الكتابة بذكاء"، كانت النقاط الثلاث التالية هي الأهم:
- وقت التفاعل: هو مقدار الوقت بين فتح الشاشة وإمكانية استخدامها.
- وقت التحميل الكامل : هو مقدار الوقت المنقضي بين فتح الشاشة وتحميل كل المحتوى بالكامل (مثل الصور).
- أداء التمرير: مدى سلاسة تمرير الشاشة بدون فقدان أي إطارات
يتم تتبُّع هذه المقاييس في وقت التشغيل في مرحلة الإنتاج، ما يتيح إجراء اختبارات أ/ب لمقارنة واجهة مستخدم Compose التي تم نقلها بواجهة المستخدم القديمة وتقييم تأثير هذا الجهد على الأداء.
تتمثّل إحدى الطرق الشائعة للتعامل مع عملية نقل البيانات هذه في البدء على نطاق صغير، ونقل عدد قليل من عناصر واجهة المستخدم، وجمع البيانات، ودراسة طريقة عملها. على الرغم من أنّ هذه النتائج المبكرة مفيدة، إلا أنّها لا تقدّم سوى صورة جزئية، ما يؤدي إلى نتائج سلبية خاطئة بشأن اعتماد Compose، وذلك للأسباب التالية:
- غير تمثيلي: يمكن لأحد عناصر واجهة المستخدم التي تم نقلها تقديم بيانات مفيدة حول أدائه العام على شاشة معيّنة. ومع ذلك، تتصرف المكوّنات المختلفة بشكل مختلف لأسباب لا يمكن تعميمها، لذا لا يمكنك دائمًا استقراء النتائج منها.
- تكلفة التشغيل التفاعلي: يؤدي استخدام جزء صغير من Compose داخل قاعدة رموز برمجية كبيرة تستخدم View إلى تكلفة ربط غير متوقّعة بين النظامَين. يؤدي هذا العبء إلى تشويه القياس، لذا لا تعكس النتائج المبكرة الصغيرة الحجم الشكل الفعلي لعملية نقل البيانات الكاملة.
ونتيجةً لذلك، لا تعكس عمليات النقل الصغيرة، على الرغم من فائدتها، التأثير الكامل لـ Compose في بعض الأحيان. كلّما زادت مساحة السطح التي يتم نقلها من البداية إلى النهاية بدون انقطاع، أصبحت الصورة أوضح وأفضل من ناحية الأداء.
تم إنشاء الشاشات الأساسية في Instagram Direct استنادًا إلى قوائم طويلة من أنواع العناصر المتنوعة، وتم تنفيذها في الأصل باستخدام RecyclerView. تعتمد البنية على تجريدات مخصّصة لتوسيع النطاق، ولكنّها تظل مرتبطة بدورة حياة النظام المستند إلى العرض.
كانت المهمة الأساسية للفريق هي نقل تدريجي لعدة مئات من عناصر القائمة الفردية إلى Compose ضمن البنية الحالية المستندة إلى RecyclerView، وطرحها في مرحلة الإنتاج في مجموعات صغيرة مستقلة ضمن اختبارات A/B، وكل ذلك بدون إجراء تغييرات مرئية على تجربة المراسلة لدى المستخدم.
أكبر عيب في هذا الإعداد هو الاعتماد بشكل كبير على نظام View القديم من خلال بنية أساسية RecyclerView، حتى بعد نقل كل عنصر من عناصر القائمة بالكامل إلى Compose. وكخطوة طبيعية تالية، قرّر الفريق الاستثمار في استبدال البنية الأساسية المستندة إلى RecyclerView بالبديل المتوافق مع Compose، وهو LazyColumn.
وهذا يعني أنّه يجب تجريد مكوّنات Compose UI من إطار العمل الذي يتم تضمينها فيه مع الحفاظ على توافقها مع كل من RecyclerView وLazyColumn في الوقت نفسه. من المهم أيضًا إمكانية التبديل بين الاثنين في وقت التشغيل من خلال علامات الميزات، وذلك لتفعيل اختبار A/B.
في حين أنّ عناصر Compose الجديدة متوافقة بشكلٍ أصلي مع LazyColumn ويمكن إضافتها إلى شجرة التركيب بدون انقطاع، تم إنشاء واجهة برمجة تطبيقات للتشغيل التفاعلي لإضافتها إلى RecyclerView أيضًا. وقد أتاح ذلك طرح إعداد LazyColumn في اختبار A/B جنبًا إلى جنب مع RecyclerView، مع إعادة استخدام عناصر Compose نفسها وتحسين الأداء، بدون التأثير في بقية الفريق الذي يعمل على إنشاء الميزات وتحسينها.
شكّلت إمكانية التوسّع والتعقيد والحساسية التي تتميّز بها Instagram حتى لأصغر المشاكل تحديًا فريدًا بالنسبة إلى Jetpack Compose. وقد تطلّب حلّ هذه المشاكل شراكة متكرّرة وعملية. من خلال العمل معًا بشكل وثيق، حلّل مهندسو Google وMeta المقاييس لتحديد إمكانات Compose الجديدة وتصميمها من أجل استيفاء معايير الأداء المستندة إلى العرض أو تجاوزها. نتيجةً لهذه الشراكة، تبرز الإضافات التالية إلى Jetpack Compose: إمكانية إيقاف التركيب مؤقتًا باستخدام LazyLayoutCacheWindows وتتبُّع مستوى العرض.
تركيبة قابلة للإيقاف المؤقت باستخدام LazyLayoutCacheWindows
تتيح ميزة "التكوين القابل للإيقاف المؤقت" (المفعَّلة تلقائيًا في Compose 1.10) إنشاء عناصر القائمة الكبيرة بشكل تدريجي على مستوى الإطارات لمنع حدوث إيقاف مؤقت لعرض واجهة المستخدم. عند إقرانها مع LazyLayoutCacheWindow (التي تمت إضافتها في Compose 1.9)، يؤدي الجمع بينهما إلى تحسين سلاسة التمرير بشكل كبير. في اختبار داخلي أجرته Meta مؤخرًا، أدّى الجمع بين ميزة "التركيب القابل للإيقاف المؤقت" وLazyLayoutCacheWindow في إطار عرض واحد إلى خفض عدد اللقطات الكبيرة التي تم إسقاطها في الدقيقة (LFDs/m) بنسبة% 13 تقريبًا مقارنةً بإصدار Compose العادي. أدّى استخدام Cache Window وحده إلى خفض معدّل الخطأ بنسبة% 8 تقريبًا مقارنةً بالمعدّل الأساسي نفسه. عدد اللقطات المتأخرة/الدقيقة هو مقياس داخلي تستخدمه Meta لتتبُّع التقطّعات الملحوظة أثناء التمرير.
يؤدي استخدام LazyLayoutCacheWindow في تطبيقك إلى إعداد العناصر خارج الشاشة والاحتفاظ بها ضمن نطاق مستند إلى وحدات البكسل حول إطار العرض لتفعيل عمليات التحريك السريع. للاستفادة من LazyLayoutCacheWindows في تطبيقك، يمكنك استخدام أحدث إصدار من Compose 1.13.0-alpha03 وإعداده كما هو موضّح في المثال أدناه:
val cacheWindow = LazyLayoutCacheWindow(ahead = 150.dp, behind = 100.dp) // OR val cacheWindow = LazyLayoutCacheWindow(aheadFraction = 0.5f, behindFraction = 0.3f) LazyColumn(state = state, cacheWindow = cacheWindow) { ... }
هناك طريقتان لإعداد نافذة ذاكرة التخزين المؤقت. ويشير كلاهما إلى الشيء نفسه: مقدار المحتوى خارج الشاشة الذي يجب إبقاؤه منسقًا، ولكن بوحدات مختلفة.
- Dp: طول مطلق ثابت تحتفظ
ahead = 150.dpبـ 150 وحدة بكسل مستقلة الكثافة من المحتوى الذي تم إنشاؤه بعد الحافة المرئية بغض النظر عن الجهاز. - Float: جزء من إطار العرض تحتفظ
aheadFraction = 0.5fبنصف شاشة مؤلَّف مسبقًا، لذا يتناسب المقدار المطلق مع ارتفاع الشاشة، ما يتيح استخدام أشكال مختلفة للأجهزة: المزيد على جهاز لوحي أو جهاز قابل للطي غير مطوي، والمزيد على هاتف صغير.
عدّل فريق Instagram الكسور العشرية الخاصة بنافذة ذاكرة التخزين المؤقت خصيصًا لبنية المحتوى وأحجام العناصر في Direct. بما أنّ القيم المثالية تختلف حسب مَعلمات واجهة المستخدم المحدّدة، يتطلّب العثور على التوازن المناسب بعض التجارب.
تسجيل مرات الظهور باستخدام onVisibilityChanged
كانت واجهة برمجة التطبيقات onVisibilityChanged (التي تمت إضافتها في Compose 1.9.0) نتيجة رئيسية أخرى للشراكة الفنية بين Google وMeta. توفّر هذه المكتبة طريقة متّسقة للأسطح الكبيرة الحجم في Jetpack Compose لمعرفة متى يكون العنصر القابل للإنشاء مرئيًا على الشاشة، ما يحلّ محل عمليات التنفيذ المخصّصة التي تم إنشاؤها يدويًا والتي كانت تُستخدم في السابق. في Instagram Direct وحده، يتم استخدام إشارات مستوى العرض هذه في مئات الملفات لدعم مقاييس جودة المنتج التي تعتمد على ما إذا كانت عناصر واجهة المستخدم معروضة بالفعل للمستخدمين.
أداء بدء التشغيل
أدّى استخدام Jetpack Compose في Instagram Direct إلى تحسينات غير متوقّعة في الأداء على مستوى مساحات عرض أخرى في التطبيق. تتضمّن بيئة تشغيل Jetpack Compose تكلفة إعداد لا يتم دفعها إلا مرة واحدة، وبما أنّ المراسلة هي مساحة عرض ذات عدد زيارات كبير غالبًا ما يتم الوصول إليها في بداية جلسة المستخدم، فقد شهدت مساحات العرض الأخرى في Instagram التي تعتمد على Compose تحسينات ملحوظة في الأداء.
تم تحسين أداء بدء تشغيل واجهة مستخدم Compose داخل Instagram Direct من خلال استخدام ملفات Baseline Profiles، التي تعمل على تجميع مسارات الرموز البرمجية النشطة مسبقًا في وقت التثبيت، وبالتالي يتم عرض Compose بسرعة من أول عملية تشغيل.
الدروس المستفادة من عملية نقل بيانات Instagram Direct إلى Jetpack Compose
- تحقّق Jetpack Compose عائدًا فوريًا على الاستثمار: لست بحاجة إلى استخدام سير عمل متقدّم للذكاء الاصطناعي للاستفادة من Compose. وبفضل تقليل حجم الرمز البرمجي بنسبة% 50 تقريبًا، أصبح من السهل الحفاظ عليه، كما تم تقليل مساحة العرض للأخطاء.
- أدّى تصميم بنية أساسية متوافقة مع الذكاء الاصطناعي إلى تحقيق إنجازات كبيرة، بما في ذلك انخفاض بنسبة% 35 في وقت تنفيذ وكيل الذكاء الاصطناعي، وانخفاض بنسبة% 32 في عدد عمليات تبادل المعلومات بين المهندس والوكيل، وانخفاض بنسبة% 33 في تكلفة الرموز المميزة.
- على الرغم من توفّر الكثير من واجهات برمجة التطبيقات الخاصة بالتوافق وإمكانية الجمع بين Views وCompose، احرص على نقل المساحات الأكبر بدلاً من المكوّنات الصغيرة الفردية. يؤدي ذلك إلى إبقاء واجهة المستخدم ضمن تسلسل هرمي واحد وغير متقطّع، ويتيح جميع تحسينات الأداء الأفضل المتوافقة مع Compose.
- استخدام Pausable composition مع LazyLayoutCacheWindow: يؤدي استخدام هذين العنصرين معًا إلى تحقيق نتائج أفضل من استخدام نوافذ ذاكرة التخزين المؤقت وحدها. باستخدام نافذة ذاكرة التخزين المؤقت فقط، قد يحاول عنصر ثقيل إنشاء تركيبة في تمريرة واحدة، ما قد يؤدي إلى تجاوز ميزانية اللقطة.
- المساهمة في تطوير Compose تعاونت Meta مع فريق Jetpack Compose لتحويل ملاحظاتهم وأفكارهم إلى واقع في Compose. العمل على مجموعة أدوات مفتوحة المصدر يعني أنّنا نستفيد جميعًا عند إجراء تحسينات على الأداء وإصلاح الأخطاء بشكل مركزي. لذا، يُرجى مشاركة ملاحظاتك.
أتاح اعتماد Jetpack Compose تحقيق مكاسب كبيرة في التطوير المستند إلى الذكاء الاصطناعي مع تبسيط هندسة واجهة المستخدم اليومية في Instagram. يقلّل الأسلوب التصريحي من الرمز النمطي، ويسهّل فهم الحالة، ويحسّن إنتاجية المطوّرين بشكل عام. يتطلّع فريق الهندسة في Instagram إلى توفير Compose على المزيد من مساحات العرض في التطبيق، ومواصلة التعاون بين Google وMeta لتحقيق المزيد من التحسينات لمستخدمي Instagram وJetpack Compose على حد سواء.
إذا لم يسبق لك تجربة Compose، أصبح الانتقال إلى Jetpack Compose أسهل من أي وقت مضى بفضل ميزة "الاستعانة بالذكاء الاصطناعي".
الإقرارات: نشكر كلاً من "ميشال زيلينسكي" و"ماثيو دو" من Meta، و"أندريه شيكوف" و"جورج ماونت" من Google على جهودهم في تحسين أداء Compose من خلال التعاون بين Meta وGoogle. نشكر أيضًا "غاري يي" من Meta على المساعدة في إتاحة ميزة "الكتابة الذكية" في رسائل Instagram المباشرة، و"غوبال جونيا" من Meta على دعمه لهذا الجهد من خلال علم البيانات.
-
دراسات الحالةWhatsApp هي أكبر منصة مراسلة في العالم، ويستخدمها مليارات الأشخاص حول العالم. وهي أداة التواصل التلقائية للأشخاص في مناطق مختلفة، إذ تربط المستخدمين من خلال المراسلة الخاصة والموثوقة والآمنة.
Niharika Arora, Tracy Agyemang, Mayank Jain • مدّة القراءة: 8 دقائق -
دراسات الحالةمهمتنا في Tinder هي تعزيز التواصل الحقيقي وإلهام المستخدمين من خلال تسهيل اللقاءات وجعلها ممتعة لكل جيل جديد من العازبين.
Ajesh Pai, Ulises Uriel Verduzco Díaz , Tracy Agyemang • مدّة القراءة: 4 دقائق -
دراسات الحالةمع اعتماد غالبية تطبيقات Android لغة Kotlin كلغة أساسية، أصبحت kotlinx.coroutines معيارًا فعليًا للبرمجة غير المتزامنة. توفّر المكتبة طريقة منظَّمة ومصمَّمة جيدًا لإدارة عمليات نقل البيانات المتزامنة، وهي طريقة متوافقة مع لغة Kotlin.
Jonathan Starup, Andrei Shikov • مدّة القراءة: 7 دقائق
يمكنك تلقّي أحدث الإحصاءات حول تطوير تطبيقات Android في بريدك الوارد أسبوعيًا.