Instagram Direct के इंजीनियरों ने Jetpack Compose की मदद से, एआई-नेटिव यूज़र इंटरफ़ेस (यूआई) आर्किटेक्चर कैसे बनाया और हर एजेंट सेशन के लिए टोकन की लागत को 33% तक कैसे कम किया
पढ़ने में 11 मिनट लगेंगे
इस ब्लॉग पोस्ट को Meta की टीम के साथ मिलकर लिखा गया है
Instagram Direct, Instagram के मुख्य प्लैटफ़ॉर्म में से एक है. यह हर दिन अरबों मैसेज मैनेज करता है. टीम ने कई सालों तक, लेगसी Android View सिस्टम को ऑप्टिमाइज़ करने के लिए हर मुमकिन कोशिश की. हालांकि, लेगसी प्लैटफ़ॉर्म को बनाए रखने और उसे बेहतर बनाने से, तकनीकी समस्याएं और इंजीनियरिंग से जुड़ी लागत बढ़ जाती है. ऐसा खास तौर पर तब होता है, जब टीमें डिक्लेरेटिव यूज़र इंटरफ़ेस (यूआई) और एआई कोडिंग असिस्टेंट को ज़्यादा से ज़्यादा अपनाती हैं.
Instagram Direct के लिए, Jetpack Compose का इस्तेमाल करने से, यूज़र इंटरफ़ेस को बेहतर बनाने के साथ-साथ कई अन्य फ़ायदे भी मिले. टीम ने एआई-नेटिव यूज़र इंटरफ़ेस (यूआई) कोडबेस बनाया है. यह ओरिजनल कोडबेस से 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 को इंटिग्रेट करना एक चुनौती है. एआई टूल अक्सर सबसे आसान तरीका अपनाते हैं. डिक्लेरेटिव और इंपरेटिव यूज़र इंटरफ़ेस (यूआई) कोड को एक साथ इस्तेमाल करने पर, एआई उन्हें गलत तरीके से मिला सकता है. इससे मामूली गड़बड़ियां, तकनीकी समस्याएं, और परफ़ॉर्मेंस में गिरावट आ सकती है.
एआई-नेटिव यूज़र इंटरफ़ेस (यूआई) आर्किटेक्चर बनाना
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 फ़्लैग को ज़रूरी कोड में पढ़ा जाता है. इसके बाद, इसे 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%तक कम कर पाई. एआई को जनरेट करने के लिए कम कोड देने से, बेहतर क्वालिटी का आउटपुट मिलता है. साथ ही, हर टास्क के लिए टोकन की लागत कम होती है.
Instagram Direct के Android कोड बेस के इंटरनल डेटा विश्लेषण में, Compose यूज़र इंटरफ़ेस (यूआई) पर काम करने वाले एआई एजेंट सेशन की तुलना, Android व्यू का इस्तेमाल करके किए गए एक जैसे टास्क से की गई. परफ़ॉर्मेंस में सुधार, दो डाइमेंशन में साफ़ तौर पर दिख रहा था:
- लैंड किए गए कोड के हर वर्ण के लिए: ज़रूरी इंजीनियर-एजेंट के बीच होने वाली बातचीत में 32% की कमी और एजेंट के काम करने के समय में 35% की कमी(इंजीनियर के अनुरोध पर एजेंट के काम शुरू करने से लेकर जवाब मिलने तक का समय).
- हर एजेंट सेशन के लिए: Views की तुलना में, Compose की मदद से टोकन की कुल लागत में 33% की गिरावट आई है.
हम आउटपुट की क्षमता और सामान्य सेशन की संख्या, दोनों की रिपोर्ट करते हैं. ऐसा इसलिए, क्योंकि ये दोनों अलग-अलग काम के नतीजे हैं. इंजीनियर-एजेंट के बीच हुए इंटरैक्शन और टास्क पूरा होने में लगे समय के आंकड़ों से, लैंड किए गए आउटपुट की हर यूनिट के लिए संसाधन के इस्तेमाल की तुलना की जाती है. वहीं, टोकन के आंकड़े से, एजेंट के सामान्य सेशन की कुल लागत की तुलना की जाती है.
डेटा से यह भी पता चला कि दोनों फ़्रेमवर्क, जटिल या कमज़ोर कोड को अलग-अलग तरीके से हैंडल करते हैं. Meta, कोड में हुए बदलावों के जोखिम के स्कोर का इस्तेमाल करके इसे ट्रैक करता है. यह स्कोर, कोड की कुल क्वालिटी और बदलाव की वजह से प्रोडक्शन से जुड़ी समस्याएं होने की संभावना का आकलन करता है. इस विश्लेषण में, टोकन के इस्तेमाल, एजेंट के काम करने में लगने वाले समय, और इंजीनियर से एजेंट के इंटरैक्शन के कंपोज़िट का इस्तेमाल करके, एजेंट की संसाधन दक्षता को मेज़र किया गया. फ़ाइलों का रिस्क स्कोर बढ़ने पर, एआई एजेंट के सेशन अपने-आप कम संसाधन-कुशल हो जाते हैं.
जब किसी फ़ाइल का कुल जोखिम स्कोर दोगुना हो जाता है, तब Android Views के साथ लागू किया गया यूज़र इंटरफ़ेस (यूआई), एजेंट के संसाधन की क्षमता को 30%तक कम कर देता है (लैंड किए गए हर वर्ण के हिसाब से). इसी तरह की स्थितियों में, Jetpack Compose के यूज़र इंटरफ़ेस में सिर्फ़ 9% की कमी होती है
Google और Meta की साझेदारी के ज़रिए, Instagram Direct की टीम ने Compose को अपनाने के लिए एक नया नज़रिया पेश किया. इसमें, यूज़र इंटरफ़ेस (यूआई) को फिर से लिखने के बजाय, कोडबेस के एआई के साथ काम करने की क्षमता को ध्यान में रखा गया. इस काम से पता चला कि Compose, एआई की सुविधाओं वाले कोडबेस और आर्किटेक्चर बनाने के लिए एक मज़बूत प्लैटफ़ॉर्म है. खास तौर पर, जब इसे Instagram जैसे बड़े ऐप्लिकेशन के लिए इस्तेमाल किया जाता है.
परफ़ॉर्मेंस ऑप्टिमाइज़ेशन
Instagram Direct, ऐप्लिकेशन के सबसे ज़रूरी हिस्सों में से एक है. लोग चाहते हैं कि यह हमेशा तेज़ी से काम करे और रिस्पॉन्सिव हो. Jetpack Compose को अपनाने का मतलब था कि यूज़र इंटरफ़ेस (यूआई) को फिर से लिखना होगा. हमारा मुख्य लक्ष्य, बेहतरीन अनुभव को बनाए रखना और किसी भी तरह की गड़बड़ी से बचना था.
कई सालों से, Instagram पर व्यू पर आधारित लेगसी सिस्टम को बेहतर बनाया जा रहा था. इस वजह से, यह सिस्टम बहुत अच्छा परफ़ॉर्म कर रहा था. टीम को नए यूज़र इंटरफ़ेस (यूआई) फ़्रेमवर्क पर माइग्रेट करते समय, उसी स्टैंडर्ड को बनाए रखना था.
Instagram, सैकड़ों या हज़ारों परफ़ॉर्मेंस मेट्रिक को मेज़र करता है. Compose को अपनाने के लिए, ये तीन बातें सबसे ज़्यादा ज़रूरी थीं:
- इंटरैक्टिव में लगने वाला समय - स्क्रीन खोलने और उसका इस्तेमाल करने के बीच लगने वाला समय.
- पूरी तरह लोड होने में लगने वाला समय - स्क्रीन खुलने से लेकर, सभी कॉन्टेंट (जैसे कि इमेज) के पूरी तरह लोड होने में लगने वाला समय.
- स्क्रोल करने की परफ़ॉर्मेंस - स्क्रीन कितनी आसानी से स्क्रोल होती है. इसमें फ़्रेम नहीं छूटने चाहिए.
इन मेट्रिक को प्रोडक्शन में रनटाइम के दौरान ट्रैक किया जाता है. इससे, माइग्रेट किए गए Compose यूज़र इंटरफ़ेस (यूआई) की तुलना लेगसी यूज़र इंटरफ़ेस (यूआई) से करने वाले A/B टेस्ट चलाए जा सकते हैं. साथ ही, इस बदलाव से परफ़ॉर्मेंस पर पड़ने वाले असर का आकलन किया जा सकता है.
इस तरह के माइग्रेशन को पूरा करने का एक सामान्य तरीका यह है कि इसे छोटे लेवल पर शुरू किया जाए. इसके लिए, कुछ यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट को माइग्रेट करें, डेटा इकट्ठा करें, और देखें कि वे कैसे काम करते हैं. ये शुरुआती नतीजे मददगार तो हैं, लेकिन इनसे सिर्फ़ कुछ हद तक जानकारी मिलती है. साथ ही, इनसे कंपोज़ करने की सुविधा को अपनाने के बारे में गलत जानकारी मिलती है. इसकी वजह यह है कि:
- प्रतिनिधि नहीं है — माइग्रेट किया गया कोई यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट, किसी स्क्रीन पर अपनी परफ़ॉर्मेंस के बारे में काम का डेटा दे सकता है. हालांकि, अलग-अलग कॉम्पोनेंट अलग-अलग तरह से काम करते हैं. इसकी वजहें सामान्य नहीं होती हैं. इसलिए, इससे हमेशा अनुमान नहीं लगाया जा सकता.
- इंटरऑप की लागत — View के बड़े कोड बेस में मौजूद Compose का छोटा हिस्सा, दोनों सिस्टम के बीच ब्रिजिंग की लागत का अनुमान नहीं लगा पाता. इस वजह से, मेज़रमेंट में गड़बड़ी होती है. इसलिए, माइग्रेशन के शुरुआती दौर में मिले छोटे पैमाने के नतीजे, यह नहीं दिखाते कि पूरा माइग्रेशन कैसा होगा.
इसलिए, छोटे माइग्रेशन फ़ायदेमंद होने के बावजूद, Compose के पूरे असर को नहीं दिखाते. किसी प्लैटफ़ॉर्म के ज़्यादा से ज़्यादा हिस्से को बिना किसी रुकावट के पूरी तरह से माइग्रेट करने पर, परफ़ॉर्मेंस के हिसाब से बेहतर नतीजे मिलते हैं.
Instagram Direct की मुख्य स्क्रीन, अलग-अलग तरह के आइटम की लंबी सूचियों के हिसाब से बनाई गई हैं. इन्हें मूल रूप से RecyclerView की मदद से लागू किया गया था. आर्किटेक्चर, स्केलेबिलिटी के लिए कस्टम ऐब्स्ट्रैक्शन पर निर्भर करता है. हालांकि, यह व्यू-आधारित सिस्टम के लाइफ़साइकल से जुड़ा रहता है.
टीम का मुख्य काम, मौजूदा RecyclerView पर आधारित आर्किटेक्चर में, सूची के कई आइटम को धीरे-धीरे Compose में माइग्रेट करना था. साथ ही, उन्हें A/B टेस्ट के तहत छोटे-छोटे ग्रुप में प्रोडक्शन के लिए रोल आउट करना था. यह सब, उपयोगकर्ता के मैसेजिंग अनुभव में कोई बदलाव किए बिना किया गया.
इस तरह के सेटअप का सबसे बड़ा नुकसान यह है कि हर सूची आइटम को Compose पर पूरी तरह से माइग्रेट करने के बाद भी, यह मुख्य RecyclerView आर्किटेक्चर के ज़रिए लेगसी व्यू सिस्टम पर काफ़ी हद तक निर्भर रहता है. इसलिए, टीम ने RecyclerView पर आधारित कोर आर्किटेक्चर को Compose-native के विकल्प — LazyColumn से बदलने का फ़ैसला किया.
इसका मतलब है कि Compose यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट को उस फ़्रेमवर्क से अलग किया जाना चाहिए जिसमें वे शामिल हैं. हालांकि, वे एक ही समय में RecyclerView और LazyColumn, दोनों के साथ काम करते रहने चाहिए. A/B टेस्टिंग को चालू करने के लिए, फ़ीचर फ़्लैग की मदद से रनटाइम के दौरान दोनों के बीच स्विच करने की सुविधा भी उतनी ही ज़रूरी है.
Compose के नए आइटम, LazyColumn के साथ नेटिव तौर पर काम करते हैं. साथ ही, इन्हें कंपोज़िशन ट्री में बिना किसी रुकावट के प्लग किया जा सकता है. हालांकि, इंटरऑप एपीआई को RecyclerView में भी शामिल किया गया है. इसकी वजह से, RecyclerView के साथ-साथ LazyColumn को भी A/B टेस्ट के तहत रोल आउट किया जा सका. इसमें Compose के एक ही आइटम का फिर से इस्तेमाल किया गया और परफ़ॉर्मेंस को बेहतर बनाया गया. साथ ही, टीम की अन्य सुविधाओं को बनाने और उन्हें बेहतर बनाने में कोई रुकावट नहीं आई.
Instagram के बड़े पैमाने पर इस्तेमाल होने, जटिलता, और संवेदनशील डेटा को ध्यान में रखते हुए, Jetpack Compose के लिए एक खास चुनौती थी. इन समस्याओं को हल करने के लिए, बार-बार और मिलकर काम करना ज़रूरी था. Google और Meta के इंजीनियरों ने साथ मिलकर काम किया. उन्होंने मेट्रिक का विश्लेषण किया, ताकि व्यू-आधारित बेंचमार्क को पूरा करने या उससे बेहतर नतीजे पाने के लिए, नई Compose सुविधाएं तैयार की जा सकें. इस पार्टनरशिप के बाद, Jetpack Compose में ये सुविधाएं जोड़ी गई हैं: LazyLayoutCacheWindows की मदद से कंपोज़िशन को रोका जा सकता है और दिखने की स्थिति को ट्रैक किया जा सकता है.
LazyLayoutCacheWindows के साथ रोके जा सकने वाले कंपोज़िशन
रोके जा सकने वाले कंपोज़िशन (Compose 1.10 में डिफ़ॉल्ट रूप से चालू होता है) की मदद से, लेज़ी-लिस्ट के महंगे आइटम को फ़्रेम के हिसाब से कंपोज़ किया जा सकता है, ताकि जंक को रोका जा सके. LazyLayoutCacheWindow (Compose 1.9 में जोड़ा गया) के साथ इस्तेमाल करने पर, यह स्क्रोलिंग को काफ़ी हद तक बेहतर बनाता है. हाल ही में Meta में हुई इंटरनल टेस्टिंग में, Pausable कंपोज़िशन को एक व्यूपोर्ट LazyLayoutCacheWindow के साथ इस्तेमाल करने पर, वैनिला कंपोज़ की तुलना में हर मिनट होने वाले बड़े फ़्रेम ड्रॉप (एलएफ़डी/मिनट) में करीब 13% की कमी आई. सिर्फ़ कैश विंडो की वजह से, इसी बेसलाइन के मुकाबले इसमें करीब 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 डीपी का कॉन्टेंट रखता है. - फ़्लोट: व्यूपोर्ट का फ़्रैक्शन.
aheadFraction = 0.5fमें आधी स्क्रीन पर पहले से ही कॉन्टेंट मौजूद होता है. इसलिए, स्क्रीन की ऊंचाई के हिसाब से कॉन्टेंट का साइज़ बदलता रहता है. यह अलग-अलग साइज़ के डिवाइसों के साथ काम करता है: टैबलेट या फ़ोल्ड किए जा सकने वाले डिवाइस को अनफ़ोल्ड करने पर ज़्यादा कॉन्टेंट दिखता है, जबकि छोटे फ़ोन पर कम कॉन्टेंट दिखता है.
Instagram की टीम ने, Direct के कॉन्टेंट स्ट्रक्चर और आइटम साइज़ के लिए, कैश मेमोरी की विंडो के फ़्लोट फ़्रैक्शन को बेहतर बनाया है. यूज़र इंटरफ़ेस (यूआई) के पैरामीटर के हिसाब से, सबसे सही वैल्यू अलग-अलग होती हैं. इसलिए, सही बैलेंस पाने के लिए कुछ एक्सपेरिमेंट करने पड़ सकते हैं.
onVisibilityChanged की मदद से इंप्रेशन लॉग करना
onVisibilityChanged (Compose 1.9.0 में जोड़ा गया) एपीआई, Google और Meta के बीच हुई तकनीकी साझेदारी का एक और अहम नतीजा था. इससे Jetpack Compose की बड़ी-बड़ी सतहों को यह पता चलता है कि कोई कंपोज़ेबल, स्क्रीन पर कब दिखता है. यह सुविधा, पहले इस्तेमाल किए गए कस्टम और हैंड-रोल्ड इंप्लीमेंटेशन की जगह लेती है. सिर्फ़ Instagram Direct में, इन विज़िबिलिटी सिग्नल का इस्तेमाल सैकड़ों फ़ाइलों में किया जाता है. इससे प्रॉडक्ट की क्वालिटी से जुड़ी मेट्रिक को बेहतर बनाने में मदद मिलती है. ये मेट्रिक इस बात पर निर्भर करती हैं कि यूज़र इंटरफ़ेस (यूआई) के एलिमेंट लोगों को दिखाए गए थे या नहीं.
स्टार्टअप परफ़ॉर्मेंस
Instagram Direct के लिए Jetpack Compose का इस्तेमाल करने से, ऐप्लिकेशन के अन्य हिस्सों की परफ़ॉर्मेंस में भी सुधार हुआ. Jetpack Compose के रनटाइम में वार्मअप की लागत लगती है, जिसका भुगतान आपको सिर्फ़ एक बार करना होता है. मैसेजिंग, ज़्यादा ट्रैफ़िक वाला ऐसा प्लैटफ़ॉर्म है जिस पर उपयोगकर्ता सेशन की शुरुआत में अक्सर आते हैं. इसलिए, Instagram के अन्य प्लैटफ़ॉर्म की परफ़ॉर्मेंस में भी सुधार हुआ. ये प्लैटफ़ॉर्म, Compose पर निर्भर करते हैं.
Instagram Direct में Compose UI के स्टार्टअप परफ़ॉर्मेंस को ऑप्टिमाइज़ किया गया है. इसके लिए, बेसलाइन प्रोफ़ाइलें का इस्तेमाल किया गया है. ये प्रोफ़ाइलें, इंस्टॉल करने के समय ही हॉट कोड पाथ को पहले से कंपाइल कर देती हैं, ताकि Compose पहली बार लॉन्च होने पर ही तेज़ी से रेंडर हो जाए.
Instagram Direct को Jetpack Compose पर माइग्रेट करने से मिली सीख
- Jetpack Compose से तुरंत फ़ायदा मिलता है: Compose का फ़ायदा पाने के लिए, आपको एआई के ऐडवांस वर्कफ़्लो का इस्तेमाल करने की ज़रूरत नहीं है. कोड में करीब 50% की कमी होने का मतलब है कि अब कम कोड को मैनेज करना होगा. साथ ही, बग के लिए कम जगह होगी.
- एआई-नेटिव आर्किटेक्चर डिज़ाइन करने से, कई फ़ायदे मिले. जैसे, एआई एजेंट को टास्क पूरा करने में लगने वाले समय में 35% की कमी आई, इंजीनियर और एजेंट के बीच होने वाले इंटरैक्शन में 32% की कमी आई, और टोकन की लागत में 33% की कमी आई.
- हालांकि, इंटरऑप एपीआई के कई विकल्प उपलब्ध हैं. साथ ही, Views और Compose को एक साथ इस्तेमाल किया जा सकता है. हमारा सुझाव है कि अलग-अलग छोटे कॉम्पोनेंट के बजाय, बड़े कॉम्पोनेंट माइग्रेट करें. इससे यूज़र इंटरफ़ेस (यूआई) को एक ही कंपोज़िशन हाइरार्की में रखा जाता है. साथ ही, Compose की परफ़ॉर्मेंस को ऑप्टिमाइज़ करने की सभी बेहतरीन सुविधाएं अनलॉक हो जाती हैं.
- LazyLayoutCacheWindow के साथ Pausable कंपोज़िशन का इस्तेमाल करें: इन दोनों का एक साथ इस्तेमाल करने से, सिर्फ़ कैश विंडो के मुकाबले बेहतर नतीजे मिलते हैं. सिर्फ़ कैश मेमोरी वाली विंडो के साथ, कोई बड़ा आइटम अब भी एक ही पास में कंपोज़ करने की कोशिश कर सकता है. इससे फ़्रेम का बजट ज़्यादा हो सकता है.
- Compose के लिए योगदान दें! Meta ने Jetpack Compose टीम के साथ मिलकर काम किया है, ताकि Compose में उनके सुझाव और आइडिया को शामिल किया जा सके. ओपन-सोर्स टूलकिट पर काम करने का मतलब है कि जब बग ठीक किए जाते हैं और परफ़ॉर्मेंस में सुधार किया जाता है, तो हम सभी को इसका फ़ायदा मिलता है. इसलिए, हमें अपना सुझाव/राय दें या शिकायत करें!
Jetpack Compose का इस्तेमाल करने से, Instagram को एआई की मदद से डेवलपमेंट करने में काफ़ी फ़ायदा मिला. साथ ही, रोज़मर्रा के यूज़र इंटरफ़ेस इंजीनियरिंग को आसान बनाने में भी मदद मिली. डिक्लेरेटिव अप्रोच से बॉयलरप्लेट कम हो जाता है. साथ ही, इससे स्टेट के बारे में तर्क देना आसान हो जाता है और डेवलपर की पूरी प्रॉडक्टिविटी बेहतर हो जाती है. Instagram की इंजीनियरिंग टीम, ऐप्लिकेशन के अलग-अलग प्लैटफ़ॉर्म पर Compose को उपलब्ध कराने के लिए काम कर रही है. साथ ही, Google और Meta मिलकर Instagram और Jetpack Compose के उपयोगकर्ताओं के लिए, और भी बेहतर सुविधाएं उपलब्ध कराने के लिए काम कर रहे हैं.
अगर आपने अब तक Compose का इस्तेमाल नहीं किया है, तो अब एआई की मदद से Jetpack Compose पर माइग्रेट करना पहले से कहीं ज़्यादा आसान हो गया है.
स्वीकारोक्ति. Meta के Michal Zielinski और Matthew Du और Google के Andrei Shikov और George Mount को धन्यवाद. Meta और Google के बीच सहयोग से, Compose की परफ़ॉर्मेंस को बेहतर बनाने में मदद मिली! हम Meta के गैरी ये को भी धन्यवाद देते हैं. उन्होंने Instagram Direct में कंपोज़ करने की सुविधा उपलब्ध कराने में हमारी मदद की. साथ ही, हम 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 डेवलपमेंट से जुड़ी नई अहम जानकारी, हर हफ़्ते अपने इनबॉक्स में पाएं.