ทีม Android Runtime (ART) ได้ลดเวลาคอมไพล์ลง 18% โดยไม่ลดทอนคุณภาพของโค้ดที่คอมไพล์แล้วหรือการถดถอยของหน่วยความจำสูงสุด การปรับปรุงนี้เป็นส่วนหนึ่งของความคิดริเริ่มในปี 2025 ของเราในการปรับปรุงเวลาคอมไพล์โดยไม่ลดการใช้งานหน่วยความจำหรือคุณภาพของโค้ดที่คอมไพล์แล้ว
การเพิ่มประสิทธิภาพความเร็วในการคอมไพล์เป็นสิ่งสำคัญสำหรับ ART เช่น เมื่อคอมไพล์แบบ Just-In-Time (JIT) จะส่งผลโดยตรงต่อประสิทธิภาพของแอปพลิเคชันและประสิทธิภาพโดยรวมของอุปกรณ์ การคอมไพล์ที่เร็วขึ้นจะช่วยลดเวลาก่อนที่การเพิ่มประสิทธิภาพจะเริ่มทำงาน ซึ่งนำไปสู่ประสบการณ์การใช้งานของผู้ใช้ที่ราบรื่นและตอบสนองได้ดียิ่งขึ้น นอกจากนี้ ทั้งสำหรับ JIT และ Ahead-Of-Time (AOT) การปรับปรุงความเร็วในการคอมไพล์จะช่วยลดการใช้ทรัพยากรในระหว่างกระบวนการคอมไพล์ ซึ่งเป็นประโยชน์ต่อระยะเวลาการใช้งานแบตเตอรี่และอุณหภูมิของอุปกรณ์ โดยเฉพาะอย่างยิ่งในอุปกรณ์ระดับล่าง
การปรับปรุงความเร็วในการคอมไพล์บางส่วนเปิดตัวใน Android เวอร์ชันที่เผยแพร่ในเดือนมิถุนายน 2025 และส่วนที่เหลือจะพร้อมใช้งานใน Android เวอร์ชันที่เผยแพร่ในช่วงสิ้นปี นอกจากนี้ ผู้ใช้ Android ทุกคนในเวอร์ชัน 12 ขึ้นไปมีสิทธิ์ได้รับการปรับปรุงเหล่านี้ผ่านการอัปเดต Mainline
การเพิ่มประสิทธิภาพคอมไพเลอร์ที่เพิ่มประสิทธิภาพ
การเพิ่มประสิทธิภาพคอมไพเลอร์มักจะต้องมีการแลกเปลี่ยนเสมอ คุณไม่สามารถได้ความเร็วมาฟรีๆ แต่ต้องยอมเสียบางอย่างไป เราตั้งเป้าหมายที่ชัดเจนและท้าทายไว้ว่า จะทำให้คอมไพเลอร์เร็วขึ้น แต่ต้องไม่ทำให้เกิดการถดถอยของหน่วยความจำ และที่สำคัญคือต้องไม่ลดคุณภาพของโค้ดที่คอมไพเลอร์สร้างขึ้น หากคอมไพเลอร์เร็วขึ้นแต่แอปทำงานช้าลง เราก็ถือว่าล้มเหลว
ทรัพยากรเดียวที่เรายินดีที่จะใช้คือเวลาในการพัฒนาของเราเองเพื่อเจาะลึก ตรวจสอบ และค้นหาวิธีแก้ปัญหาที่ชาญฉลาดซึ่งตรงตามเกณฑ์ที่เข้มงวดเหล่านี้ มาดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีที่เราทำงานเพื่อค้นหาจุดที่ต้องปรับปรุง รวมถึงค้นหาวิธีแก้ปัญหาที่เหมาะสมกับปัญหาต่างๆ
การค้นหาการเพิ่มประสิทธิภาพที่เป็นไปได้และคุ้มค่า
ก่อนที่จะเริ่มเพิ่มประสิทธิภาพเมตริก คุณต้องวัดเมตริกนั้นได้ มิฉะนั้น คุณจะไม่มีทางแน่ใจว่าได้ปรับปรุงเมตริกนั้นแล้วหรือไม่ โชคดีที่ความเร็วในการคอมไพล์ค่อนข้างสม่ำเสมอ ตราบใดที่คุณใช้ความระมัดระวังบางอย่าง เช่น ใช้อุปกรณ์เครื่องเดียวกับที่ใช้ในการวัดก่อนและหลังการเปลี่ยนแปลง และตรวจสอบว่าคุณไม่ได้จำกัดความเร็วของอุปกรณ์เนื่องจากความร้อน นอกจากนี้ เรายังมีการวัดที่กำหนดได้ เช่น สถิติคอมไพเลอร์ ซึ่งช่วยให้เราเข้าใจสิ่งที่เกิดขึ้นเบื้องหลัง
เนื่องจากทรัพยากรที่เราเสียไปเพื่อการปรับปรุงเหล่านี้คือเวลาในการพัฒนา เราจึงต้องการทำซ้ำให้เร็วที่สุดเท่าที่จะทำได้ ซึ่งหมายความว่าเราได้เลือกแอปที่เป็นตัวแทนมาจำนวนหนึ่ง (ทั้งแอปของบุคคลที่หนึ่ง แอปของบุคคลที่สาม และระบบปฏิบัติการ Android เอง) เพื่อสร้างต้นแบบวิธีแก้ปัญหา ต่อมา เราได้ยืนยันว่าการติดตั้งใช้งานขั้นสุดท้ายนั้นคุ้มค่าด้วยการทดสอบทั้งแบบแมนนวลและแบบอัตโนมัติในวงกว้าง
เราจะทริกเกอร์การคอมไพล์แบบแมนนวลในเครื่องด้วยชุด APK ที่เลือกไว้ จากนั้นรับโปรไฟล์การคอมไพล์ และใช้ pprof เพื่อแสดงภาพว่าเราใช้เวลาไปกับอะไรบ้าง
ตัวอย่างกราฟ Flame Graph ของโปรไฟล์ใน pprof
เครื่องมือ pprof มีประสิทธิภาพมากและช่วยให้เราแบ่ง กรอง และจัดเรียงข้อมูลเพื่อดูได้ เช่น ระยะการคอมไพล์หรือเมธอดใดที่ใช้เวลามากที่สุด เราจะไม่ลงรายละเอียดเกี่ยวกับ pprof เอง เพียงแค่ทราบว่าหากแถบมีขนาดใหญ่ขึ้น แสดงว่าการคอมไพล์ใช้เวลานานขึ้น
มุมมองหนึ่งคือมุมมอง "จากล่างขึ้นบน" ซึ่งคุณจะเห็นเมธอดที่ใช้เวลามากที่สุด ในรูปภาพด้านล่าง เราจะเห็นเมธอดที่ชื่อว่า Kill ซึ่งใช้เวลาคอมไพล์มากกว่า 1% นอกจากนี้ เราจะพูดถึงเมธอดยอดนิยมอื่นๆ ในบล็อกโพสต์นี้ด้วย
มุมมองจากล่างขึ้นบนของโปรไฟล์
ในคอมไพเลอร์ที่เพิ่มประสิทธิภาพของเรา มีระยะที่เรียกว่า Global Value Numbering (GVN) คุณไม่จำเป็นต้องกังวลเกี่ยวกับสิ่งที่ GVN ทำโดยรวม แต่ส่วนที่เกี่ยวข้องคือการทราบว่า GVN มีเมธอดที่ชื่อว่า `Kill` ซึ่งจะลบบางโหนดตามตัวกรอง การดำเนินการนี้ใช้เวลานานเนื่องจากต้องทำซ้ำผ่านโหนดทั้งหมดและตรวจสอบทีละโหนด เราสังเกตเห็นว่ามีบางกรณีที่เรารู้ล่วงหน้าว่าการตรวจสอบจะเป็นเท็จ ไม่ว่าจะมีโหนดใดที่ใช้งานได้ในขณะนั้น ในกรณีเหล่านี้ เราสามารถข้ามการทำซ้ำทั้งหมดได้ ซึ่งจะลดเวลาจาก 1.023% ลงเหลือประมาณ 0.3% และปรับปรุงรันไทม์ของ GVN ได้ประมาณ 15%
การติดตั้งใช้งานการเพิ่มประสิทธิภาพที่คุ้มค่า
เราได้พูดถึงวิธีวัดและวิธีตรวจหาจุดที่ใช้เวลาไป แต่ทั้งหมดนี้เป็นเพียงจุดเริ่มต้น ขั้นตอนถัดไปคือวิธีเพิ่มประสิทธิภาพเวลาที่ใช้ในการคอมไพล์
โดยปกติแล้ว ในกรณีเช่น `Kill` ที่กล่าวถึงข้างต้น เราจะดูวิธีทำซ้ำผ่านโหนดและดำเนินการให้เร็วขึ้น เช่น ทำสิ่งต่างๆ แบบขนานกันหรือปรับปรุงอัลกอริทึมเอง อันที่จริง เราได้ลองทำแบบนั้นก่อน และเมื่อไม่พบสิ่งที่จะทำ เราก็คิดขึ้นมาได้ว่า "เดี๋ยวนะ..." และเห็นว่าวิธีแก้ปัญหาคือ (ในบางกรณี) ไม่ต้องทำซ้ำเลย! เมื่อทำการเพิ่มประสิทธิภาพประเภทนี้ คุณอาจมองข้ามภาพรวมไปได้ง่าย
ในกรณีอื่นๆ เราได้ใช้เทคนิคต่างๆ มากมาย ซึ่งรวมถึง
- ใช้ฮิวริสติกเพื่อตัดสินว่าการเพิ่มประสิทธิภาพจะให้ผลลัพธ์ที่คุ้มค่าหรือไม่ และจึงข้ามการเพิ่มประสิทธิภาพนั้นได้
- ใช้โครงสร้างข้อมูลเพิ่มเติมเพื่อแคชข้อมูลที่คำนวณแล้ว
- เปลี่ยนโครงสร้างข้อมูลปัจจุบันเพื่อเพิ่มความเร็ว
- คำนวณผลลัพธ์แบบเลซซีเพื่อหลีกเลี่ยงการวนซ้ำในบางกรณี
- ใช้การแยกส่วนที่เหมาะสม ฟีเจอร์ที่ไม่จำเป็นอาจทำให้โค้ดทำงานช้าลง
- หลีกเลี่ยงการติดตามพอยน์เตอร์ที่ใช้บ่อยผ่านการโหลดหลายครั้ง
เราจะทราบได้อย่างไรว่าการเพิ่มประสิทธิภาพนั้นคุ้มค่าที่จะทำต่อ
คุณไม่จำเป็นต้องทราบ หลังจากตรวจพบว่าส่วนหนึ่งใช้เวลาคอมไพล์มาก และหลังจากใช้เวลาในการพัฒนาเพื่อพยายามปรับปรุงส่วนนั้นแล้ว บางครั้งคุณก็อาจไม่พบวิธีแก้ปัญหา อาจไม่มีอะไรให้ทำ ใช้เวลานานเกินไปในการติดตั้งใช้งาน ทำให้เมตริกอื่นถดถอยลงอย่างมาก เพิ่มความซับซ้อนของฐานของโค้ด ฯลฯ การเพิ่มประสิทธิภาพที่สำเร็จทุกครั้งที่คุณเห็นในบล็อกโพสต์นี้มีอีกมากมายนับไม่ถ้วนที่ไม่ประสบความสำเร็จ
หากคุณอยู่ในสถานการณ์ที่คล้ายกัน ให้ลองประมาณว่าคุณจะปรับปรุงเมตริกได้มากน้อยเพียงใดโดยทำงานให้น้อยที่สุดเท่าที่จะทำได้ ซึ่งหมายความว่าให้ทำตามลำดับต่อไปนี้
- ประมาณการโดยใช้เมตริกที่คุณได้รวบรวมไว้แล้ว หรือเพียงแค่ใช้ความรู้สึก
- ประมาณการโดยใช้ต้นแบบแบบเร็วๆ
- ติดตั้งใช้งานวิธีแก้ปัญหา
อย่าลืมพิจารณาประมาณการข้อเสียของวิธีแก้ปัญหาด้วย เช่น หากคุณจะใช้โครงสร้างข้อมูลเพิ่มเติม คุณยินดีที่จะใช้หน่วยความจำเท่าใด
เจาะลึก
มาดูการเปลี่ยนแปลงบางอย่างที่เราได้ติดตั้งใช้งานกันเลย
เราได้ติดตั้งใช้งานการเปลี่ยนแปลงเพื่อเพิ่มประสิทธิภาพเมธอดที่ชื่อว่า FindReferenceInfoOf เมธอดนี้ทำการค้นหาแบบเชิงเส้นของเวกเตอร์เพื่อค้นหารายการ เราได้อัปเดตโครงสร้างข้อมูลนั้นให้มีการจัดทำดัชนีตามรหัสของคำสั่ง เพื่อให้ FindReferenceInfoOf เป็น O(1) แทนที่จะเป็น O(n) นอกจากนี้ เรายังได้จัดสรรเวกเตอร์ไว้ล่วงหน้าเพื่อหลีกเลี่ยงการปรับขนาด เราได้เพิ่มหน่วยความจำเล็กน้อยเนื่องจากต้องเพิ่มฟิลด์พิเศษที่นับจำนวนรายการที่เราแทรกลงในเวกเตอร์ แต่ก็เป็นการเสียสละเพียงเล็กน้อยเนื่องจากหน่วยความจำสูงสุดไม่ได้เพิ่มขึ้น การดำเนินการนี้ทำให้ระยะ LoadStoreAnalysis เร็วขึ้น 34-66% ซึ่งจะช่วยปรับปรุงเวลาคอมไพล์ได้ประมาณ 0.5-1.8%
เรามีการติดตั้งใช้งาน HashSet แบบกำหนดเองที่เราใช้ในหลายๆ ที่ การสร้างโครงสร้างข้อมูลนี้ใช้เวลานานพอสมควร และเราได้ทราบเหตุผลแล้ว เมื่อหลายปีก่อน โครงสร้างข้อมูลนี้ใช้ในไม่กี่ที่เท่านั้นที่ใช้ HashSets ขนาดใหญ่มาก และมีการปรับแต่งเพื่อเพิ่มประสิทธิภาพสำหรับกรณีนั้น อย่างไรก็ตาม ปัจจุบันมีการใช้ในทางตรงกันข้าม โดยมีรายการเพียงไม่กี่รายการและมีอายุการใช้งานสั้น ซึ่งหมายความว่าเราเสียรอบการทำงานไปกับการสร้าง HashSet ขนาดใหญ่ แต่ใช้เพียงไม่กี่รายการก่อนที่จะทิ้ง ด้วยการเปลี่ยนแปลงนี้ เราปรับปรุงเวลาคอมไพล์ได้ประมาณ 1.3-2% นอกจากนี้ การใช้งานหน่วยความจำยังลดลงประมาณ 0.5-1% เนื่องจากเราไม่ได้ใช้โครงสร้างข้อมูลขนาดใหญ่เท่าเมื่อก่อน
เราได้ปรับปรุงเวลาคอมไพล์ได้ประมาณ 0.5-1% โดยส่งโครงสร้างข้อมูลตามการอ้างอิงไปยัง Lambda เพื่อหลีกเลี่ยงการคัดลอกโครงสร้างข้อมูล การดำเนินการนี้เป็นสิ่งที่ถูกมองข้ามไปในการตรวจสอบครั้งแรกและอยู่ในฐานโค้ดของเรามาหลายปี เราสังเกตเห็นว่าเมธอดเหล่านี้สร้างและทำลายโครงสร้างข้อมูลจำนวนมากจากการดูโปรไฟล์ใน pprof ซึ่งนำไปสู่การตรวจสอบและเพิ่มประสิทธิภาพเมธอดเหล่านั้น
เราได้เพิ่มความเร็วในระยะที่เขียนเอาต์พุตที่คอมไพล์แล้วโดยการแคชค่าที่คำนวณแล้ว ซึ่งช่วยปรับปรุงเวลาคอมไพล์ทั้งหมดได้ประมาณ 1.3-2.8% น่าเสียดายที่การบันทึกเพิ่มเติมมากเกินไปและการทดสอบอัตโนมัติของเราได้แจ้งเตือนเราถึงการถดถอยของหน่วยความจำ ต่อมา เราได้ดูโค้ดเดียวกันอีกครั้งและติดตั้งใช้งานเวอร์ชันใหม่ที่ไม่เพียงแต่จัดการกับการถดถอยของหน่วยความจำเท่านั้น แต่ยังปรับปรุงเวลาคอมไพล์ได้อีกประมาณ 0.5-1.8%! ในการเปลี่ยนแปลงครั้งที่ 2 นี้ เราต้องปรับโครงสร้างและจินตนาการใหม่ว่าระยะนี้ควรทำงานอย่างไร เพื่อกำจัดโครงสร้างข้อมูล 1 ใน 2 รายการ
เรามีระยะในคอมไพเลอร์ที่เพิ่มประสิทธิภาพซึ่งจะอินไลน์การเรียกใช้ฟังก์ชันเพื่อให้ได้ประสิทธิภาพที่ดีขึ้น เราใช้ทั้งฮิวริสติกก่อนที่จะทำการคำนวณใดๆ และการตรวจสอบขั้นสุดท้ายหลังจากทำงานเสร็จแล้วแต่ก่อนที่จะสรุปการอินไลน์ เพื่อเลือกเมธอดที่จะอินไลน์ หากการตรวจสอบใดๆ เหล่านั้นตรวจพบว่าการอินไลน์ไม่คุ้มค่า (เช่น จะมีการเพิ่มคำสั่งใหม่มากเกินไป) เราจะไม่ทำการอินไลน์การเรียกใช้เมธอด
เราได้ย้ายการตรวจสอบ 2 รายการจากหมวดหมู่ "การตรวจสอบขั้นสุดท้าย" ไปยังหมวดหมู่ "ฮิวริสติก" เพื่อประมาณว่าการอินไลน์จะสำเร็จหรือไม่ก่อนที่จะทำการคำนวณที่ใช้เวลานาน เนื่องจากเป็นการประมาณการ จึงอาจไม่สมบูรณ์แบบ แต่เราได้ยืนยันว่าฮิวริสติกใหม่ของเราครอบคลุม 99.9% ของสิ่งที่อินไลน์ไว้ก่อนหน้านี้โดยไม่ส่งผลต่อประสิทธิภาพ ฮิวริสติกใหม่เหล่านี้รายการหนึ่งเกี่ยวกับรีจิสเตอร์ DEX ที่จำเป็น (ปรับปรุงได้ประมาณ 0.2-1.3%) และอีกรายการหนึ่งเกี่ยวกับจำนวนคำสั่ง (ปรับปรุงได้ประมาณ 2%)
เรามีการติดตั้งใช้งาน BitVector แบบกำหนดเองที่เราใช้ในหลายๆ ที่ เราได้แทนที่คลาส BitVector ที่ปรับขนาดได้ด้วย BitVectorView ที่ง่ายกว่าสำหรับ BitVector ที่มีขนาดคงที่บางรายการ การดำเนินการนี้จะช่วยลดการอ้างอิงทางอ้อมและการตรวจสอบช่วงรันไทม์ และเพิ่มความเร็วในการสร้างออบเจ็กต์ BitVector
นอกจากนี้ คลาส BitVectorView ยังได้รับการสร้างเทมเพลตตามประเภทพื้นที่เก็บข้อมูลพื้นฐาน (แทนที่จะใช้ uint32_t เสมอเหมือน BitVector แบบเก่า) ซึ่งช่วยให้การดำเนินการบางอย่าง เช่น Union() สามารถประมวลผลบิตได้ 2 เท่าพร้อมกันในแพลตฟอร์ม 64 บิต ตัวอย่างฟังก์ชันที่ได้รับผลกระทบมีจำนวนลดลงมากกว่า 1% โดยรวมเมื่อคอมไพล์ระบบปฏิบัติการ Android การดำเนินการนี้ทำผ่านการเปลี่ยนแปลงหลายรายการ [1, 2, 3, 4, 5, 6]
หากเราพูดถึงการเพิ่มประสิทธิภาพทั้งหมดโดยละเอียด เราคงต้องอยู่ที่นี่ทั้งวัน! หากคุณสนใจการเพิ่มประสิทธิภาพเพิ่มเติม โปรดดูการเปลี่ยนแปลงอื่นๆ ที่เราได้ติดตั้งใช้งาน
- เพิ่มการบันทึก เพื่อปรับปรุงเวลาคอมไพล์ได้ประมาณ 0.6-1.6%
- คำนวณข้อมูลแบบเลซซีเพื่อหลีกเลี่ยงการวนซ้ำ หากเป็นไปได้
- ปรับโครงสร้างโค้ด เพื่อข้ามการคำนวณล่วงหน้าเมื่อจะไม่มีการใช้
- หลีกเลี่ยงการโหลดแบบเป็นห่วงโซ่ที่ขึ้นอยู่กับกันและกันเมื่อได้รับตัวจัดสรรจากที่อื่นได้ง่าย
- อีกกรณีหนึ่งของการเพิ่มการตรวจสอบเพื่อหลีกเลี่ยงงานที่ไม่จำเป็น
- หลีกเลี่ยงการแยกสาขาบ่อยๆ ตามประเภทรีจิสเตอร์ (Core/FP) ในตัวจัดสรรรีจิสเตอร์
- ตรวจสอบว่ามีการเริ่มต้นอาร์เรย์บางรายการในเวลาคอมไพล์ อย่าพึ่งพา Clang ในการดำเนินการนี้
- ล้างการวนซ้ำบางรายการ ใช้การวนซ้ำช่วงที่ Clang เพิ่มประสิทธิภาพได้ดีขึ้นเนื่องจากไม่จำเป็นต้องโหลดพอยน์เตอร์ภายในของคอนเทนเนอร์ซ้ำเนื่องจากผลข้างเคียงของการวนซ้ำ หลีกเลี่ยงการเรียกใช้ฟังก์ชันเสมือน `HInstruction::GetInputRecords()` ในการวนซ้ำผ่าน `InputAt(.)` ที่อินไลน์ไว้สำหรับอินพุตแต่ละรายการ
- หลีกเลี่ยงฟังก์ชัน Accept() สำหรับรูปแบบ Visitor โดยใช้ประโยชน์จากการเพิ่มประสิทธิภาพคอมไพเลอร์
บทสรุป
ความมุ่งมั่นของเราในการปรับปรุงความเร็วในการคอมไพล์ของ ART ได้ผลลัพธ์ที่สำคัญ ซึ่งทำให้ Android ทำงานได้ราบรื่นและมีประสิทธิภาพมากขึ้น รวมถึงช่วยยืดระยะเวลาการใช้งานแบตเตอรี่และลดความร้อนของอุปกรณ์ การระบุและติดตั้งใช้งานการเพิ่มประสิทธิภาพอย่างขยันขันแข็งแสดงให้เห็นว่าสามารถปรับปรุงเวลาคอมไพล์ได้อย่างมากโดยไม่ลดการใช้งานหน่วยความจำหรือคุณภาพของโค้ด
การเดินทางของเราเกี่ยวข้องกับการสร้างโปรไฟล์ด้วยเครื่องมือต่างๆ เช่น pprof ความเต็มใจที่จะทำซ้ำ และบางครั้งก็ต้องละทิ้งแนวทางที่ได้ผลลัพธ์น้อยกว่า ความพยายามร่วมกันของทีม ART ไม่เพียงแต่ลดเวลาคอมไพล์ลงได้เป็นเปอร์เซ็นต์ที่น่าทึ่งเท่านั้น แต่ยังวางรากฐานสำหรับการพัฒนาในอนาคตด้วย
การปรับปรุงทั้งหมดนี้พร้อมใช้งานในการอัปเดต Android ช่วงสิ้นปี 2025 และสำหรับ Android 12 ขึ้นไปผ่านการอัปเดต Mainline เราหวังว่าการเจาะลึกกระบวนการเพิ่มประสิทธิภาพของเรานี้จะให้ข้อมูลเชิงลึกที่มีคุณค่าเกี่ยวกับความซับซ้อนและผลตอบแทนของวิศวกรรมคอมไพเลอร์!
-
ข่าวสารเกี่ยวกับผลิตภัณฑ์การมอบประสบการณ์การใช้งานออนไลน์ที่ปลอดภัยและการปกป้องผู้ใช้จากอันตรายเป็นสิ่งสำคัญที่สุดสำหรับ Google Play
Paul Feng • ใช้เวลาอ่าน 2 นาที -
ข่าวสารเกี่ยวกับผลิตภัณฑ์วันนี้เราจะฉลองครบรอบ 5 ปีอย่างเป็นทางการนับตั้งแต่เปิดตัว Jetpack Compose 1.0 ตั้งแต่เวอร์ชัน 1.0 ที่ประกาศเมื่อวันที่ 28 กรกฎาคม 2021 ไปจนถึงเวอร์ชันล่าสุด 1.11 เราได้เห็น API พัฒนาไปอย่างมากในช่วงหลายปีที่ผ่านมา และเราขอใช้โอกาสนี้ฉลองความสำเร็จ
Rebecca Franks, Nick Butcher, Loryn Hairston • ใช้เวลาอ่าน 5 นาที -
ข่าวสารเกี่ยวกับผลิตภัณฑ์Android Studio Quail 2 พร้อมใช้งานแล้วและพร้อมให้คุณใช้ในเวอร์ชันที่ใช้งานจริง ซึ่งจะเปลี่ยน IDE ของคุณด้วยเวิร์กโฟลว์แบบ Agent ที่ทำงานพร้อมกัน การสร้างโปรไฟล์หน่วยความจำรั่วไหลที่ผสานรวมไว้ในตัว และการแก้ไขข้อขัดข้องที่เกิดขึ้นโดยพิจารณาจากบริบท
Amman Asfaw • ใช้เวลาอ่าน 3 นาที
รับข้อมูลเชิงลึกล่าสุดเกี่ยวกับการพัฒนา Android ส่งตรงถึงกล่องจดหมายของคุณ ทุกสัปดาห์