วิธีที่วิศวกรของ Instagram Direct สร้างสถาปัตยกรรม UI ที่มาพร้อม AI ในตัวด้วย Jetpack Compose และลดต้นทุนโทเค็นต่อเซสชัน Agent ลง 33%
ใช้เวลาอ่าน 11 นาที
บล็อกโพสต์นี้เขียนขึ้นโดยความร่วมมือกับทีม Meta
Instagram Direct เป็นหนึ่งในแพลตฟอร์มหลักของ Instagram ที่จัดการข้อความของผู้ใช้หลายพันล้านข้อความในแต่ละวัน ตลอดหลายปีที่ผ่านมา ทีมได้บีบทุกการเพิ่มประสิทธิภาพระดับไมโครที่เป็นไปได้ออกจากระบบ Android View เดิม อย่างไรก็ตาม การดูแลรักษาและขยายแพลตฟอร์มเดิมที่ได้รับการเพิ่มประสิทธิภาพอย่างมากจะสร้างหนี้ทางเทคนิคและค่าใช้จ่ายด้านวิศวกรรมจำนวนมาก โดยเฉพาะอย่างยิ่งเมื่อทีมต่างๆ หันมาใช้ UI แบบประกาศและผู้ช่วยเขียนโค้ด AI มากขึ้น
การนำ Jetpack Compose มาใช้กับ Instagram Direct เป็นมากกว่าการปรับปรุง UI ให้ทันสมัยตามปกติ ทีมได้สร้างฐานของโค้ด UI ที่เป็น AI แบบเนทีฟซึ่งมีขนาดเล็กลง 50% เมื่อเทียบกับการติดตั้งใช้งานเดิม ขณะเดียวกันก็ลดเวลาในการดำเนินการของ AI Agent ลง 35% , ลดการแลกเปลี่ยนระหว่างวิศวกรกับ Agent ลง 32% และลดต้นทุนโทเค็นลง 33% ทีมได้นำ Jetpack Compose มาใช้โดยร่วมมืออย่างใกล้ชิดกับ Google ขณะเดียวกันก็รักษามาตรฐานประสิทธิภาพไว้ในระดับสูง การเพิ่มประสิทธิภาพนี้ทำให้ Meta และ Google ปรับปรุง Compose ไม่เพียงแต่สำหรับ Instagram เท่านั้น แต่ยังรวมถึงระบบนิเวศของนักพัฒนาแอป Android ในวงกว้างด้วย
การปรับปรุงฐานของโค้ดให้ทันสมัยในวงกว้าง
AI ได้กลายเป็นเพื่อนคู่คิดในชีวิตประจำวันของวิศวกรในอุตสาหกรรมอย่างรวดเร็ว และการนำ AI ไปใช้กับฐานของโค้ดขนาดใหญ่อย่าง Instagram ก็ช่วยเพิ่มประสิทธิภาพการทำงานได้อย่างแท้จริง ทีม Instagram Direct ตั้งเป้าหมายที่ท้าทายยิ่งขึ้น แทนที่จะใช้เครื่องมือ AI กับโค้ดที่มีอยู่ ทีมได้ออกแบบฐานของโค้ดและสถาปัตยกรรมใหม่ให้เป็นแบบ AI-native โดยการออกแบบ ซึ่งช่วยเพิ่มผลลัพธ์ของ AI ได้มากกว่าการปรับปรุงโค้ดเดิมเพียงอย่างเดียว
ทีม Instagram Direct เลือก Jetpack Compose เป็นคอมโพเนนต์หลักในการสร้างสถาปัตยกรรม UI ที่ใช้ AI แบบเนทีฟ ลักษณะการประกาศช่วยให้โค้ดกระชับ คาดการณ์ได้ และมีโครงสร้างที่ง่ายขึ้นสำหรับโมเดล AI ในการให้เหตุผล โดยมีผลข้างเคียงน้อยลง สถานะโดยนัยน้อยลง และขอบเขตคอมโพเนนต์ที่ชัดเจนขึ้น
การย้ายข้อมูลไปยัง Jetpack Compose ต้องมีการวางแผนอย่างรอบคอบ ผู้คนหลายร้อยล้านคนส่งข้อความบน Instagram ทุกวัน ดังนั้นการย้ายข้อมูลจึงต้องค่อยเป็นค่อยไป ราบรื่น และไม่รบกวนประสบการณ์การใช้งานของผู้ใช้ในขณะที่ทีมปรับสถาปัตยกรรมพื้นฐานที่อยู่เบื้องหลัง เพื่อให้เห็นภาพขนาดของความท้าทายนี้ คอมโพเนนต์ UI แต่ละรายการสามารถแสดงผลในการเรียงสับเปลี่ยนสถานะที่แตกต่างกันกว่า 160 รายการ และหน้าจอการสนทนาเพียงหน้าจอเดียวจะจัดการประเภทข้อความที่แตกต่างกันมากกว่า 200 ประเภท
เมื่อย้ายข้อมูลฐานของโค้ดขนาดนี้ไปยัง Compose คุณอาจอยากเลือกวิธีที่ง่ายและฝังคอมโพเนนต์ UI ของ Compose ไว้ในลำดับชั้นการแสดงผลที่มีอยู่ ซึ่งเป็นขั้นตอนที่เพิ่มขึ้นในระหว่างการย้ายข้อมูลแบบค่อยเป็นค่อยไป ซึ่งเป็นวิธีที่ถูกต้องสมบูรณ์ อย่างไรก็ตาม ในระยะยาว การผสานรวม Compose ภายในฐานของโค้ดที่ใช้ View เป็นหลักอาจเป็นเรื่องท้าทาย เครื่องมือ AI มักจะเลือกเส้นทางที่ง่ายที่สุด หากคุณผสมโค้ด UI แบบประกาศและแบบบังคับ AI มีแนวโน้มที่จะผสมโค้ดทั้ง 2 แบบอย่างไม่ถูกต้อง ซึ่งทำให้เกิดข้อบกพร่องเล็กๆ น้อยๆ หนี้ทางเทคนิค และประสิทธิภาพที่ถดถอย
การสร้างสถาปัตยกรรม UI ที่มาพร้อม AI ในตัว
ในระดับของ Instagram การใช้สถาปัตยกรรมแบบนามธรรมเป็นสิ่งที่หลีกเลี่ยงไม่ได้ และเป็นสิ่งที่ช่วยให้แอปยังคงดูแลรักษาได้เมื่อเติบโตขึ้น ลองพิจารณารูปแบบทั่วไปที่ประเภทรายการ RecyclerView ทุกประเภทได้รับการจำลองเป็นคลาสสืบทอดของคลาสพื้นฐาน RecyclerViewItem ที่กำหนดเองซึ่งแสดงฮุกวงจรปกติ เช่น onBind
ตัวอย่างที่ 1
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") } } ... } } }
ในข้อมูลโค้ดด้านบน มีปัญหาเกิดขึ้น 2 อย่าง ก่อนอื่น ระบบจะอ่านแฟล็ก isPinnedChatsEnabled ในโค้ดแบบบังคับ แล้วบันทึกไว้ใน Lambda ของ Compose ซึ่งเป็นการเชื่อมโยงที่ละเอียดอ่อนระหว่างกระบวนทัศน์ ประการที่ 2 isPinned จะอยู่ในช่องที่เปลี่ยนแปลงได้ในตัวรายการเองแทนที่จะอยู่ใน ChatUiState ดังนั้นจึงยังคงอยู่แม้จะมีการเชื่อมโยง RecyclerView ซ้ำและการรีไซเคิลข้ามแถว ซึ่งทำให้เกิดการรั่วไหลและข้อบกพร่องที่ยากต่อการจำลองซ้ำ
แม้ว่าจะล้างโค้ดโดยให้ฟังก์ชัน @Composable เฉพาะแก่รายการแล้ว แต่ปัญหาก็ยังคงเหมือนเดิม
ตัวอย่างที่ 2
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") } } ... } }
นี่เป็นตัวอย่างง่ายๆ ที่เราตั้งใจยกขึ้นมา แต่ก็แสดงให้เห็นถึงปัญหาที่กว้างขึ้น นั่นคือ ยิ่ง AI มีขอบเขตน้อยลงเท่าใด คุณภาพของโค้ดที่สร้างขึ้นก็จะยิ่งต่ำลงเมื่อเวลาผ่านไป แม้ว่าการกำหนดขอบเขตและการฝึกทักษะจะช่วยได้ แต่ก็ยังไม่เพียงพอ เพราะเมื่อ AI พบอุปสรรค ก็มักจะหาทางหลบเลี่ยงเพื่อปลดล็อกตัวเอง
หากต้องการทำให้ฐานของโค้ดเป็นมิตรกับ AI คุณต้องปฏิบัติตามกฎที่นำไปใช้ได้จริง 2 ข้อต่อไปนี้
- ลดการพึ่งพาบริบทที่กำหนดเอง ยิ่ง AI Agent ต้องการความรู้เฉพาะเจาะจงเกี่ยวกับฐานของโค้ดที่กำหนดเองมากขึ้นเพื่อทำการเปลี่ยนแปลงที่ถูกต้อง คุณภาพของเอาต์พุตก็จะยิ่งต่ำลง ยิ่งฐานของโค้ดใกล้เคียงกับแนวทางปฏิบัติแนะนำที่ทราบมากเท่าใด ผลลัพธ์จาก AI ก็จะยิ่งดีขึ้นเท่านั้น
- ฐานของโค้ดที่เน้น AI เป็นหลักต้องบังคับใช้ขอบเขตของตนเอง การแก้ไขช่องโหว่ในการออกแบบด้วยทักษะ AI ไม่สามารถปรับขนาดได้ เนื่องจากทักษะทุกอย่างที่โหลดลงในบริบทจะใช้โทเค็นและอาจลดประสิทธิภาพของ Agent แต่สถาปัตยกรรมควรเป็นตัวรับน้ำหนักนั้นแทน AI Agent จะเลือกเส้นทางที่ง่ายที่สุดโดยธรรมชาติ ดังนั้นการออกแบบจึงควรทำให้เส้นทางนั้นนำไปสู่โค้ดที่ถูกต้องและมีคุณภาพสูง ในขณะเดียวกันก็ทำให้การตัดสินใจออกแบบที่ไม่ดีเป็นเรื่องยากและมีค่าใช้จ่ายสูง
รายการลิสต์ยังคงแสดงด้วยนามธรรมของตัวเองได้ แต่ในกรณีนี้ โค้ด Compose ทั้งหมดจะอยู่ในคอนสตรัคเตอร์ จึงไม่มีสิทธิ์เข้าถึงสมาชิกคลาสหรือสถานะ และแหล่งที่มาของอาร์กิวเมนต์เพียงแหล่งเดียวคือคอนสตรัคเตอร์ ซึ่งทำให้เทียบเท่ากับฟังก์ชัน @Composable ธรรมดา ขณะเดียวกันก็สอดคล้องกับสถาปัตยกรรมที่มีอยู่
ตัวอย่างที่ 3
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") } } ... }, )
การย้ายฐานของโค้ดขนาดนี้เป็นงานที่ยิ่งใหญ่มาก เป็นเวลานานแล้วที่คอมโพเนนต์ UI หลายร้อยรายการซึ่งประกอบขึ้นเป็น Direct UI ส่วนใหญ่ต้องอยู่ร่วมกับคอมโพเนนต์เดิม โดยทั้ง 2 อย่างได้รับการดูแลควบคู่กันไป เวิร์กโฟลว์ AI ช่วยให้การย้ายข้อมูลแบบคู่ขนานนี้เป็นไปได้ด้วยการเร่งกระบวนการเขียนโค้ดจำนวนมหาศาล แนวทางดังกล่าวช่วยให้ทีม Direct ทำการย้ายข้อมูลได้ในเวลาที่รวดเร็วเป็นประวัติการณ์ โดยไม่รบกวนทีมอื่นๆ ที่ยังคงเปิดตัวฟีเจอร์ที่ช่วยปรับปรุงประสบการณ์ของผู้คนหลายล้านคนทุกวัน
วิศวกรหลายคนเรียกใช้ AI Agent ของตนเองกับฐานความรู้ที่ใช้ร่วมกันซึ่งมีทักษะและแบบแผนที่นำกลับมาใช้ใหม่ได้ซึ่งสร้างขึ้นระหว่างการย้ายข้อมูล ซึ่งช่วยให้เวิร์กโฟลว์และแนวทางปฏิบัติแนะนำสอดคล้องกันทั่วทั้งทีม แทนที่จะให้วิศวกรแต่ละคนค้นพบแนวทางปฏิบัติเหล่านั้นด้วยตนเอง ทีมได้ดำเนินการย้ายข้อมูลในแต่ละแพลตฟอร์มตามขั้นตอนต่อไปนี้
- เขียนโค้ด Compose ทั้งหมดด้วย AI
- เราปรับแต่งโค้ด จัดการกับกรณีที่เกิดขึ้นไม่บ่อย และปิดช่องว่างด้านประสิทธิภาพ จนกระทั่ง UI ได้รับการเปิดตัวต่อผู้ใช้จริงในการทดสอบแบบสาธารณะ
การแบ่งงานออกเป็น 2 ขั้นตอนต่อหน้าจอช่วยให้วิศวกรคนหนึ่งสามารถดำเนินการได้อย่างรวดเร็วตลอดทั้งแพลตฟอร์ม โดยกำหนดสถาปัตยกรรมและกรณีขอบเขตที่ยุ่งยากไว้ล่วงหน้า เมื่อมีรากฐานดังกล่าวแล้ว คนอื่นๆ ก็สามารถมุ่งเน้นไปที่การทำให้ UI พร้อมใช้งานจริงได้โดยไม่ต้องหยุดเพื่อตัดสินใจทางเทคนิคเหล่านั้นด้วยตนเอง ซึ่งจะช่วยให้การย้ายข้อมูลโดยรวมเป็นไปอย่างรวดเร็ว
ผลลัพธ์ของการย้ายข้อมูลได้ยืนยันแนวทางดังกล่าว สำหรับแพลตฟอร์ม Instagram Direct ที่ย้ายข้อมูลแล้ว Jetpack Compose ช่วยให้ทีมลดจำนวนโค้ด UI ทั้งหมดลงได้ 50% โค้ดที่ AI ต้องสร้างน้อยลงจะเชื่อมโยงกับเอาต์พุตที่มีคุณภาพสูงขึ้นและต้นทุนโทเค็นต่อหนึ่งงานที่ต่ำลง
การวิเคราะห์ข้อมูลภายในของฐานของโค้ด Android สำหรับ Instagram Direct เปรียบเทียบเซสชัน AI Agent ที่ทำงานบน Compose UI กับงานเดียวกันที่ใช้ Android Views ประสิทธิภาพที่เพิ่มขึ้นเห็นได้ชัดใน 2 มิติ ดังนี้
- ต่ออักขระของโค้ดที่นำไปใช้: Compose ต้องการการแลกเปลี่ยนระหว่างวิศวกรกับ Agent น้อยลง 32% และเวลาในการดำเนินการของ Agent น้อยลง 35% (เวลาที่ผ่านไปนับตั้งแต่ Agent เริ่มทำงานตามคำขอของวิศวกรจนกว่าจะแสดงผลลัพธ์)
- ต่อเซสชัน Agent: ต้นทุนโทเค็นโดยรวมลดลง 33% เมื่อใช้ Compose เทียบกับ Views
เรารายงานทั้งประสิทธิภาพเอาต์พุตและจำนวนเซสชันทั่วไปเนื่องจากเป็นผลลัพธ์ที่มีประโยชน์ในตัวเอง การแลกเปลี่ยนระหว่างวิศวกรกับ Agent และตัวเลขเวลาในการดำเนินการจะเปรียบเทียบการใช้ทรัพยากรต่อหน่วยของเอาต์พุตที่ได้ ขณะที่ตัวเลขโทเค็นจะเปรียบเทียบต้นทุนทั้งหมดสำหรับเซสชัน Agent ทั่วไป
นอกจากนี้ ข้อมูลยังเผยให้เห็นความแตกต่างที่สอดคล้องกันในวิธีที่เฟรมเวิร์กทั้ง 2 จัดการกับโค้ดที่ซับซ้อนหรือเปราะบาง Meta ติดตามเรื่องนี้โดยใช้คะแนนความเสี่ยงของการเปลี่ยนแปลงโค้ด ซึ่งจะประเมินคุณภาพโค้ดโดยรวมและความเป็นไปได้ที่การเปลี่ยนแปลงจะทำให้เกิดเหตุการณ์ในเวอร์ชันที่ใช้งานจริง การวิเคราะห์นี้วัดประสิทธิภาพของทรัพยากรของ Agent โดยใช้การใช้โทเค็น เวลาในการดำเนินการของ Agent และการโต้ตอบระหว่างวิศวกรกับ Agent เมื่อไฟล์มีคะแนนความเสี่ยงสูงขึ้น เซสชันของ AI Agent จะใช้ทรัพยากรอย่างมีประสิทธิภาพน้อยลงโดยอัตโนมัติ
เมื่อคะแนนความเสี่ยงสะสมของไฟล์เพิ่มขึ้นเป็น 2 เท่า UI ที่ใช้กับ Android Views จะลดประสิทธิภาพของทรัพยากร Agent ลง 30% (ต่ออักขระที่แสดง) ในสถานการณ์เดียวกันนี้ UI ของ Jetpack Compose ลดลงเพียง 9%
ด้วยความร่วมมือระหว่าง Google และ Meta ทีม Instagram Direct ได้นำมุมมองใหม่ๆ มาใช้ในการนำ Compose มาใช้ โดยพิจารณาผ่านมุมมองของความพร้อมด้าน AI ของฐานของโค้ด ไม่ใช่แค่การเขียน UI ใหม่ งานนี้เผยให้เห็นจุดแข็งของ Compose ในการทำหน้าที่เป็นรากฐานสำหรับการสร้างฐานของโค้ดและสถาปัตยกรรมที่เน้น AI เป็นหลัก โดยเฉพาะเมื่อนำไปใช้ในระดับแอปอย่าง Instagram
การเพิ่มประสิทธิภาพ
Instagram Direct เป็นหนึ่งในแพลตฟอร์มที่สำคัญที่สุดของแอป และผู้ใช้คาดหวังว่าแพลตฟอร์มนี้จะทำงานได้อย่างรวดเร็วและตอบสนองได้ดีตลอดเวลา การนำ Jetpack Compose มาใช้อย่างมีประสิทธิภาพหมายถึงการเขียน UI ใหม่จำนวนมาก และเป้าหมายอันดับหนึ่งคือการรักษาประสบการณ์การใช้งานคุณภาพสูงโดยไม่มีการถดถอย
การปรับปรุงซ้ำๆ เป็นเวลาหลายปีได้ผลักดันให้การใช้งานแบบอิงตามมุมมองเดิมใน Instagram มีประสิทธิภาพสูงเป็นพิเศษ และทีมจำเป็นต้องรักษามาตรฐานเดียวกันนี้ไว้ขณะเปลี่ยนไปใช้เฟรมเวิร์ก UI ใหม่ทั้งหมด
Instagram วัดเมตริกประสิทธิภาพหลายร้อยรายการหรืออาจถึงหลายพันรายการ สำหรับการนำ Compose มาใช้ สิ่งที่สำคัญที่สุด 3 ประการมีดังนี้
- เวลาในการตอบสนอง - ระยะเวลาระหว่างการเปิดหน้าจอจนถึงเวลาที่สามารถใช้งานได้
- เวลาในการโหลดจนเสร็จสมบูรณ์ - ระยะเวลาระหว่างการเปิดหน้าจอจนถึงเวลาที่เนื้อหาทั้งหมดโหลดเสร็จสมบูรณ์ (เช่น รูปภาพ)
- ประสิทธิภาพการเลื่อน - ความราบรื่นในการเลื่อนหน้าจอโดยไม่มีเฟรมที่หายไป
ระบบจะติดตามเมตริกเหล่านี้ที่รันไทม์ในเวอร์ชันที่ใช้งานจริง ซึ่งช่วยให้ทำการทดสอบ A/B เพื่อเปรียบเทียบ UI ของ Compose ที่ย้ายข้อมูลกับ UI เดิม และประเมินผลกระทบด้านประสิทธิภาพของความพยายามนี้ได้
วิธีทั่วไปในการย้ายข้อมูลเช่นนี้คือการเริ่มจากส่วนเล็กๆ โดยย้ายคอมโพเนนต์ UI จำนวนหนึ่ง รวบรวมข้อมูล และศึกษาลักษณะการทำงานของคอมโพเนนต์เหล่านั้น แม้ว่าผลลัพธ์เบื้องต้นเหล่านี้จะมีประโยชน์ แต่ก็แสดงให้เห็นภาพเพียงบางส่วนเท่านั้น โดยให้ผลลบเท็จ (False Negative) ต่อการนำ Compose มาใช้เนื่องจากสาเหตุต่อไปนี้
- ไม่เป็นตัวแทน - คอมโพเนนต์ UI ที่ย้ายข้อมูลแล้ว 1 รายการสามารถให้ข้อมูลที่เป็นประโยชน์เกี่ยวกับประสิทธิภาพโดยรวมในหน้าจอหนึ่งๆ ได้ อย่างไรก็ตาม องค์ประกอบต่างๆ มีลักษณะการทำงานที่แตกต่างกันด้วยเหตุผลที่ไม่ได้เป็นไปตามหลักทั่วไป คุณจึงไม่สามารถคาดการณ์จากองค์ประกอบดังกล่าวได้เสมอไป
- ต้นทุนการทำงานร่วมกัน — โค้ด Compose ขนาดเล็กภายในฐานของโค้ด View ขนาดใหญ่จะมีต้นทุนการเชื่อมต่อที่คาดเดาไม่ได้ระหว่างทั้ง 2 ระบบ ค่าใช้จ่ายดังกล่าวจะบิดเบือนการวัดผล ดังนั้นผลลัพธ์ขนาดเล็กในช่วงแรกจึงไม่สะท้อนถึงลักษณะของการย้ายข้อมูลทั้งหมดที่เกิดขึ้นจริง
ผลลัพธ์ที่ได้คือการย้ายข้อมูลขนาดเล็ก แม้ว่าจะมีประโยชน์ แต่ก็ไม่ได้แสดงถึงผลกระทบทั้งหมดของ Compose เสมอไป ยิ่งมีการย้ายข้อมูลแพลตฟอร์มแบบครบวงจรโดยไม่มีการหยุดชะงักในการเชื่อมต่อมากเท่าใด ภาพรวมด้านประสิทธิภาพก็จะยิ่งชัดเจนและดีขึ้นเท่านั้น
หน้าจอหลักใน Instagram Direct สร้างขึ้นจากรายการประเภทต่างๆ ที่มีความยาว ซึ่งเดิมใช้ RecyclerView สถาปัตยกรรมนี้อาศัยนามธรรมที่กำหนดเองเพื่อความสามารถในการปรับขนาด แต่ยังคงผูกพันกับวงจรของระบบที่อิงตามมุมมอง
งานหลักของทีมคือการค่อยๆ ย้ายข้อมูลรายการหลายร้อยรายการไปยัง Compose ภายในสถาปัตยกรรมที่ใช้ RecyclerView ที่มีอยู่ โดยเปิดตัวในเวอร์ชันที่ใช้งานจริงในกลุ่มเล็กๆ ที่เป็นอิสระภายใต้การทดสอบ A/B โดยทั้งหมดนี้ไม่มีการเปลี่ยนแปลงที่มองเห็นได้ในประสบการณ์การรับส่งข้อความของผู้ใช้
ข้อเสียที่ใหญ่ที่สุดของการตั้งค่าดังกล่าวคือการพึ่งพาระบบ View เดิมอย่างมากผ่านสถาปัตยกรรม RecyclerView หลัก แม้ว่าจะย้ายข้อมูลรายการทั้งหมดไปยัง Compose แล้วก็ตาม ขั้นตอนถัดไปที่สมเหตุสมผลคือทีมตัดสินใจลงทุนในการแทนที่สถาปัตยกรรมหลักที่ใช้ RecyclerView ด้วยทางเลือกที่มาพร้อมกับ Compose อย่าง LazyColumn
ซึ่งหมายความว่าคอมโพเนนต์ Compose UI ควรแยกออกจากเฟรมเวิร์กที่รวมอยู่ด้วย แต่ยังคงเข้ากันได้กับทั้ง RecyclerView และ LazyColumn ในเวลาเดียวกัน ความสามารถในการสลับระหว่างทั้ง 2 อย่างในรันไทม์ผ่านแฟล็กฟีเจอร์ก็มีความสำคัญไม่แพ้กัน เพื่อเปิดใช้การทดสอบ A/B
แม้ว่ารายการ Compose ใหม่จะเข้ากันได้กับ LazyColumn โดยค่าเริ่มต้นและสามารถเสียบเข้ากับแผนผังองค์ประกอบที่ไม่มีการรบกวนได้ แต่ก็มีการสร้าง API การทำงานร่วมกันเพื่อเสียบรายการเหล่านั้นลงใน RecyclerView ด้วย ซึ่งทำให้สามารถเปิดตัวการตั้งค่า LazyColumn ภายใต้การทดสอบ A/B ควบคู่ไปกับ RecyclerView โดยนำรายการ Compose เดียวกันมาใช้ซ้ำและปรับปรุงประสิทธิภาพ โดยไม่รบกวนทีมที่เหลือที่กำลังสร้างและปรับแต่งฟีเจอร์
ขนาด ความซับซ้อน และความไวของ Instagram ต่อการถดถอยแม้เพียงเล็กน้อยทำให้ Jetpack Compose ต้องเผชิญกับความท้าทายที่ไม่เหมือนใคร การแก้ไขปัญหาเหล่านี้ต้องอาศัยการทำงานร่วมกันอย่างใกล้ชิดและต่อเนื่อง วิศวกรของ Google และ Meta ทำงานร่วมกันอย่างใกล้ชิดเพื่อวิเคราะห์เมตริกเพื่อระบุและออกแบบความสามารถใหม่ๆ ของ Compose เพื่อให้ตรงตามหรือเหนือกว่าเกณฑ์เปรียบเทียบที่อิงตาม View ผลลัพธ์จากการเป็นพาร์ทเนอร์นี้ทำให้ Jetpack Compose มีฟีเจอร์เพิ่มเติมที่โดดเด่น ได้แก่ Composition ที่หยุดชั่วคราวได้ด้วย LazyLayoutCacheWindows และการติดตามระดับการมองเห็น
องค์ประกอบที่หยุดชั่วคราวได้ด้วย LazyLayoutCacheWindows
Composition ที่หยุดชั่วคราวได้ (เปิดใช้โดยค่าเริ่มต้นใน Compose 1.10) ช่วยให้สามารถสร้างรายการ Lazy List ที่ใช้ทรัพยากรมากแบบค่อยเป็นค่อยไปในเฟรมต่างๆ เพื่อป้องกันการกระตุก เมื่อใช้ร่วมกับ LazyLayoutCacheWindow (เพิ่มใน Compose 1.9) การใช้ร่วมกันนี้จะช่วยเพิ่มความลื่นไหลในการเลื่อนได้อย่างมาก ในการทดสอบภายในล่าสุดที่ Meta การรวม Composition ที่หยุดชั่วคราวได้เข้ากับLazyLayoutCacheWindowวิวพอร์ตเดียวช่วยลดเฟรมขนาดใหญ่ที่หายไปต่อนาที (LFD/m) ได้ประมาณ 13% เมื่อเทียบกับ Compose แบบธรรมดา ส่วน Cache Window เพียงอย่างเดียวช่วยลดการใช้หน่วยความจำได้ประมาณ 8% เมื่อเทียบกับเกณฑ์พื้นฐานเดียวกัน LFDs/m เป็นเมตริกภายในที่ 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) { ... }
การกำหนดค่าหน้าต่างแคชทำได้ 2 วิธี ทั้ง 2 รายการอธิบายสิ่งเดียวกัน นั่นคือปริมาณเนื้อหานอกหน้าจอที่ต้องจัดองค์ประกอบไว้ แต่ใช้หน่วยต่างกัน
- Dp: ความยาวสัมบูรณ์คงที่
ahead = 150.dpจะเก็บเนื้อหาขนาด 150dp ที่ประกอบขึ้นเลยขอบที่มองเห็นได้ไว้ ไม่ว่าจะใช้อุปกรณ์ใดก็ตาม - Float: เศษส่วนของวิวพอร์ต
aheadFraction = 0.5fจะเก็บครึ่งหนึ่งของหน้าจอที่คอมโพสไว้ล่วงหน้า ดังนั้นจำนวนสัมบูรณ์จะปรับขนาดตามความสูงของหน้าจอที่รองรับรูปแบบต่างๆ เช่น แท็บเล็ตหรืออุปกรณ์แบบพับได้ที่กางออกจะมีจำนวนมากกว่า ส่วนโทรศัพท์ขนาดกะทัดรัดจะมีจำนวนน้อยกว่า
ทีม Instagram ได้ปรับแต่งเศษส่วนแบบ Float ของหน้าต่างแคชให้เหมาะกับโครงสร้างเนื้อหาและขนาดรายการของ Direct โดยเฉพาะ เนื่องจากค่าที่เหมาะสมจะแตกต่างกันไปตามพารามิเตอร์ UI ที่เฉพาะเจาะจง การค้นหาความสมดุลที่เหมาะสมจึงต้องมีการทดสอบ
การบันทึกการแสดงผลด้วย onVisibilityChanged
API onVisibilityChanged (เพิ่มใน Compose 1.9.0) เป็นผลลัพธ์สำคัญอีกอย่างหนึ่งจากความร่วมมือทางเทคนิคระหว่าง Google กับ Meta ซึ่งช่วยให้แพลตฟอร์ม Jetpack Compose ขนาดใหญ่มีวิธีที่สอดคล้องกันในการทราบว่า Composable ปรากฏบนหน้าจอจริงเมื่อใด โดยแทนที่การใช้งานที่กำหนดเองและเขียนด้วยมือซึ่งใช้ในอดีต ภายใน Instagram Direct เพียงอย่างเดียว สัญญาณการมองเห็นเหล่านี้จะใช้ในไฟล์หลายร้อยไฟล์เพื่อรองรับเมตริกคุณภาพของผลิตภัณฑ์ซึ่งขึ้นอยู่กับว่าองค์ประกอบ UI แสดงต่อผู้ใช้จริงหรือไม่
ประสิทธิภาพการเริ่มต้นระบบ
การนำ Jetpack Compose มาใช้กับ Instagram Direct ช่วยปรับปรุงประสิทธิภาพในแพลตฟอร์มอื่นๆ ของแอปอย่างไม่คาดคิด รันไทม์ของ Jetpack Compose มีค่าใช้จ่ายในการเตรียมความพร้อมที่คุณจ่ายเพียงครั้งเดียว และเนื่องจากการรับส่งข้อความเป็นแพลตฟอร์มที่มีการเข้าชมสูงซึ่งมักมีการเข้าชมตั้งแต่ช่วงต้นของเซสชันของผู้ใช้ แพลตฟอร์มอื่นๆ ใน Instagram ที่ใช้ Compose จึงมีการปรับปรุงประสิทธิภาพที่เห็นได้ชัดเจน
ประสิทธิภาพการเริ่มต้นของ Compose UI ภายใน Instagram Direct ได้รับการเพิ่มประสิทธิภาพผ่านการใช้โปรไฟล์พื้นฐาน ซึ่งจะคอมไพล์เส้นทางโค้ดที่ใช้บ่อยล่วงหน้า ณ เวลาติดตั้ง เพื่อให้ Compose แสดงผลได้อย่างรวดเร็วตั้งแต่การเปิดตัวครั้งแรก
บทเรียนจากการย้ายข้อมูล Instagram Direct ไปยัง Jetpack Compose
- Jetpack Compose ให้ผลตอบแทนจากการลงทุนทันที: คุณไม่จำเป็นต้องใช้เวิร์กโฟลว์ AI ขั้นสูงเพื่อรับประโยชน์จาก Compose โค้ดที่ลดลงประมาณ 50% หมายความว่ามีโค้ดที่ต้องดูแลรักษาน้อยลง และลดโอกาสที่จะเกิดข้อบกพร่อง
- การออกแบบสถาปัตยกรรมที่ใช้ AI เป็นหลักทำให้เกิดชัยชนะครั้งสำคัญ ซึ่งรวมถึงเวลาในการดำเนินการของ AI Agent ที่ลดลง 35%, การแลกเปลี่ยนระหว่างวิศวกรกับ Agent ลดลง 32% และต้นทุนโทเค็นลดลง 33%
- แม้ว่าจะมี API สำหรับการทำงานร่วมกันและการรองรับการรวม Views และ Compose เข้าด้วยกันอยู่มากมาย แต่ให้มุ่งเน้นที่การย้ายข้อมูลแพลตฟอร์มขนาดใหญ่กว่าคอมโพเนนต์ขนาดเล็กแต่ละรายการ วิธีนี้จะช่วยให้ UI อยู่ในลำดับชั้นองค์ประกอบเดียวที่ไม่ขาดตอน และปลดล็อกการเพิ่มประสิทธิภาพแบบเนทีฟของ Compose ที่ดีที่สุดทั้งหมด
- จับคู่คอมโพสิชันที่หยุดชั่วคราวได้กับ LazyLayoutCacheWindow: การจับคู่ 2 รายการนี้เข้าด้วยกันจะให้ผลลัพธ์ที่ดีกว่าการใช้หน้าต่างแคชเพียงอย่างเดียว หากมีเพียงหน้าต่างแคช รายการที่มีขนาดใหญ่อาจยังคงพยายามคอมโพสในรอบเดียว ซึ่งอาจทำให้เกินงบประมาณเฟรม
- มีส่วนร่วมในการพัฒนา Compose Meta ได้ร่วมมือกับทีม Jetpack Compose เพื่อนำความคิดเห็นและไอเดียต่างๆ มาใช้ใน Compose การทำงานกับชุดเครื่องมือโอเพนซอร์สหมายความว่าเราทุกคนจะได้รับประโยชน์เมื่อมีการแก้ไขข้อบกพร่องและปรับปรุงประสิทธิภาพจากส่วนกลาง ดังนั้น โปรดแสดงความคิดเห็นให้เราทราบ
การนำ Jetpack Compose มาใช้ช่วยเพิ่มประสิทธิภาพในการพัฒนาที่มีการใช้งาน AI ช่วยได้อย่างมาก พร้อมทั้งลดความซับซ้อนของวิศวกรรม UI ในแต่ละวันของ Instagram แนวทางแบบประกาศช่วยลดโค้ดสำเร็จรูป ทำให้เข้าใจสถานะได้ง่ายขึ้น และปรับปรุงประสิทธิภาพการทำงานโดยรวมของนักพัฒนาซอฟต์แวร์ ทีมวิศวกรของ Instagram ตั้งตารอที่จะนำ Compose ไปใช้กับแพลตฟอร์มอื่นๆ ในแอป และความร่วมมืออย่างต่อเนื่องระหว่าง Google และ Meta เพื่อนำการปรับปรุงเพิ่มเติมมาสู่ผู้ใช้ Instagram และ Jetpack Compose
หากคุณยังไม่ได้ลองใช้ Compose ตอนนี้มี AI คอยช่วยเหลือแล้ว การย้ายข้อมูลไปยัง Jetpack Compose จึงง่ายกว่าที่เคย
การรับทราบ ขอขอบคุณ Michal Zielinski และ Matthew Du จาก Meta รวมถึง Andrei Shikov และ George Mount จาก Google ที่ช่วยปรับปรุงประสิทธิภาพของ Compose ผ่านการทำงานร่วมกันระหว่าง Meta และ Google ขอขอบคุณ Gary Ye จาก Meta ที่ช่วยนำ Compose มาใช้กับ Instagram Direct และ Gopal Juneja จาก Meta ที่สนับสนุนความพยายามนี้ผ่านวิทยาศาสตร์ข้อมูล
-
กรณีศึกษาGrab เป็นซูเปอร์แอปชั้นนำของเอเชียตะวันออกเฉียงใต้ที่ให้บริการจัดส่ง การเดินทาง และบริการทางการเงินแก่ผู้ใช้หลายล้านคนใน 8 ประเทศผ่านแอปเดียว
Ajesh Pai, Nguyen Van Minh, Tracy Agyemang • ใช้เวลาอ่าน 5 นาที -
กรณีศึกษาWhatsApp เป็นแพลตฟอร์มรับส่งข้อความที่ใหญ่ที่สุดในโลก โดยให้บริการผู้ใช้หลายพันล้านคนทั่วโลก ซึ่งเป็นเครื่องมือสื่อสารเริ่มต้นสำหรับผู้คนในภูมิภาคต่างๆ ที่เชื่อมต่อผู้ใช้ผ่านการรับส่งข้อความที่เป็นส่วนตัว เชื่อถือได้ และปลอดภัย
Niharika Arora, Tracy Agyemang, Mayank Jain • ใช้เวลาอ่าน 8 นาที -
กรณีศึกษาTinder มีพันธกิจในการส่งเสริมและสร้างแรงบันดาลใจให้เกิดความสัมพันธ์ที่แท้จริงด้วยการทำให้การพบปะเป็นเรื่องง่ายและสนุกสำหรับคนโสดรุ่นใหม่ทุกรุ่น
Ajesh Pai, Ulises Uriel Verduzco Díaz , Tracy Agyemang • ใช้เวลาอ่าน 4 นาที
รับข้อมูลเชิงลึกเกี่ยวกับการพัฒนา Android ล่าสุดที่ส่งไปยังกล่องจดหมายของคุณทุกสัปดาห์