เมื่อเธรด UI ของแอป Android ถูกบล็อกนานเกินไป ระบบจะทริกเกอร์ข้อผิดพลาด "แอปพลิเคชันไม่ตอบสนอง" (ANR) Android Vitals จะติดตามและรายงานเมตริก ANR ใน Google Play Console เพื่อช่วยคุณตรวจสอบความเสถียรและการตอบสนองของแอปในอุปกรณ์ต่างๆ
เมตริกและเกณฑ์ของ Android Vitals
Android Vitals ช่วยให้คุณตรวจสอบและปรับปรุงอัตรา ANR ของแอปได้ Android Vitals จะวัดอัตรา ANR หลายรายการ ดังนี้
- อัตรา ANR: เปอร์เซ็นต์ของผู้ใช้ที่ใช้งานอยู่รายวันที่พบ ANR ประเภทใดก็ตาม
- อัตรา ANR ที่ผู้ใช้รับรู้: เปอร์เซ็นต์ของผู้ใช้ที่ใช้งานอยู่รายวันที่พบ ANR ที่ผู้ใช้รับรู้อย่างน้อย 1 ครั้ง ปัจจุบันระบบจะพิจารณาเฉพาะ ANR ประเภท
Input dispatching timed outว่าเป็น ANR ที่ผู้ใช้รับรู้ - อัตรา ANR หลายครั้ง: เปอร์เซ็นต์ของผู้ใช้ที่ใช้งานอยู่รายวันที่พบ ANR อย่างน้อย 2 ครั้ง
ผู้ใช้ที่ใช้งานอยู่รายวันคือผู้ใช้ที่ไม่ซ้ำซึ่งใช้แอปของคุณใน 1 วันบนอุปกรณ์ 1 เครื่อง โดยอาจใช้หลายเซสชัน หากผู้ใช้ใช้แอปของคุณบนอุปกรณ์มากกว่า 1 เครื่องใน 1 วัน อุปกรณ์แต่ละเครื่องจะนับเป็นจำนวนผู้ใช้ที่ใช้งานอยู่ของวันนั้นๆ
อัตรา ANR ที่ผู้ใช้รับรู้เป็น Vitals หลัก ซึ่งหมายความว่าเมตริกนี้ส่งผลกระทบต่อการค้นพบได้ของแอปคุณใน Google Play และมีความสำคัญเนื่องจาก ANR ที่เมตริกนี้นับอาจเกิดขึ้นทุกครั้งที่ผู้ใช้มีส่วนร่วมกับแอป ซึ่งทำให้เกิดการหยุดชะงักมากที่สุด
Play กำหนดเกณฑ์ลักษณะการทำงานที่ไม่ถูกต้องไว้ 2 เกณฑ์ในเมตริกนี้ ได้แก่
- เกณฑ์ลักษณะการทำงานที่ไม่ถูกต้องโดยรวม: ผู้ใช้ที่ใช้งานอยู่รายวันอย่างน้อย 0.47% พบ ANR ที่ผู้ใช้รับรู้ในอุปกรณ์ทุกรุ่น
- เกณฑ์ลักษณะการทำงานที่ไม่ถูกต้องในแต่ละอุปกรณ์: ผู้ใช้รายวันอย่างน้อย 8% พบ ANR ที่ผู้ใช้รับรู้ในอุปกรณ์รุ่นใดรุ่นหนึ่ง
หากแอปของคุณเกินเกณฑ์ลักษณะการทำงานที่ไม่ถูกต้องโดยรวม ก็มีแนวโน้มที่จะค้นพบได้น้อยลงในทุกอุปกรณ์ หากแอปของคุณทํางานเกินเกณฑ์ลักษณะการทํางานที่ไม่ถูกต้องต่ออุปกรณ์ในอุปกรณ์บางเครื่อง ก็มีแนวโน้มที่จะค้นพบได้น้อยลงในอุปกรณ์เหล่านั้น และอาจมีคําเตือนแสดงในข้อมูลสินค้าใน Store ของคุณ
Android Vitals จะแจ้งเตือนคุณผ่าน Play Console เมื่อแอปมี ANR มากเกินไป
ดูข้อมูลเกี่ยวกับวิธีที่ Google Play รวบรวมข้อมูล Android Vitals ได้ในเอกสารประกอบของ Play Console
ตรวจหาปัญหา
หากแอปอยู่ในเบื้องหน้าเมื่อเกิด ANR ระบบจะแสดงกล่องโต้ตอบแก่ผู้ใช้ ดังที่แสดงในรูปที่ 1 กล่องโต้ตอบ ANR จะให้โอกาสผู้ใช้ในการบังคับปิดแอป
ANR เป็นปัญหาเนื่องจากชุดข้อความหลักของแอปซึ่งมีหน้าที่อัปเดต UI ไม่สามารถประมวลผลเหตุการณ์การป้อนข้อมูลของผู้ใช้หรือวาดภาพได้ ซึ่งทำให้ผู้ใช้หงุดหงิด ดูข้อมูลเพิ่มเติมเกี่ยวกับเทรดหลักของแอปได้ที่ภาพรวมกระบวนการและเทรด
ระบบจะทริกเกอร์ ANR สำหรับแอปของคุณเมื่อเกิดเงื่อนไขอย่างใดอย่างหนึ่งต่อไปนี้
- การส่งอินพุตหมดเวลา: หากแอปไม่ตอบสนองต่อเหตุการณ์อินพุต (เช่น การกดแป้นหรือการแตะหน้าจอ) ภายใน 5 วินาที
- การเรียกใช้บริการ: หากบริการที่แอปของคุณประกาศไม่สามารถเรียกใช้
Service.onCreateและService.onStartCommandหรือService.onBindให้เสร็จภายในไม่กี่วินาที - ไม่ได้เรียกใช้
Service.startForeground: หากแอปใช้Context.startForegroundServiceเพื่อเริ่มบริการใหม่ในเบื้องหน้า แต่บริการไม่เรียกใช้startForegroundภายใน 5 วินาที - การประกาศ Intent: หาก
BroadcastReceiverทำงานไม่เสร็จภายในระยะเวลาที่กำหนด หากแอปมีกิจกรรมที่ทำงานอยู่เบื้องหน้า ระยะหมดเวลานี้จะเท่ากับ 10 วินาที - การโต้ตอบกับ
JobScheduler: หากJobServiceไม่แสดงผลจากJobService.onStartJobหรือJobService.onStopJobภายในไม่กี่วินาที หรือหากงานที่ผู้ใช้เริ่มเริ่มต้นขึ้นและแอปของคุณไม่เรียกใช้JobService.setNotificationภายในไม่กี่วินาทีหลังจากที่มีการเรียกใช้JobService.onStartJobสำหรับแอปที่กำหนดเป้าหมายเป็น Android 13 และต่ำกว่า ANR จะเกิดขึ้นโดยไม่มีการแจ้งเตือนและไม่มีการรายงานไปยังแอป สำหรับแอปที่กำหนดเป้าหมายเป็น Android 14 ขึ้นไป ANR จะเกิดขึ้นอย่างชัดเจนและมีการรายงานไปยังแอป
นอกจาก Android Vitals แล้ว คุณยังใช้เครื่องมืออื่นๆ เพื่อตรวจหา ANR ในภาคสนามได้ด้วย แม้ว่าเครื่องมือของบุคคลที่สามจะรายงาน ANR ใน Android 10 (ระดับ API 29) และต่ำกว่าไม่ได้ก็ตาม
วิเคราะห์ ANR
รูปแบบที่พบได้ทั่วไปซึ่งควรระวังเมื่อวินิจฉัย ANR มีดังนี้
- แอปกำลังดำเนินการที่ช้าซึ่งเกี่ยวข้องกับ I/O ในเทรดหลัก
- แอปกำลังทำการคำนวณที่ใช้เวลานานในชุดข้อความหลัก
- เทรดหลักกำลังเรียกใช้ Binder แบบซิงโครนัสไปยังกระบวนการอื่น และกระบวนการอื่นนั้นใช้เวลานานในการแสดงผล
- เทรดหลักถูกบล็อกเนื่องจากรอการบล็อกที่ซิงค์สำหรับการดำเนินการที่ใช้เวลานานซึ่งเกิดขึ้นในเทรดอื่น
- เทรดหลักอยู่ในภาวะติดตายกับเทรดอื่น ไม่ว่าจะในกระบวนการของคุณหรือผ่านการเรียก Binder เทรดหลักไม่ได้แค่รอให้การดำเนินการที่ใช้เวลานานเสร็จสิ้น แต่ยังอยู่ในสถานการณ์เดดล็อกด้วย
เทคนิคต่อไปนี้จะช่วยคุณระบุสาเหตุของ ANR ได้
HealthStats
HealthStats แสดงเมตริกเกี่ยวกับประสิทธิภาพของแอปพลิเคชันโดยการบันทึกเวลาทั้งหมดของผู้ใช้และระบบ, เวลา CPU, เครือข่าย, สถิติวิทยุ, เวลาเปิดและปิดหน้าจอ รวมถึงการปลุกให้ตื่น ซึ่งจะช่วยให้คุณวัดการใช้งาน CPU โดยรวมและการใช้แบตเตอรี่ได้
แก้ไขข้อบกพร่อง
Debug ช่วยคุณตรวจสอบแอปพลิเคชัน Android ในระหว่างการพัฒนา รวมถึงการติดตามและจำนวนการจัดสรรเพื่อระบุอาการกระตุกและแล็กในแอป
นอกจากนี้ คุณยังใช้ Debug เพื่อดูตัวนับหน่วยความจำรันไทม์และหน่วยความจำเนทีฟ รวมถึงเมตริกหน่วยความจำที่ช่วยระบุหน่วยความจำที่ใช้ของกระบวนการหนึ่งๆ ได้ด้วย
ApplicationExitInfo
ApplicationExitInfo พร้อมใช้งานใน Android 11 (ระดับ API 30) ขึ้นไป และให้ข้อมูลเกี่ยวกับสาเหตุที่แอปพลิเคชันออก ซึ่งรวมถึง ANR, หน่วยความจำเหลือน้อย, แอปขัดข้อง, การใช้งาน CPU มากเกินไป, การรบกวนผู้ใช้, การรบกวนระบบ และการเปลี่ยนแปลงสิทธิ์รันไทม์
โหมดจำกัด
การใช้ StrictMode ช่วยให้คุณค้นหาการดำเนินการ I/O โดยไม่ตั้งใจในเทรดหลักขณะพัฒนาแอป คุณสามารถใช้ StrictMode ที่ระดับแอปพลิเคชันหรือกิจกรรมได้
เปิดใช้กล่องโต้ตอบ ANR ในเบื้องหลัง
Android จะแสดงกล่องโต้ตอบ ANR สำหรับแอปที่ใช้เวลานานเกินไปในการประมวลผลข้อความประกาศก็ต่อเมื่อเปิดใช้แสดง ANR ทั้งหมดในตัวเลือกสำหรับนักพัฒนาแอปของอุปกรณ์ ด้วยเหตุนี้ กล่องโต้ตอบ ANR ในเบื้องหลังจึงไม่แสดงต่อผู้ใช้เสมอไป แม้ว่าแอปจะประสบปัญหาด้านประสิทธิภาพก็ตาม
โปรไฟล์ CPU และการติดตามของระบบ
ใช้เครื่องมือสร้างโปรไฟล์ CPU ของ Android Studio เพื่อบันทึกการติดตามของระบบและกิจกรรม CPU ขณะที่เกมทำงาน การตรวจสอบเทรด Activity หลักควบคู่ไปกับเทรดการแสดงผล เสียง และเทรดผู้ปฏิบัติงานของเกมเอนจินจะช่วยให้คุณตรวจพบเฟรมที่ยาว การโหลดเนื้อหาแบบซิงโครนัส และการแย่งชิงเทรดก่อนที่จะทำให้เกิด ANR
ดึงไฟล์การติดตาม
Android จะจัดเก็บข้อมูลการติดตามเมื่อพบ ANR ใน Android เวอร์ชันที่ต่ำกว่า จะมีไฟล์ /data/anr/traces.txt เพียงไฟล์เดียวในอุปกรณ์ ใน Android เวอร์ชันที่สูงกว่า จะมีไฟล์ /data/anr/anr_* หลายไฟล์ คุณเข้าถึงการติดตาม ANR จากอุปกรณ์หรือโปรแกรมจำลองได้โดยใช้ Android Debug Bridge (adb) เป็นรูท ดังนี้
adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>
คุณสามารถบันทึกรายงานข้อบกพร่องจากอุปกรณ์จริงได้โดยใช้ตัวเลือกสำหรับนักพัฒนาแอป "ใช้รายงานข้อบกพร่อง" ในอุปกรณ์หรือคำสั่ง adb bugreport ในคอมพิวเตอร์สำหรับการพัฒนาซอฟต์แวร์ ดูข้อมูลเพิ่มเติมได้ที่บันทึกและอ่านรายงานข้อบกพร่อง
แก้ไขปัญหา
หลังจากระบุปัญหาแล้ว คุณสามารถใช้เคล็ดลับในส่วนนี้เพื่อแก้ไขปัญหาที่พบได้ทั่วไป
โค้ดที่ทำงานช้าในเทรดหลัก
ระบุตำแหน่งในโค้ดที่เทรดหลักของแอปไม่ว่างนานกว่า 5 วินาที มองหา Use Case ที่น่าสงสัยในเกมและพยายามจำลอง ANR
ในเกม การหยุดชะงักของเธรดหลักมักเกิดขึ้นเมื่อการคลายการบีบอัดเนื้อหาแบบซิงโครนัส การคอมไพล์ตัวปรับเฉดสี หรือการเริ่มต้นสถานะเกมที่หนักหน่วงทำงานในเธรด Activity หลักของ Android (เช่น ภายใน onCreate, onResume หรือ Callback ของ JNI ที่เรียกใช้จากเธรด UI) ย้ายการดำเนินการ Game Loop, การประมวลผลเนื้อหา และการเริ่มต้นฉากไปยังเทรดเครื่องมือ เทรดการแสดงผล หรือเทรดผู้ปฏิบัติงานในเบื้องหลังโดยเฉพาะ เพื่อให้เทรดหลักยังคงว่างสำหรับการประมวลผลอินพุตและเหตุการณ์ในวงจร
I/O ในเทรดหลัก
การดําเนินการ I/O ในเทรดหลักเป็นสาเหตุที่พบบ่อยของการทํางานที่ช้าในเทรดหลัก ซึ่งอาจทําให้เกิด ANR
ย้ายการอ่าน Asset Bundle, การจัดลำดับเกมที่บันทึกไว้, SharedPreferences
การเข้าถึง และคำขอเครือข่ายทั้งหมดออกจากเทรด Activity หลักไปยังเทรดผู้ปฏิบัติงานในเบื้องหลัง
เพื่อให้เวลาในการตอบสนองของพื้นที่เก็บข้อมูลหรือเครือข่ายไม่บล็อกการส่งอินพุต
Deadlock
เดดล็อกจะเกิดขึ้นเมื่อเทรดเข้าสู่สถานะรอเนื่องจากเทรดอื่นใช้ทรัพยากรที่จำเป็นอยู่ ซึ่งเทรดนั้นก็กำลังรอทรัพยากรที่เทรดแรกใช้เช่นกัน หากเทรดหลักของแอปอยู่ในสถานการณ์นี้ ก็มีแนวโน้มที่จะเกิด ANR
ในเกม ภาวะติดตายและการแย่งชิงล็อกมักเกิดขึ้นระหว่างเทรด Activity หลักของ Android (จัดการวงจร, Surface หรือ Callback ของอินพุต) กับเทรดการแสดงผล ตรรกะ หรือเสียงของ C หรือ C++ แบบเนทีฟ หลีกเลี่ยงการรอแบบซิงโครนัสในเทรดหลักสำหรับการล็อกเอนจินแบบเนทีฟ และใช้การจัดลำดับการล็อกที่สอดคล้องกันหรือคิวข้อความที่ไม่มีการล็อกเมื่อสื่อสารผ่าน JNI และเทรดเอนจิน
ภาวะติดตายเป็นปรากฏการณ์ที่ได้รับการศึกษาอย่างดีในด้านวิทยาการคอมพิวเตอร์ และมีอัลกอริทึมการป้องกันภาวะติดตายที่คุณสามารถใช้เพื่อหลีกเลี่ยงภาวะติดตายได้
ดูข้อมูลเพิ่มเติมได้ที่ภาวะติดตายและอัลกอริทึมการป้องกันภาวะติดตายใน Wikipedia
Broadcast Receiver ที่ทำงานช้า
แอปสามารถตอบสนองต่อข้อความประกาศ เช่น การเปิดหรือปิดใช้โหมดบนเครื่องบินหรือการเปลี่ยนแปลงสถานะการเชื่อมต่อ โดยใช้ Broadcast Receiver ANR จะเกิดขึ้นเมื่อแอปใช้เวลานานเกินไปในการประมวลผลข้อความประกาศ
ANR จะเกิดขึ้นในกรณีต่อไปนี้
- Broadcast Receiver ยังดำเนินการตามเมธอด
onReceiveไม่เสร็จภายในระยะเวลาที่เหมาะสม - Broadcast Receiver เรียกใช้
goAsyncและเรียกใช้finishในออบเจ็กต์PendingResultไม่สำเร็จ
แอปควรดำเนินการสั้นๆ ในเมธอด onReceive ของ BroadcastReceiver เท่านั้น อย่างไรก็ตาม หากแอปของคุณต้องการการประมวลผลที่ซับซ้อนมากขึ้นอันเป็นผลมาจากข้อความประกาศ คุณควรเลื่อนงานไปยังเทรดผู้ปฏิบัติงานในเบื้องหลังหากคาดว่างานจะใช้เวลาไม่เกิน 2-3 วินาที หรือเลื่อนไปยัง WorkManager สำหรับงานที่คาดว่าจะใช้เวลานานกว่า 2-3 วินาที
GameActivity
ไลบรารี GameActivity ช่วยลด ANR ในกรณีศึกษาของเกมและแอปที่เขียนด้วย C หรือ C++ หากคุณแทนที่กิจกรรมแบบเนทีฟที่มีอยู่ด้วย GameActivity คุณจะลดการบล็อกเธรด UI และป้องกันไม่ให้เกิด ANR บางรายการได้
หากคุณสร้างเกมด้วย Unity โปรดดูแก้ไขข้อบกพร่อง ANR สำหรับเกม Unity, ANR ที่พบบ่อยในเกม Unity และสร้างสัญลักษณ์สำหรับข้อขัดข้องของ Android และ ANR สำหรับเกม Unity
ดูข้อมูลเพิ่มเติมเกี่ยวกับ ANR ได้ที่ทำให้แอปตอบสนองอยู่เสมอ ดูข้อมูลเพิ่มเติมเกี่ยวกับชุดข้อความได้ที่ประสิทธิภาพที่ดีขึ้นผ่านชุดข้อความ
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- การปลุกระบบบ่อยเกินไป