مطالعات موردی

چگونه مهندسان اینستاگرام دایرکت با استفاده از Jetpack Compose معماری رابط کاربری بومی هوش مصنوعی ساختند و هزینه توکن به ازای هر جلسه اپراتور را ۳۳٪ کاهش دادند

۱۱ دقیقه مطالعه
نمایه Pavlo Stavytskyi را مشاهده کنید مشاهده پروفایل ربکا فرانکس
Pavlo Stavytskyi و Rebecca Franks

این پست وبلاگ با همکاری تیم متا نوشته شده است

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

استفاده از Jetpack Compose برای دایرکت اینستاگرام فراتر از یک مدرن‌سازی رابط کاربری معمولی بود. این تیم یک کدبیس رابط کاربری بومی هوش مصنوعی ساخت که ۵۰٪ کوچکتر از پیاده‌سازی اصلی است، در حالی که به کاهش ۳۵٪ در زمان اجرای عامل هوش مصنوعی ، ۳۲٪ کاهش تبادلات مهندس-عامل و کاهش ۳۳٪ در هزینه توکن دست یافت. این تیم در همکاری نزدیک با گوگل، Jetpack Compose را با حفظ عملکرد بالا به کار گرفت. از طریق بهینه‌سازی‌های عملکرد، متا و گوگل Compose را نه تنها برای اینستاگرام، بلکه برای اکوسیستم گسترده‌تر توسعه‌دهندگان اندروید نیز بهبود بخشیدند.

مدرن‌سازی کدبیس در مقیاس وسیع

هوش مصنوعی به سرعت به یک همراه روزانه برای مهندسان در صنعت تبدیل شده است و اعمال آن بر روی یک پایگاه کد در مقیاس بزرگ مانند اینستاگرام، در حال حاضر دستاوردهای بهره‌وری واقعی را به همراه دارد. تیم اینستاگرام دایرکت هدف بلندپروازانه‌تری را تعیین کرد. این تیم به جای اینکه صرفاً ابزارهای هوش مصنوعی را به کد موجود معطوف کند، پایگاه کد و معماری آن را به گونه‌ای طراحی کرد که از نظر طراحی بومی هوش مصنوعی باشد و تأثیر هوش مصنوعی را بسیار فراتر از آنچه که به تنهایی می‌تواند ارائه دهد، چند برابر کند.

تیم اینستاگرام دایرکت، Jetpack Compose را به عنوان یک جزء کلیدی برای ساخت معماری رابط کاربری بومی هوش مصنوعی انتخاب کرد. ماهیت اعلانی آن تضمین می‌کند که کد مختصر، قابل پیش‌بینی و از نظر ساختاری برای مدل‌های هوش مصنوعی آسان‌تر باشد، عوارض جانبی کمتری داشته باشد، حالت ضمنی کمتری داشته باشد و مرزهای مؤلفه‌ها واضح‌تر باشد.

مهاجرت به Jetpack Compose نیاز به برنامه‌ریزی دقیقی داشت. صدها میلیون نفر هر روز در اینستاگرام پیام ارسال می‌کنند، بنابراین این مهاجرت باید تدریجی، روان و بدون هیچ اختلالی در تجربه کاربری انجام می‌شد، در حالی که تیم در حال بازسازی پایه و اساس آن بود. برای نشان دادن مقیاس چالش: اجزای رابط کاربری می‌توانند در بیش از ۱۶۰ حالت مختلف رندر شوند و یک صفحه مکالمه به تنهایی بیش از ۲۰۰ نوع پیام مجزا را مدیریت می‌کند.

طراحی محصول ۱.png

هنگام مهاجرت یک پایگاه کد با این حجم به Compose، وسوسه‌انگیز است که راه آسان را انتخاب کنید و اجزای رابط کاربری Compose را در سلسله مراتب View موجود جاسازی کنید. به عنوان یک گام افزایشی در طول مهاجرت تدریجی، این کاملاً معتبر است. با این حال، در درازمدت، ادغام Compose در یک پایگاه کد مبتنی بر View چالش برانگیز است. ابزارهای هوش مصنوعی اغلب مسیر کمترین مقاومت را در پیش می‌گیرند. اگر کد رابط کاربری اعلانی و دستوری را با هم مخلوط کنید، هوش مصنوعی احتمالاً آنها را به اشتباه ترکیب می‌کند و باعث ایجاد اشکالات ظریف، بدهی فنی و رگرسیون عملکرد می‌شود.

ساخت یک معماری رابط کاربری بومی هوش مصنوعی

در مقیاس اینستاگرام، درجه‌ای از انتزاع معماری اجتناب‌ناپذیر است و این همان چیزی است که برنامه را در حین رشد، قابل نگهداری نگه می‌دارد. یک الگوی رایج را در نظر بگیرید که در آن هر نوع آیتم 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 در کد دستوری خوانده می‌شود و سپس درون یک لامبدا 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 را تشکیل می‌دهند، مجبور بودند با همتایان قدیمی خود همزیستی داشته باشند و هر دو به صورت موازی نگهداری شوند. گردش‌های کاری هوش مصنوعی با سرعت بخشیدن به فرآیند نوشتن حجم عظیمی از کد، به امکان‌پذیر شدن این مهاجرت موازی کمک کردند. این رویکرد همان چیزی است که به تیم Direct اجازه داد مهاجرت را در زمان رکوردی انجام دهد، بدون اینکه بقیه تیم را مختل کند، که به ارائه ویژگی‌هایی ادامه می‌دادند که تجربه میلیون‌ها نفر را هر روز بهبود می‌بخشد.

چندین مهندس، عامل‌های هوش مصنوعی خود را در برابر یک پایگاه دانش مشترک از مهارت‌ها و قراردادهای قابل استفاده مجدد که در طول مهاجرت ساخته شده بودند، اجرا کردند. این کار باعث شد گردش‌های کاری و بهترین شیوه‌ها در سراسر تیم همگام‌سازی شوند، نه اینکه هر مهندس آنها را دوباره کشف کند. در هر سطح، تیم مهاجرت را در مراحل زیر انجام داد:

  • تمام کد Compose را با هوش مصنوعی بنویسید.
  • آن را اصلاح کنید، موارد حاشیه‌ای را مدیریت کنید و شکاف‌های عملکردی را پر کنید، تا زمانی که رابط کاربری در یک آزمایش عمومی برای کاربران واقعی عرضه شود.

تقسیم کار به دو مرحله در هر صفحه، به یک مهندس اجازه می‌دهد تا به سرعت در کل سطح حرکت کند، معماری و موارد پیچیده را از قبل حل و فصل کند. با انجام این کار مقدماتی، دیگران می‌توانند بدون توقف برای تصمیم‌گیری‌های فنی، بر آماده‌سازی رابط کاربری برای تولید تمرکز کنند و مهاجرت کلی را سریع نگه دارند.

نتایج مهاجرت، این رویکرد را تأیید کرد. برای سطوح دایرکت اینستاگرام منتقل‌شده، Jetpack Compose به تیم اجازه داد تا کل کد رابط کاربری را تا ۵۰٪ کاهش دهد . کد کمتر برای تولید توسط هوش مصنوعی با خروجی با کیفیت بالاتر و هزینه توکن کمتر برای هر کار مرتبط است.

نقل قول-پاولو-جدید.jpg

یک تحلیل داده‌های داخلی از کدبیس اندروید برای اینستاگرام دایرکت، جلسات عامل هوش مصنوعی را که روی رابط کاربری Compose کار می‌کردند با همان وظایف با استفاده از Android Views مقایسه کرد. افزایش بهره‌وری در دو بُعد مشخص بود:

  • به ازای هر کاراکتر کد ارسالی: Compose به ۳۲٪ تبادل مهندس-عامل کمتر و ۳۵٪ زمان اجرای عامل (زمان سپری شده از زمانی که یک عامل شروع به کار بر روی درخواست یک مهندس می‌کند تا زمانی که پاسخ را برمی‌گرداند) نیاز داشت.
  • به ازای هر جلسه اپراتور: هزینه کلی توکن با Compose در مقایسه با Views، ۳۳ درصد کاهش یافت .

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

داده‌ها همچنین تفاوت مداومی را در نحوه مدیریت کدهای پیچیده یا شکننده توسط دو چارچوب نشان دادند. متا این موضوع را با استفاده از امتیاز ریسک تغییرات کد پیگیری می‌کند، که کیفیت کلی کد و احتمال ایجاد حوادث تولیدی توسط یک تغییر را ارزیابی می‌کند. این تجزیه و تحلیل، کارایی منابع یک عامل را با استفاده از ترکیبی از مصرف توکن، زمان اجرای عامل و تعاملات مهندس با عامل اندازه‌گیری کرد. با افزایش امتیاز ریسک فایل‌ها، جلسات عامل هوش مصنوعی به طور طبیعی از نظر منابع کارایی کمتری پیدا می‌کنند.

وقتی امتیاز ریسک انباشته یک فایل دو برابر می‌شود ، رابط کاربری پیاده‌سازی شده با Android Views، بهره‌وری منابع عامل را 30٪ (به ازای هر کاراکتر فرود آمده) کاهش می‌دهد . در شرایط مشابه، کاهش توسط Jetpack Compose UI تنها 9٪ است.

از طریق همکاری بین گوگل و متا، تیم اینستاگرام دایرکت دیدگاه تازه‌ای به پذیرش Compose ارائه داد - با رویکردی از دریچه آمادگی هوش مصنوعی کدبیس، نه فقط بازنویسی رابط کاربری. این کار قدرت Compose را در خدمت به عنوان پایه‌ای برای ساخت کدبیس‌ها و معماری‌های مبتنی بر هوش مصنوعی، به ویژه هنگامی که در مقیاس برنامه‌هایی مانند اینستاگرام اعمال می‌شود، آشکار کرد.

بهینه‌سازی عملکرد

دایرکت اینستاگرام یکی از بخش‌های جدایی‌ناپذیر این اپلیکیشن است و مردم انتظار دارند که همیشه سریع و پاسخگو باشد. استفاده از Jetpack Compose عملاً به معنای بازنویسی اساسی رابط کاربری بود و هدف اصلی، حفظ تجربه کاربری با کیفیت بالا و بدون هیچ گونه افت و خیزی بود.

سال‌ها تکرار، پیاده‌سازی مبتنی بر نمای قدیمی در اینستاگرام را به سطح عملکرد فوق‌العاده بالایی رسانده بود و تیم باید ضمن انتقال به یک چارچوب رابط کاربری کاملاً جدید، به همان استاندارد نیز دست می‌یافت.

اینستاگرام صدها، اگر نگوییم هزاران، معیار عملکرد را اندازه‌گیری می‌کند. برای پذیرش Compose، سه مورد زیر از همه مهم‌تر بودند:

  • زمان تعامل - مدت زمان بین باز کردن صفحه نمایش تا امکان استفاده از آن.
  • زمان بارگذاری کامل - مدت زمان بین باز شدن صفحه تا بارگذاری کامل تمام محتوا (یعنی تصاویر).
  • عملکرد اسکرول - صفحه نمایش چقدر روان اسکرول می‌شود، بدون اینکه فریمی از دست برود.

این معیارها در زمان اجرا در محیط تولید ردیابی می‌شوند و امکان اجرای تست‌های A/B برای مقایسه رابط کاربری Compose منتقل‌شده با رابط کاربری قدیمی و ارزیابی تأثیر عملکرد این تلاش را فراهم می‌کنند.

یک روش رایج برای نزدیک شدن به چنین مهاجرتی، شروع کوچک، جابجایی روی تعداد انگشت‌شماری از اجزای رابط کاربری، جمع‌آوری داده‌ها و مطالعه نحوه رفتار آنهاست. اگرچه مفید است، اما این نتایج اولیه فقط یک تصویر ناقص را ترسیم می‌کنند و منفی‌های کاذبی را در برابر پذیرش Compose ارائه می‌دهند زیرا:

  • نماینده نیست - یک کامپوننت رابط کاربری منتقل شده می‌تواند داده‌های مفیدی در مورد عملکرد کلی آن در یک صفحه خاص ارائه دهد. با این حال، کامپوننت‌های مختلف به دلایلی که تعمیم‌پذیر نیستند، رفتار متفاوتی دارند، بنابراین شما همیشه نمی‌توانید از آن نتیجه بگیرید.
  • هزینه تعامل - یک قطعه کوچک Compose درون یک پایگاه کد بزرگ View، هزینه پل زدن غیرقابل پیش‌بینی بین دو سیستم را پرداخت می‌کند. این سربار، اندازه‌گیری را تحریف می‌کند، بنابراین نتایج اولیه در مقیاس کوچک، منعکس‌کننده مهاجرت کامل نیستند.

نتیجه این است که مهاجرت‌های کوچک، اگرچه مفید هستند، اما همیشه تأثیر کامل Compose را منعکس نمی‌کنند. هرچه سطح بیشتری از ابتدا تا انتها و بدون وقفه‌های پل‌زننده منتقل شود، تصویر از نظر عملکرد واضح‌تر و بهتر می‌شود.

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

نمودار ۱.png

وظیفه اصلی تیم، انتقال تدریجی چند صد آیتم لیست مجزا به Compose در معماری مبتنی بر RecyclerView موجود و اجرای آنها در گروه‌های کوچک و مستقل تحت تست‌های A/B در محیط عملیاتی بود - و همه این کارها بدون تغییر قابل مشاهده در تجربه پیام‌رسانی کاربر انجام می‌شد.

بزرگترین نقطه ضعف چنین تنظیماتی، وابستگی قابل توجه به سیستم نمایش قدیمی از طریق معماری اصلی RecyclerView ، حتی پس از انتقال کامل هر آیتم لیست به Compose است. به عنوان یک گام طبیعی بعدی، تیم تصمیم گرفت روی جایگزینی معماری اصلی مبتنی بر RecyclerView با جایگزین بومی Compose - LazyColumn - سرمایه‌گذاری کند.

این یعنی کامپوننت‌های رابط کاربری Compose باید از چارچوبی که در آن قرار دارند، جدا شوند و در عین حال همزمان با RecyclerView و LazyColumn سازگار باشند. به همان اندازه، قابلیت جابجایی بین این دو در زمان اجرا از طریق feature flagها برای فعال کردن تست A/B نیز مهم است.

نمودار ۲.png

در حالی که آیتم‌های جدید Compose به طور طبیعی با LazyColumn سازگار هستند و می‌توانند به یک درخت ترکیب بدون وقفه متصل شوند، یک رابط برنامه‌نویسی کاربردی (API) برای قرار دادن آنها در RecyclerView نیز ایجاد شد. این امر امکان اجرای تنظیمات LazyColumn را تحت یک تست A/B در کنار RecyclerView فراهم کرد - استفاده مجدد از همان آیتم‌های Compose و بهبود عملکرد، بدون ایجاد اختلال در بقیه مراحل ساخت تیم و اصلاح ویژگی‌ها.

مقیاس، پیچیدگی و حساسیت اینستاگرام حتی به کوچکترین رگرسیون‌ها، چالش منحصر به فردی را برای Jetpack Compose ایجاد کرد. پرداختن به این موارد نیازمند یک همکاری عملی و تکرارشونده بود. مهندسان گوگل و متا با همکاری نزدیک، معیارها را تجزیه و تحلیل کردند تا قابلیت‌های جدید Compose را مشخص و طراحی کنند تا معیارهای مبتنی بر View را برآورده یا از آنها فراتر رود. در نتیجه این همکاری، موارد زیر به Jetpack Compose اضافه شده است: ترکیب قابل مکث با LazyLayoutCacheWindows و ردیابی دید.

ترکیب قابل مکث با LazyLayoutCacheWindows

ترکیب قابل مکث (که به طور پیش‌فرض در Compose 1.10 فعال است) اجازه می‌دهد تا آیتم‌های گران‌قیمت lazy-list به صورت تدریجی در فریم‌ها ترکیب شوند تا از jank جلوگیری شود. وقتی این ترکیب با LazyLayoutCacheWindow (که در Compose 1.9 اضافه شد) جفت می‌شود، این ترکیب به طور قابل توجهی نرمی پیمایش را بهبود می‌بخشد. در آزمایش داخلی اخیر در Meta، ترکیب ترکیب قابل مکث با یک LazyLayoutCacheWindow تک‌نمایشی، افت فریم‌های بزرگ در دقیقه (LFDs/m3) را در مقایسه با Compose معمولی حدود ۱۳٪ کاهش داد. Cache Window به تنهایی آن را حدود ۸٪ در مقایسه با همان خط پایه کاهش داد. LFDs/m3 یک معیار داخلی است که Meta برای ردیابی لکنت‌های قابل توجه هنگام پیمایش استفاده می‌کند.

نقل قول-فابیو.jpg


استفاده از LazyLayoutCacheWindow در برنامه شما، آیتم‌های خارج از صفحه را در یک نوار پیکسلی در اطراف viewport آماده و نگه می‌دارد تا امکان جابجایی سریع (fast flings) فراهم شود. برای بهره‌مندی از 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 صرف نظر از دستگاه، 150dp از محتوای تشکیل شده را فراتر از لبه قابل مشاهده نگه می‌دارد.
  • Float : کسری از نمای دید. aheadFraction = 0.5f نیمی از صفحه را در جلو نگه می‌دارد، بنابراین مقدار مطلق با ارتفاع صفحه نمایش که از فاکتورهای فرم مختلف پشتیبانی می‌کند، تغییر می‌کند: بیشتر در تبلت یا تاشوی باز شده، و کمتر در یک تلفن جمع و جور.

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

ثبت ایمپرشن با onVisibilityChanged


  onVisibilityChanged   (اضافه شده در Compose 1.9.0) API یکی دیگر از نتایج کلیدی همکاری فنی بین گوگل و متا بود. این API به سطوح بزرگ Jetpack Compose روشی ثابت برای اطلاع از زمان قابل مشاهده بودن یک Composable روی صفحه می‌دهد و جایگزین پیاده‌سازی‌های سفارشی و دستی مورد استفاده در گذشته می‌شود. تنها در دایرکت اینستاگرام، این سیگنال‌های قابلیت مشاهده در صدها فایل برای پشتیبانی از معیارهای کیفیت محصول استفاده می‌شوند که به این بستگی دارند که آیا عناصر رابط کاربری واقعاً به افراد نشان داده شده‌اند یا خیر.

عملکرد استارتاپ

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

عملکرد اولیه رابط کاربری Compose در داخل خود دایرکت اینستاگرام با استفاده از Baseline Profiles بهینه‌سازی شده است، که مسیرهای کد فوری را در زمان نصب از قبل کامپایل می‌کند، بنابراین Compose از همان اولین اجرا به سرعت رندر می‌شود.

درس‌هایی از مهاجرت دایرکت اینستاگرام به جت‌پک کامپوز 

  • Jetpack Compose بازگشت سرمایه فوری دارد: برای بهره‌مندی از Compose نیازی به استفاده از گردش‌های کاری پیشرفته هوش مصنوعی ندارید. با کاهش حدود ۵۰ درصدی کد، به معنای کد کمتری برای نگهداری و کاهش سطح باگ‌ها است.
  • طراحی یک معماری بومی هوش مصنوعی منجر به پیروزی‌های قابل توجهی شد ، از جمله کاهش ۳۵ درصدی زمان اجرای عامل هوش مصنوعی، ۳۲ درصد کاهش تبادلات مهندس-عامل و کاهش ۳۳ درصدی هزینه توکن.
  • اگرچه APIهای interop و پشتیبانی زیادی برای ترکیب Views و Compose با هم وجود دارد، اما هدف، انتقال سطوح بزرگتر به کامپوننت‌های کوچک و مجزا است . این کار رابط کاربری را در یک سلسله مراتب ترکیب واحد و بدون وقفه نگه می‌دارد و بهترین بهینه‌سازی‌های عملکرد Compose-native را آزاد می‌کند.
  • ترکیب Pausable را با LazyLayoutCacheWindow جفت کنید : جفت کردن این دو با هم نتایج بهتری نسبت به پنجره‌های cache به تنهایی ارائه می‌دهد. با تنها پنجره cache، یک آیتم سنگین همچنان می‌تواند سعی کند در یک مرحله ترکیب شود و به طور بالقوه از بودجه فریم فراتر رود.
  • به Compose کمک کنید! متا با تیم Jetpack Compose همکاری کرده است تا بازخوردها و ایده‌های آنها را در Compose به کار گیرد. کار بر روی یک جعبه ابزار متن‌باز به این معنی است که وقتی اشکالات و بهبودهای عملکرد به صورت متمرکز انجام می‌شوند، همه ما سود می‌بریم. بنابراین، بازخورد خود را اعلام کنید!

استفاده از Jetpack Compose دستاوردهای قابل توجهی در توسعه مبتنی بر هوش مصنوعی ایجاد کرد و در عین حال مهندسی رابط کاربری روزمره در اینستاگرام را ساده‌تر نمود. رویکرد اعلانی، حجم انبوهی از اطلاعات تکراری را کاهش می‌دهد، استدلال در مورد وضعیت را آسان‌تر می‌کند و بهره‌وری کلی توسعه‌دهندگان را بهبود می‌بخشد. تیم مهندسی اینستاگرام مشتاقانه منتظر است تا Compose را به سطوح بیشتری در سراسر برنامه بیاورد و همکاری مداوم بین گوگل و متا برای بهبود بیشتر کاربران اینستاگرام و Jetpack Compose ادامه یابد.

اگر هنوز Compose را امتحان نکرده‌اید، اکنون با کمک هوش مصنوعی، مهاجرت به Jetpack Compose آسان‌تر از همیشه است.

تشکر و قدردانی. از میشال زیلینسکی و متیو دو از متا، و آندری شیکوف و جورج مونت از گوگل، به خاطر تلاش‌هایشان در بهبود عملکرد Compose از طریق همکاری بین متا و گوگل، سپاسگزاریم! همچنین از گری یه از متا برای کمک به آوردن Compose به دایرکت اینستاگرام، و از گوپال جونجا از متا برای حمایت از این تلاش از طریق علم داده، سپاسگزاریم!

نوشته شده توسط:
ادامه مطلب