Bitmap thường là các đối tượng tiêu tốn nhiều bộ nhớ nhất trong một ứng dụng. Các thao tác giải mã và chia tỷ lệ thường nằm trên đường dẫn quan trọng để kết xuất khung hình. Việc tối ưu hoá mức sử dụng bộ nhớ bitmap giúp cải thiện đáng kể khả năng phản hồi của giao diện người dùng, thời lượng pin và độ ổn định tổng thể bằng cách giảm hiện tượng giật, lỗi ANR và các quy trình bị huỷ do hết bộ nhớ.
Xác định mức sử dụng bộ nhớ bitmap cao
Android vitals cung cấp các chỉ số về mức sử dụng bộ nhớ bitmap của ứng dụng bằng cách tổng hợp dữ liệu từ các thiết bị Android. Các chỉ số này bao gồm các phân vị theo khoảng thời gian (ví dụ: 28 ngày) cho mỗi gói và quy trình. Dữ liệu này giúp xác định các xu hướng và khả năng giảm hiệu suất bộ nhớ trên nhiều loại và phiên bản thiết bị.
Android vitals chia sẻ mức sử dụng bộ nhớ bitmap của ứng dụng theo các trạng thái quy trình sau:
- Nền trước: Tiến trình của ứng dụng hiển thị. P99 dự kiến sẽ cao hơn đáng kể ở nền trước so với các trạng thái quy trình khác, nhưng nhà phát triển nên điều tra nếu tỷ lệ P99/P50 đáng kể (ví dụ: cao hơn 3,5 lần), vì điều này thường cho thấy tình trạng rò rỉ bộ nhớ bitmap. Bạn có thể xác định điều này bằng cách tìm sự khác biệt giữa mức sử dụng thông thường (P50) và mức sử dụng bất thường (P99); trong khi tình trạng phình to tài sản chung làm tăng bộ nhớ một cách đồng đều trên tất cả các phân vị, thì tình trạng rò rỉ bộ nhớ sẽ tăng lên theo thời gian, làm sai lệch đáng kể dữ liệu ở phần cuối (P99). Đảm bảo rằng các hoạt động phân bổ bitmap trên nền trước không duy trì một cách không cần thiết sau khi ứng dụng chuyển sang các trạng thái khác.
- Dịch vụ mà người dùng nhận biết được: Quy trình của ứng dụng đang chạy ở trạng thái nhận biết được. Trong đó có dịch vụ trên nền trước, các tác vụ được tăng tốc và các tác vụ chuyển dữ liệu do người dùng yêu cầu. Ứng dụng không được giữ lại các hoạt động phân bổ bitmap nền trước có kích thước lớn khi chuyển sang các trạng thái này. Vì các dịch vụ này được thiết kế cho các tác vụ chạy trong thời gian dài, nên việc giữ lại các thành phần lớn sẽ làm giảm trải nghiệm người dùng tổng thể và buộc Trình nền Low Memory Killer (LMKD) thu hồi bộ nhớ bằng cách chấm dứt các quy trình có mức độ ưu tiên thấp hơn.
- Nền: Ứng dụng đang chạy một dịch vụ nền hoặc gần đây đã chuyển sang nền nhưng chưa được lưu vào bộ nhớ đệm. Vì trạng thái quy trình này ít quan trọng hơn các quy trình ở nền trước hoặc có thể nhận thấy, nên các ứng dụng phải giải phóng rõ ràng các thành phần bitmap lớn tại đây để giảm áp lực về bộ nhớ.
- Đã lưu vào bộ nhớ đệm: Ứng dụng đang ở trạng thái lưu vào bộ nhớ đệm. Trạng thái này rất nhạy cảm với áp lực bộ nhớ hệ thống, chẳng hạn như LMK. Các ứng dụng phải chủ động giảm mức sử dụng bộ nhớ bitmap ở trạng thái này để tránh bị hệ điều hành loại bỏ.
Các yếu tố góp phần làm tăng mức sử dụng bộ nhớ bitmap
Bộ nhớ ảo chưa từng được sử dụng cũng có thể được đưa vào tính toán. Nếu bạn thấy mức sử dụng bộ nhớ bitmap cao bất thường, hãy xác minh rằng bạn không phân bổ bộ nhớ không dùng đến.
Tài nguyên
Phân tích bitmap trong Android Studio
Phân tích hiệu suất trong Android Studio cho bitmap
Sử dụng Trình phân tích bộ nhớ để kiểm tra mức phân bổ bộ nhớ theo thời gian thực, thu thập tệp báo lỗi và phân tích các đối tượng để tìm tình trạng rò rỉ bộ nhớ; ngoài ra, hãy sử dụng trình phân tích vùng nhớ khối xếp để phát hiện tình trạng rò rỉ bộ nhớ, xác định các mức phân bổ bitmap trùng lặp và trực quan hoá việc giữ lại đối tượng.
Tự động phát hiện rò rỉ bằng LeakCanary
Tích hợp thư viện LeakCanary để tự động phát hiện tình trạng rò rỉ bộ nhớ trong ứng dụng của bạn. LeakCanary cung cấp tính năng phân tích heap tự động, xác định các đối tượng lẽ ra phải được thu gom rác nhưng vẫn được giữ lại trong bộ nhớ, chẳng hạn như các bitmap do các Activity hoặc Fragment đã bị huỷ giữ lại.
Tài liệu về hiệu suất bitmap
Những tài nguyên này cung cấp hướng dẫn toàn diện về các phương pháp hay nhất để xử lý bitmap hiệu quả trên nhiều thành phần Android.
Danh sách kiểm tra dành cho nhà phát triển để tối ưu hoá mức sử dụng bộ nhớ bitmap
Để tối ưu hoá hiệu quả bộ nhớ bitmap, hãy tuân theo 3 nguyên tắc cốt lõi: giảm, sử dụng lại và tái chế.
- Giảm: Giảm thiểu mức sử dụng bộ nhớ ban đầu khi tải hoặc hiển thị bitmap.
- Sử dụng lại: Triển khai cơ chế lưu vào bộ nhớ đệm để tránh việc phân bổ bitmap dư thừa.
- Recycle (Tái chế): Chủ động giải phóng tài nguyên để cho phép phân bổ lại bộ nhớ cho các quy trình đang hoạt động.
Danh sách kiểm tra sau đây dành cho nhà phát triển có thể giúp bạn tối ưu hoá mức sử dụng bộ nhớ bitmap.
| Nguyên tắc cốt lõi | Khu vực | Mô tả |
|---|---|---|
| Giảm | Loại bỏ các bitmap trùng lặp | Phân tích kết xuất vùng nhớ khối xếp bằng Trình phân tích bộ nhớ để phát hiện các hoạt động phân bổ bitmap dư thừa. Tham khảo hướng dẫn Quản lý bộ nhớ bitmap. |
| Tận dụng các thư viện tải hình ảnh | Sử dụng các thư viện như Glide và Coil để tự động hoá việc tạo luồng, lưu vào bộ nhớ đệm và giải mã hiệu quả. | |
| Triển khai tính năng giảm mẫu | Giải mã hình ảnh để khớp với kích thước vùng chứa giao diện người dùng mục tiêu thay vì tải thành phần có độ phân giải đầy đủ. | |
| Sử dụng RGB_565 cho hình ảnh mờ | Giảm mức sử dụng bộ nhớ xuống 50% bằng cách chuyển từ ARGB_8888 sang cấu hình 16 bit cho những hình ảnh không có độ trong suốt. |
|
| Ưu tiên VectorDrawable | Sử dụng các vectơ cho biểu tượng và đồ hoạ cơ bản để đảm bảo việc mở rộng sắc nét với mức sử dụng bộ nhớ tối thiểu. | |
| Tối ưu hoá việc phân phối hình ảnh phía máy chủ | Định cấu hình API phụ trợ để phân phát hình ảnh phù hợp với mật độ thiết bị và kích thước ImageView. | |
| Loại bỏ lề trong suốt | Tránh phân bổ bộ nhớ cho các pixel "vô hình" bằng cách sử dụng InsetDrawable hoặc khoảng đệm bố cục thay vì các lề được tích hợp sẵn. Xem bài viết Thiết kế các ứng dụng Android có hiệu suất bộ nhớ cao. | |
| Sử dụng lại | Định cấu hình kích thước bộ nhớ đệm tối ưu | Điều chỉnh giới hạn bộ nhớ và bộ nhớ đệm của ổ đĩa dựa trên RAM và độ phân giải màn hình của thiết bị. Tham khảo bài viết Lưu các bitmap vào bộ nhớ đệm. |
| Tái chế | Xoá tài nguyên hoàn toàn ở chế độ nền | Triển khai TRIM_MEMORY_BACKGROUND để xoá bộ nhớ đệm và cải thiện khả năng duy trì quy trình trong quá trình hệ thống chịu áp lực về bộ nhớ. |
| Phát hành tài sản khi giao diện người dùng bị ẩn | Sử dụng TRIM_MEMORY_UI_HIDDEN để phát hành bộ nhớ đệm bitmap khi người dùng không còn thấy ứng dụng nữa. |
|
| Theo dõi tình trạng rò rỉ bộ nhớ | Sử dụng LeakCanary và Trình phân tích bộ nhớ để tìm các cấu trúc bitmap được giữ lại sau khi LifecycleOwner bị huỷ. Hãy tham khảo bài viết Quản lý bộ nhớ của ứng dụng. |